mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 11:39:22 +00:00
feat: Add UI signifying the currently selected wallet indicator (#1704)
* feat: Add UI signifying the currently selected wallet indicator * fix: Product Fix - Add more padding to child wallets list item tile in grouped wallets, fix sort by dragging for general single wallets, and also groups, add animation to trailing arrow icon when tile is expanded or not * Update wallet group image and change maxLines --------- Co-authored-by: tuxpizza <tuxsudo@tux.pizza>
This commit is contained in:
parent
791b410277
commit
b2850c203f
10 changed files with 144 additions and 26 deletions
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB |
BIN
assets/images/wallet_group_bright.png
Normal file
BIN
assets/images/wallet_group_bright.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
assets/images/wallet_group_dark.png
Normal file
BIN
assets/images/wallet_group_dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
BIN
assets/images/wallet_group_light.png
Normal file
BIN
assets/images/wallet_group_light.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7 KiB |
|
@ -3,10 +3,11 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
|
|||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class WalletGroupDescriptionPage extends BasePage {
|
||||
WalletGroupDescriptionPage({required this.selectedWalletType});
|
||||
|
@ -16,17 +17,25 @@ class WalletGroupDescriptionPage extends BasePage {
|
|||
@override
|
||||
String get title => S.current.wallet_group;
|
||||
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
|
||||
final lightImage = 'assets/images/wallet_group_light.png';
|
||||
final darkImage = 'assets/images/wallet_group_dark.png';
|
||||
final brightImage = 'assets/images/wallet_group_bright.png';
|
||||
|
||||
final image = currentTheme.type == ThemeType.light ? lightImage : darkImage;
|
||||
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Column(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/wallet_group.png',
|
||||
scale: 0.8,
|
||||
),
|
||||
Image.asset(
|
||||
image,
|
||||
height: 200
|
||||
),
|
||||
SizedBox(height: 32),
|
||||
Expanded(
|
||||
child: Text.rich(
|
||||
|
|
|
@ -58,6 +58,7 @@ class WalletGroupsDisplayBody extends StatelessWidget {
|
|||
final groupName =
|
||||
group.groupName ?? '${S.of(context).wallet_group} ${index + 1}';
|
||||
return GroupedWalletExpansionTile(
|
||||
shouldShowCurrentWalletPointer: false,
|
||||
leadingWidget:
|
||||
Icon(Icons.account_balance_wallet_outlined, size: 28),
|
||||
borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||
|
|
|
@ -12,6 +12,7 @@ class GroupedWalletExpansionTile extends StatelessWidget {
|
|||
this.childWallets = const [],
|
||||
this.onTitleTapped,
|
||||
this.onChildItemTapped = _defaultVoidCallback,
|
||||
this.onExpansionChanged,
|
||||
this.leadingWidget,
|
||||
this.trailingWidget,
|
||||
this.childTrailingWidget,
|
||||
|
@ -22,13 +23,18 @@ class GroupedWalletExpansionTile extends StatelessWidget {
|
|||
this.borderRadius,
|
||||
this.margin,
|
||||
this.tileKey,
|
||||
this.isCurrentlySelectedWallet = false,
|
||||
this.shouldShowCurrentWalletPointer = false,
|
||||
}) : super(key: tileKey);
|
||||
|
||||
final Key? tileKey;
|
||||
final bool isSelected;
|
||||
final bool isCurrentlySelectedWallet;
|
||||
final bool shouldShowCurrentWalletPointer;
|
||||
|
||||
final VoidCallback? onTitleTapped;
|
||||
final void Function(WalletListItem item) onChildItemTapped;
|
||||
final void Function(bool)? onExpansionChanged;
|
||||
|
||||
final String title;
|
||||
final Widget? leadingWidget;
|
||||
|
@ -70,8 +76,10 @@ class GroupedWalletExpansionTile extends StatelessWidget {
|
|||
splashFactory: NoSplash.splashFactory,
|
||||
),
|
||||
child: ExpansionTile(
|
||||
onExpansionChanged: onExpansionChanged,
|
||||
key: tileKey,
|
||||
tilePadding: EdgeInsets.symmetric(vertical: 1, horizontal: 16),
|
||||
tilePadding:
|
||||
EdgeInsets.symmetric(vertical: 1, horizontal: !isCurrentlySelectedWallet ? 16 : 0),
|
||||
iconColor: effectiveArrowColor,
|
||||
collapsedIconColor: effectiveArrowColor,
|
||||
leading: leadingWidget,
|
||||
|
@ -90,19 +98,46 @@ class GroupedWalletExpansionTile extends StatelessWidget {
|
|||
),
|
||||
children: childWallets.map(
|
||||
(item) {
|
||||
final currentColor = item.isCurrent
|
||||
? Theme.of(context)
|
||||
.extension<WalletListTheme>()!
|
||||
.createNewWalletButtonBackgroundColor
|
||||
: Theme.of(context).colorScheme.background;
|
||||
final walletTypeToCrypto = walletTypeToCryptoCurrency(item.type);
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
key: ValueKey(item.name),
|
||||
trailing: childTrailingWidget?.call(item),
|
||||
onTap: () => onChildItemTapped(item),
|
||||
leading: Image.asset(
|
||||
walletTypeToCrypto.iconPath!,
|
||||
width: 32,
|
||||
height: 32,
|
||||
leading: SizedBox(
|
||||
width: 60,
|
||||
child: Row(
|
||||
children: [
|
||||
item.isCurrent && shouldShowCurrentWalletPointer
|
||||
? Container(
|
||||
height: 35,
|
||||
width: 6,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(16),
|
||||
bottomRight: Radius.circular(16),
|
||||
),
|
||||
color: currentColor,
|
||||
),
|
||||
)
|
||||
: SizedBox(width: 6),
|
||||
SizedBox(width: 16),
|
||||
Image.asset(
|
||||
walletTypeToCrypto.iconPath!,
|
||||
width: 32,
|
||||
height: 32,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
item.name,
|
||||
maxLines: 1,
|
||||
maxLines: 2,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
|
|
|
@ -7,11 +7,13 @@ class EditWalletButtonWidget extends StatelessWidget {
|
|||
required this.width,
|
||||
required this.onTap,
|
||||
this.isGroup = false,
|
||||
this.isExpanded = false,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final bool isGroup;
|
||||
final double width;
|
||||
final bool isExpanded;
|
||||
final VoidCallback onTap;
|
||||
|
||||
@override
|
||||
|
@ -42,7 +44,7 @@ class EditWalletButtonWidget extends StatelessWidget {
|
|||
if (isGroup) ...{
|
||||
SizedBox(width: 6),
|
||||
Icon(
|
||||
Icons.keyboard_arrow_down,
|
||||
isExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
|
||||
size: 24,
|
||||
color: Theme.of(context).extension<FilterTheme>()!.titlesColor,
|
||||
),
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
|||
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
|
||||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/themes/extensions/filter_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
|
@ -156,7 +157,18 @@ class WalletListBodyState extends State<WalletListBody> {
|
|||
final group = widget.walletListViewModel.multiWalletGroups[index];
|
||||
final groupName = group.groupName ??
|
||||
'${S.current.wallet_group} ${index + 1}';
|
||||
|
||||
widget.walletListViewModel.updateTileState(
|
||||
index,
|
||||
widget.walletListViewModel.expansionTileStateTrack[index] ?? false,
|
||||
);
|
||||
|
||||
return GroupedWalletExpansionTile(
|
||||
onExpansionChanged: (value) {
|
||||
widget.walletListViewModel.updateTileState(index, value);
|
||||
setState(() {});
|
||||
},
|
||||
shouldShowCurrentWalletPointer: true,
|
||||
borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||
margin: EdgeInsets.only(left: 20, right: 20, bottom: 12),
|
||||
title: groupName,
|
||||
|
@ -168,6 +180,8 @@ class WalletListBodyState extends State<WalletListBody> {
|
|||
trailingWidget: EditWalletButtonWidget(
|
||||
width: 74,
|
||||
isGroup: true,
|
||||
isExpanded:
|
||||
widget.walletListViewModel.expansionTileStateTrack[index]!,
|
||||
onTap: () {
|
||||
final wallet = widget.walletListViewModel
|
||||
.convertWalletInfoToWalletListItem(group.wallets.first);
|
||||
|
@ -193,13 +207,16 @@ class WalletListBodyState extends State<WalletListBody> {
|
|||
childTrailingWidget: (item) {
|
||||
return item.isCurrent
|
||||
? SizedBox.shrink()
|
||||
: EditWalletButtonWidget(
|
||||
width: 44,
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.walletEdit,
|
||||
arguments: WalletEditPageArguments(
|
||||
walletListViewModel: widget.walletListViewModel,
|
||||
editingWallet: item,
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(right: 16),
|
||||
child: EditWalletButtonWidget(
|
||||
width: 44,
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.walletEdit,
|
||||
arguments: WalletEditPageArguments(
|
||||
walletListViewModel: widget.walletListViewModel,
|
||||
editingWallet: item,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -232,13 +249,40 @@ class WalletListBodyState extends State<WalletListBody> {
|
|||
updateFunction: widget.walletListViewModel.reorderAccordingToWalletList,
|
||||
itemBuilder: (context, index) {
|
||||
final wallet = widget.walletListViewModel.singleWalletsList[index];
|
||||
final currentColor = wallet.isCurrent
|
||||
? Theme.of(context)
|
||||
.extension<WalletListTheme>()!
|
||||
.createNewWalletButtonBackgroundColor
|
||||
: Theme.of(context).colorScheme.background;
|
||||
|
||||
return GroupedWalletExpansionTile(
|
||||
tileKey: ValueKey('single_wallets_expansion_tile_widget_$index'),
|
||||
leadingWidget: Image.asset(
|
||||
walletTypeToCryptoCurrency(wallet.type).iconPath!,
|
||||
width: 32,
|
||||
height: 32,
|
||||
isCurrentlySelectedWallet: wallet.isCurrent,
|
||||
leadingWidget: SizedBox(
|
||||
width: 60,
|
||||
child: Row(
|
||||
children: [
|
||||
wallet.isCurrent
|
||||
? Container(
|
||||
height: 35,
|
||||
width: 6,
|
||||
margin: EdgeInsets.only(right: 16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(16),
|
||||
bottomRight: Radius.circular(16),
|
||||
),
|
||||
color: currentColor,
|
||||
),
|
||||
)
|
||||
: SizedBox(width: 6),
|
||||
Image.asset(
|
||||
walletTypeToCryptoCurrency(wallet.type).iconPath!,
|
||||
width: 32,
|
||||
height: 32,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: wallet.name,
|
||||
isSelected: false,
|
||||
|
|
|
@ -22,7 +22,8 @@ abstract class WalletListViewModelBase with Store {
|
|||
this._walletManager,
|
||||
) : wallets = ObservableList<WalletListItem>(),
|
||||
multiWalletGroups = ObservableList<WalletGroup>(),
|
||||
singleWalletsList = ObservableList<WalletListItem>() {
|
||||
singleWalletsList = ObservableList<WalletListItem>(),
|
||||
expansionTileStateTrack = ObservableMap<int, bool>() {
|
||||
setOrderType(_appStore.settingsStore.walletListOrder);
|
||||
reaction((_) => _appStore.wallet, (_) => updateList());
|
||||
updateList();
|
||||
|
@ -40,6 +41,18 @@ abstract class WalletListViewModelBase with Store {
|
|||
@observable
|
||||
ObservableList<WalletListItem> singleWalletsList;
|
||||
|
||||
@observable
|
||||
ObservableMap<int, bool> expansionTileStateTrack;
|
||||
|
||||
@action
|
||||
void updateTileState(int index, bool isExpanded) {
|
||||
if (expansionTileStateTrack.containsKey(index)) {
|
||||
expansionTileStateTrack.update(index, (value) => isExpanded);
|
||||
} else {
|
||||
expansionTileStateTrack.addEntries({index: isExpanded}.entries);
|
||||
}
|
||||
}
|
||||
|
||||
@computed
|
||||
bool get shouldRequireTOTP2FAForAccessingWallet =>
|
||||
_appStore.settingsStore.shouldRequireTOTP2FAForAccessingWallet;
|
||||
|
@ -100,8 +113,8 @@ abstract class WalletListViewModelBase with Store {
|
|||
// delete all wallets from walletInfoSource:
|
||||
await _walletInfoSource.clear();
|
||||
|
||||
// add wallets from wallets list in order of wallets list, by name:
|
||||
for (WalletListItem wallet in wallets) {
|
||||
// Reorder single wallets using the singleWalletsList
|
||||
for (WalletListItem wallet in singleWalletsList) {
|
||||
for (int i = 0; i < walletInfoSourceCopy.length; i++) {
|
||||
if (walletInfoSourceCopy[i].name == wallet.name) {
|
||||
await _walletInfoSource.add(walletInfoSourceCopy[i]);
|
||||
|
@ -111,6 +124,20 @@ abstract class WalletListViewModelBase with Store {
|
|||
}
|
||||
}
|
||||
|
||||
// Reorder wallets within multi-wallet groups
|
||||
for (WalletGroup group in multiWalletGroups) {
|
||||
for (WalletInfo walletInfo in group.wallets) {
|
||||
for (int i = 0; i < walletInfoSourceCopy.length; i++) {
|
||||
if (walletInfoSourceCopy[i].name == walletInfo.name) {
|
||||
await _walletInfoSource.add(walletInfoSourceCopy[i]);
|
||||
walletInfoSourceCopy.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild the list of wallets and groups
|
||||
updateList();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue