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-27 23:36:56 +01:00 committed by GitHub
parent 791b410277
commit b2850c203f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
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 KiB

View file

@ -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(

View file

@ -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)),

View file

@ -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,

View file

@ -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,
),

View file

@ -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,

View file

@ -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();
}