diff --git a/assets/images/wallet_group.png b/assets/images/wallet_group.png deleted file mode 100644 index f4a577b22..000000000 Binary files a/assets/images/wallet_group.png and /dev/null differ diff --git a/assets/images/wallet_group_bright.png b/assets/images/wallet_group_bright.png new file mode 100644 index 000000000..263361db6 Binary files /dev/null and b/assets/images/wallet_group_bright.png differ diff --git a/assets/images/wallet_group_dark.png b/assets/images/wallet_group_dark.png new file mode 100644 index 000000000..7cd08d2cd Binary files /dev/null and b/assets/images/wallet_group_dark.png differ diff --git a/assets/images/wallet_group_light.png b/assets/images/wallet_group_light.png new file mode 100644 index 000000000..7827971e7 Binary files /dev/null and b/assets/images/wallet_group_light.png differ diff --git a/lib/src/screens/new_wallet/wallet_group_description_page.dart b/lib/src/screens/new_wallet/wallet_group_description_page.dart index eb3501bed..f30ff1d6c 100644 --- a/lib/src/screens/new_wallet/wallet_group_description_page.dart +++ b/lib/src/screens/new_wallet/wallet_group_description_page.dart @@ -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( diff --git a/lib/src/screens/new_wallet/wallet_group_display_page.dart b/lib/src/screens/new_wallet/wallet_group_display_page.dart index 67dde506e..d3ce27446 100644 --- a/lib/src/screens/new_wallet/wallet_group_display_page.dart +++ b/lib/src/screens/new_wallet/wallet_group_display_page.dart @@ -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)), diff --git a/lib/src/screens/new_wallet/widgets/grouped_wallet_expansion_tile.dart b/lib/src/screens/new_wallet/widgets/grouped_wallet_expansion_tile.dart index 52e2e74b0..57f6a9047 100644 --- a/lib/src/screens/new_wallet/widgets/grouped_wallet_expansion_tile.dart +++ b/lib/src/screens/new_wallet/widgets/grouped_wallet_expansion_tile.dart @@ -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()! + .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, diff --git a/lib/src/screens/wallet_list/edit_wallet_button_widget.dart b/lib/src/screens/wallet_list/edit_wallet_button_widget.dart index 8f858348a..fd6f1a0ee 100644 --- a/lib/src/screens/wallet_list/edit_wallet_button_widget.dart +++ b/lib/src/screens/wallet_list/edit_wallet_button_widget.dart @@ -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()!.titlesColor, ), diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 9c210d8eb..8bb9593c9 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -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 { 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 { 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 { 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 { updateFunction: widget.walletListViewModel.reorderAccordingToWalletList, itemBuilder: (context, index) { final wallet = widget.walletListViewModel.singleWalletsList[index]; + final currentColor = wallet.isCurrent + ? Theme.of(context) + .extension()! + .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, diff --git a/lib/view_model/wallet_list/wallet_list_view_model.dart b/lib/view_model/wallet_list/wallet_list_view_model.dart index 539f5c640..4a4fdcb19 100644 --- a/lib/view_model/wallet_list/wallet_list_view_model.dart +++ b/lib/view_model/wallet_list/wallet_list_view_model.dart @@ -22,7 +22,8 @@ abstract class WalletListViewModelBase with Store { this._walletManager, ) : wallets = ObservableList(), multiWalletGroups = ObservableList(), - singleWalletsList = ObservableList() { + singleWalletsList = ObservableList(), + expansionTileStateTrack = ObservableMap() { setOrderType(_appStore.settingsStore.walletListOrder); reaction((_) => _appStore.wallet, (_) => updateList()); updateList(); @@ -40,6 +41,18 @@ abstract class WalletListViewModelBase with Store { @observable ObservableList singleWalletsList; + @observable + ObservableMap 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(); }