Release fixes (#3301)
* fix: Solana GMT token showing the wrong decimal place * add badge icon to swap confirm sheet, also address book chain icons display correctly * missing mask icon for mweb
David Adegoke committed
Jun 6, 2026 at 13:34 UTC
7c321faf2fd5b21c86b5813c0aee73e3a88093b8
5 files changed
+105
-50
lib/entities/new_ui_entities/list_item/list_item_regular_row.dart
+4
@@ -8,6 +8,7 @@ class ListItemRegularRow extends ListItem {
8
this.subtitle,
9
this.trailingText,
10
this.iconPath,
11
+ this.badgeIconPath,
12
this.onTap,
13
this.trailingIconPath,
14
this.showArrow = true,
@@ -19,6 +20,7 @@ class ListItemRegularRow extends ListItem {
20
this.copyableText,
21
this.leadingIconErrorWidget,
22
this.leadingIconSize,
23
+ this.badgeIconSize,
24
this.iconColor,
25
});
26
@@ -26,6 +28,7 @@ class ListItemRegularRow extends ListItem {
28
final String? trailingText;
29
final String? iconPath;
30
final String? trailingIconPath;
31
+ final String? badgeIconPath;
32
final String? copyableText;
33
final VoidCallback? onTap;
34
final bool showArrow;
@@ -36,5 +39,6 @@ class ListItemRegularRow extends ListItem {
39
final double? trailingIconSize;
40
final Widget? leadingIconErrorWidget;
41
final double? leadingIconSize;
42
+ final double? badgeIconSize;
43
final Color? iconColor;
44
}
lib/new-ui/widgets/send_page/l2_action_wallet_selector.dart
+9
-10
@@ -3,6 +3,7 @@ import 'dart:async';
3
import 'package:cake_wallet/bitcoin/bitcoin.dart';
4
import 'package:cake_wallet/generated/i18n.dart';
5
import 'package:cake_wallet/main.dart';
6
+import 'package:cake_wallet/new-ui/widgets/coins_page/token_image_widget.dart';
7
import 'package:cake_wallet/new-ui/widgets/new_primary_button.dart';
8
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
9
import 'package:cake_wallet/new-ui/widgets/send_page/l2_send_external_modal.dart';
@@ -56,8 +57,8 @@ class _L2ActionWalletSelectorState extends State<L2ActionWalletSelector> {
57
super.initState();
58
if (widget.showOtherWallets) {
59
() async {
59
- items.addAll((await WalletInfo.getAll())
60
- .where((item) => item.type == widget.sendViewModel.walletType && item.hardwareWalletType == null));
60
+ items.addAll((await WalletInfo.getAll()).where((item) =>
61
+ item.type == widget.sendViewModel.walletType && item.hardwareWalletType == null));
62
items.sort((a, b) {
63
if (a.name == widget.sendViewModel.wallet.name)
64
return -1;
@@ -125,8 +126,7 @@ class _L2ActionWalletSelectorState extends State<L2ActionWalletSelector> {
126
return Padding(
127
padding: const EdgeInsets.symmetric(vertical: 4.0),
128
child: WalletRow(
128
- currencyIconPath:
129
- getCryptoCurrencyIconForWalletListItem(item.type),
129
+ currencyIconPath: getCryptoCurrencyIconForWalletListItem(item.type),
130
walletName: item.name,
131
isCurrent: item.name == widget.sendViewModel.wallet.name,
132
isSelected: _selectedWalletIndex == index && !textEntered,
@@ -252,8 +252,8 @@ class _L2ActionWalletSelectorState extends State<L2ActionWalletSelector> {
252
mainAxisAlignment: MainAxisAlignment.center,
253
spacing: 10,
254
children: [
255
- CakeImageWidget(imageUrl:
256
- "assets/new-ui/send_from_external.svg",
255
+ CakeImageWidget(
256
+ imageUrl: "assets/new-ui/send_from_external.svg",
257
colorFilter: ColorFilter.mode(
258
Theme.of(context).colorScheme.primary, BlendMode.srcIn),
259
),
@@ -378,10 +378,9 @@ class WalletRow extends StatelessWidget {
378
Row(
379
spacing: 12,
380
children: [
381
- Image.asset(
382
- currencyIconPath,
383
- height: 24,
384
- width: 24,
381
+ TokenImageWidget(
382
+ imageUrl: currencyIconPath,
383
+ size: 24,
384
),
385
Column(
386
mainAxisAlignment: MainAxisAlignment.center,
lib/new-ui/widgets/swap_page/swap_confirm_sheet.dart
+23
@@ -14,7 +14,10 @@ import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
14
import 'package:cake_wallet/view_model/exchange/exchange_trade_view_model.dart';
15
import 'package:cake_wallet/view_model/exchange/exchange_view_model.dart';
16
import 'package:cake_wallet/view_model/send/send_view_model_state.dart';
17
+import 'package:cw_core/crypto_currency.dart';
18
import 'package:cw_core/currencies_with_memo.dart';
19
+import 'package:cw_core/currency_for_wallet_type.dart';
20
+import 'package:cw_core/wallet_type.dart';
21
import 'package:flutter/material.dart';
22
import 'package:flutter/services.dart';
23
import 'package:flutter_mobx/flutter_mobx.dart';
@@ -160,6 +163,7 @@ class SwapTransactionDetails extends StatelessWidget {
163
keyValue: "send value",
164
label: exchangeViewModel.depositCurrency.fullName ?? "",
165
iconPath: exchangeViewModel.depositCurrency.iconPath ?? "",
166
+ badgeIconPath: _resolveChainBadgePath(exchangeViewModel.depositCurrency),
167
trailingText: exchangeTradeViewModel.trade.amountFormatted() +
168
" " +
169
(exchangeViewModel.depositCurrency.title)),
@@ -184,6 +188,7 @@ class SwapTransactionDetails extends StatelessWidget {
188
keyValue: "receive value",
189
label: exchangeViewModel.receiveCurrency.fullName ?? "",
190
iconPath: exchangeViewModel.receiveCurrency.iconPath ?? "",
191
+ badgeIconPath: _resolveChainBadgePath(exchangeViewModel.receiveCurrency),
192
trailingText:
193
(receiveAmount) + " " + (exchangeViewModel.receiveCurrency.title)),
194
ListItemRegularRow(
@@ -272,3 +277,21 @@ class SwapTransactionDetails extends StatelessWidget {
277
}
278
}
279
}
280
+
281
+String? _resolveChainBadgePath(CryptoCurrency currency) {
282
+ try {
283
+ if (currency.chainIconPath != null) return currency.chainIconPath;
284
+
285
+ final tag = currency.tag;
286
+ if (tag != null && tag.isNotEmpty) {
287
+ final byTag = CryptoCurrency.fromString(tag);
288
+ if (byTag.chainIconPath != null) return byTag.chainIconPath;
289
+ }
290
+
291
+ final walletType = cryptoCurrencyOrTokenToWalletType(currency);
292
+ if (walletType != null) {
293
+ return walletTypeToCryptoCurrency(walletType).chainIconPath;
294
+ }
295
+ } catch (_) {}
296
+ return null;
297
+}
lib/src/widgets/new_list_row/list_item_regular_row_widget.dart
+67
-40
@@ -6,34 +6,36 @@ import 'package:flutter/material.dart';
6
import 'package:flutter/services.dart';
7
8
class ListItemRegularRowWidget extends StatelessWidget {
9
- const ListItemRegularRowWidget({
10
- super.key,
11
- required this.keyValue,
12
- required this.label,
13
- this.subtitle,
14
- this.trailingText,
15
- this.iconPath,
16
- this.onTap,
17
- this.isFirstInSection = false,
18
- this.isLastInSection = false,
19
- this.showArrow = true,
20
- this.trailingIconPath,
21
- this.truncateTrailingText = false,
22
- this.foregroundColor,
23
- this.trailingIconSize,
24
- this.bottomWidget,
25
- this.trailingWidget,
26
- this.copyableText,
27
- this.leadingIconErrorWidget,
28
- this.leadingIconSize,
29
- this.iconColor
30
- });
9
+ const ListItemRegularRowWidget(
10
+ {super.key,
11
+ required this.keyValue,
12
+ required this.label,
13
+ this.subtitle,
14
+ this.trailingText,
15
+ this.iconPath,
16
+ this.badgeIconPath,
17
+ this.onTap,
18
+ this.isFirstInSection = false,
19
+ this.isLastInSection = false,
20
+ this.showArrow = true,
21
+ this.trailingIconPath,
22
+ this.truncateTrailingText = false,
23
+ this.foregroundColor,
24
+ this.trailingIconSize,
25
+ this.bottomWidget,
26
+ this.trailingWidget,
27
+ this.copyableText,
28
+ this.leadingIconErrorWidget,
29
+ this.leadingIconSize,
30
+ this.badgeIconSize,
31
+ this.iconColor});
32
33
final String keyValue;
34
final String label;
35
final String? subtitle;
36
final String? trailingText;
37
final String? iconPath;
38
+ final String? badgeIconPath;
39
final VoidCallback? onTap;
40
final bool isFirstInSection;
41
final bool isLastInSection;
@@ -47,6 +49,7 @@ class ListItemRegularRowWidget extends StatelessWidget {
49
final String? copyableText;
50
final Widget? leadingIconErrorWidget;
51
final double? leadingIconSize;
52
+ final double? badgeIconSize;
53
final Color? iconColor;
54
55
@override
@@ -69,6 +72,38 @@ class ListItemRegularRowWidget extends StatelessWidget {
72
isFirstInSection: isFirstInSection,
73
isLastInSection: isLastInSection,
74
builder: (context, textStyle, labelStyle) {
75
+ final leadingIcon = iconPath != null
76
+ ? CakeImageWidget(
77
+ imageUrl: iconPath!,
78
+ width: leadingIconSize ?? 24,
79
+ height: leadingIconSize ?? 24,
80
+ errorWidget: leadingIconErrorWidget,
81
+ colorFilter:
82
+ iconColor == null ? null : ColorFilter.mode(iconColor!, BlendMode.srcIn),
83
+ )
84
+ : null;
85
+
86
+ final imageWidget = badgeIconPath != null
87
+ ? Stack(
88
+ clipBehavior: Clip.none,
89
+ children: [
90
+ leadingIcon!,
91
+ Positioned(
92
+ right: -3,
93
+ bottom: -3,
94
+ child: CakeImageWidget(
95
+ imageUrl: badgeIconPath!,
96
+ width: badgeIconSize ?? 10,
97
+ height: badgeIconSize ?? 10,
98
+ errorWidget: leadingIconErrorWidget,
99
+ colorFilter: iconColor == null
100
+ ? null
101
+ : ColorFilter.mode(iconColor!, BlendMode.srcIn),
102
+ ),
103
+ ),
104
+ ],
105
+ )
106
+ : leadingIcon;
107
return Column(
108
crossAxisAlignment: CrossAxisAlignment.start,
109
mainAxisAlignment: MainAxisAlignment.center,
@@ -81,16 +116,9 @@ class ListItemRegularRowWidget extends StatelessWidget {
116
children: [
117
if (iconPath != null)
118
Padding(
84
- padding: const EdgeInsets.only(right: 12.0),
85
- child: CakeImageWidget(
86
- imageUrl: iconPath!,
87
- width: leadingIconSize ?? 24,
88
- height: leadingIconSize ?? 24,
89
- errorWidget: leadingIconErrorWidget,
90
- colorFilter: iconColor == null
91
- ? null
92
- : ColorFilter.mode(iconColor!, BlendMode.srcIn),
93
- )),
119
+ padding: const EdgeInsets.only(right: 12.0),
120
+ child: imageWidget ?? SizedBox(),
121
+ ),
122
Flexible(
123
child: Column(
124
mainAxisAlignment: MainAxisAlignment.center,
@@ -140,14 +168,13 @@ class ListItemRegularRowWidget extends StatelessWidget {
168
BlendMode.srcIn),
169
)
170
else if (showArrow)
143
- Padding(
144
- padding: const EdgeInsets.symmetric(vertical: 7.0),
145
- child: CakeImageWidget(imageUrl:
146
- "assets/new-ui/arrow_forward.svg",
147
- height: 14,
148
- color: theme.colorScheme.onSurfaceVariant
149
- ),
150
- )
171
+ Padding(
172
+ padding: const EdgeInsets.symmetric(vertical: 7.0),
173
+ child: CakeImageWidget(
174
+ imageUrl: "assets/new-ui/arrow_forward.svg",
175
+ height: 14,
176
+ color: theme.colorScheme.onSurfaceVariant),
177
+ )
178
],
179
),
180
],
lib/src/widgets/new_list_row/new_list_section.dart
+2
@@ -96,6 +96,7 @@ class NewListSections extends StatelessWidget {
96
subtitle: item.subtitle,
97
trailingText: item.trailingText,
98
iconPath: item.iconPath,
99
+ badgeIconPath: item.badgeIconPath,
100
trailingIconPath: item.trailingIconPath,
101
onTap: tapHandlers[item.keyValue] ?? item.onTap,
102
isFirstInSection: isFirst,
@@ -109,6 +110,7 @@ class NewListSections extends StatelessWidget {
110
bottomWidget: item.bottomWidget,
111
leadingIconErrorWidget: item.leadingIconErrorWidget,
112
leadingIconSize: item.leadingIconSize,
113
+ badgeIconSize: item.badgeIconSize,
114
iconColor: item.iconColor,
115
);
116
}