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:
David Adegoke
2024-09-28 01:36:56 +03:00
committed by GitHub
co-authored by tuxpizza
parent 791b410277
commit b2850c203f
10 changed files with 144 additions and 26 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 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();
}