disable editing coin control from settings (#3284)
malik1004x committed
Jun 15, 2026 at 01:17 UTC
9face62effa3326005047351a8e7557e51ac1044
8 files changed
+38
-20
lib/di.dart
+3
-3
@@ -1569,10 +1569,10 @@ Future<void> setup({
1569
unspentCoinsListViewModel:
1570
getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom)));
1571
1572
- getIt.registerFactoryParam<NewCoinControlPage, UnspentCoinType?, void>(
1573
- (coinTypeToSpendFrom, _) => NewCoinControlPage(
1572
+ getIt.registerFactoryParam<NewCoinControlPage, UnspentCoinType?, bool?>(
1573
+ (coinTypeToSpendFrom, canEdit) => NewCoinControlPage(
1574
unspentCoinsListViewModel:
1575
- getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom))
1575
+ getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom), canEdit: canEdit ?? true,)
1576
1577
);
1578
lib/new-ui/pages/coin_control_page.dart
+21
-7
@@ -4,15 +4,25 @@ import 'package:cake_wallet/new-ui/widgets/modal_header.dart';
4
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
5
import 'package:cake_wallet/routes.dart';
6
import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart';
7
+import 'package:cw_core/unspent_coin_type.dart';
8
import 'package:flutter/cupertino.dart';
9
import 'package:flutter/material.dart';
10
import 'package:flutter_mobx/flutter_mobx.dart';
11
import "package:cake_wallet/view_model/unspent_coins/unspent_coins_item.dart";
12
13
+class CoinControlPageArgs {
14
+ final bool canEdit;
15
+ final UnspentCoinType? coinTypeToSpendFrom;
16
+
17
+ const CoinControlPageArgs({required this.canEdit, this.coinTypeToSpendFrom});
18
+}
19
+
20
class NewCoinControlPage extends StatefulWidget {
13
- const NewCoinControlPage({super.key, required this.unspentCoinsListViewModel});
21
+ const NewCoinControlPage(
22
+ {super.key, required this.unspentCoinsListViewModel, required this.canEdit});
23
24
final UnspentCoinsListViewModel unspentCoinsListViewModel;
25
+ final bool canEdit;
26
27
@override
28
State<NewCoinControlPage> createState() => _NewCoinControlPageState();
@@ -31,9 +41,9 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
41
Widget build(BuildContext context) {
42
return PopScope(
43
canPop: !widget.unspentCoinsListViewModel.isSavingItems,
34
- onPopInvokedWithResult: (didPop, result) async{
44
+ onPopInvokedWithResult: (didPop, result) async {
45
await widget.unspentCoinsListViewModel.dispose();
36
- if(!didPop && mounted) Navigator.of(context).pop();
46
+ if (!didPop && mounted) Navigator.of(context).pop();
47
},
48
child: Material(
49
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
@@ -94,9 +104,9 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
104
child: ModalHeader(
105
iconPath: "assets/new-ui/settings_row_icons/coin-control.svg",
106
title: "Coin Control",
97
- message: S.of(context).coin_control_desc),
107
+ message: widget.canEdit ? S.of(context).coin_control_desc : S.of(context).coin_control_desc_no_edit),
108
),
99
- if (widget.unspentCoinsListViewModel.items.isNotEmpty)
109
+ if (widget.unspentCoinsListViewModel.items.isNotEmpty && widget.canEdit)
110
Padding(
111
padding: const EdgeInsets.all(12.0),
112
child: Row(
@@ -124,7 +134,7 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
134
)
135
],
136
),
127
- ),
137
+ ) else SizedBox(height: 24,),
138
if (widget.unspentCoinsListViewModel.nonFrozenItems.isEmpty &&
139
widget.unspentCoinsListViewModel.frozenItems.isEmpty) ...[
140
SizedBox(height: 12),
@@ -144,6 +154,7 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
154
: Padding(
155
padding: const EdgeInsets.symmetric(horizontal: 18.0),
156
child: CoinControlListSection(
157
+ canEdit: widget.canEdit,
158
items: widget.unspentCoinsListViewModel.nonFrozenItems,
159
unspentCoinsListViewModel:
160
widget.unspentCoinsListViewModel),
@@ -170,6 +181,7 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
181
.onSurfaceVariant),
182
),
183
CoinControlListSection(
184
+ canEdit: widget.canEdit,
185
items: widget
186
.unspentCoinsListViewModel.frozenItems,
187
unspentCoinsListViewModel:
@@ -194,9 +206,10 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
206
207
class CoinControlListSection extends StatelessWidget {
208
const CoinControlListSection(
197
- {super.key, required this.items, required this.unspentCoinsListViewModel});
209
+ {super.key, required this.items, required this.unspentCoinsListViewModel, required this.canEdit});
210
211
final List<UnspentCoinsItem> items;
212
+ final bool canEdit;
213
final UnspentCoinsListViewModel unspentCoinsListViewModel;
214
215
@override
@@ -231,6 +244,7 @@ class CoinControlListSection extends StatelessWidget {
244
isLoading: item.isBeingSaved,
245
isFirst: index == 0,
246
isLast: index == items.length - 1,
247
+ hasCheckbox: canEdit,
248
onCheckBoxTap: item.isFrozen
249
? null
250
: () async {
lib/new-ui/pages/send_page.dart
+1
-1
@@ -524,7 +524,7 @@ class _NewSendPageState extends State<NewSendPage> {
524
label: "Coin Control",
525
onTap: () {
526
showCupertinoModalBottomSheet(enableDrag: false, useRootNavigator: true, isDismissible: false, context: context, builder: (context){
527
- return NewCoinControlPage(unspentCoinsListViewModel: widget.sendViewModel.unspentCoinsListViewModel,);
527
+ return NewCoinControlPage(unspentCoinsListViewModel: widget.sendViewModel.unspentCoinsListViewModel,canEdit: true);
528
});
529
}
530
),
lib/new-ui/widgets/coin_control_page/coin_control_list_item.dart
+6
-1
@@ -17,7 +17,7 @@ class CoinControlListItem extends StatelessWidget {
17
required this.isFirst,
18
required this.isLast,
19
required this.isLoading,
20
- this.onCheckBoxTap,
20
+ this.onCheckBoxTap, required this.hasCheckbox,
21
});
22
23
final String note;
@@ -31,6 +31,7 @@ class CoinControlListItem extends StatelessWidget {
31
final bool isFirst;
32
final bool isLast;
33
final bool isLoading;
34
+ final bool hasCheckbox;
35
final Function()? onCheckBoxTap;
36
37
@override
@@ -123,6 +124,10 @@ class CoinControlListItem extends StatelessWidget {
124
return CakeImageWidget(imageUrl:"assets/new-ui/frozen.svg");
125
}
126
127
+ if(!hasCheckbox) {
128
+ return SizedBox.shrink();
129
+ }
130
+
131
return NewSimpleCheckbox(value: isSending, onChanged: (value){onCheckBoxTap?.call();});
132
133
}
lib/new-ui/widgets/swap_page/swap_options_page.dart
+1
-1
@@ -102,7 +102,7 @@ class SwapOptionsPage extends StatelessWidget {
102
label: "Coin Control",
103
onTap: () {
104
showCupertinoModalBottomSheet(enableDrag: false, useRootNavigator: true, isDismissible: false, context: context, builder: (context){
105
- return NewCoinControlPage(unspentCoinsListViewModel: exchangeViewModel.unspentCoinsListViewModel,);
105
+ return NewCoinControlPage(unspentCoinsListViewModel: exchangeViewModel.unspentCoinsListViewModel,canEdit: true,);
106
});
107
}),
108
ListItemSelector(
lib/router.dart
+3
-6
@@ -759,12 +759,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
759
);
760
761
case Routes.unspentCoinsList:
762
- final coinTypeToSpendFrom = settings.arguments as UnspentCoinType?;
763
- return handleRouteWithPlatformAwareness(
764
- (context) => FeatureFlag.hasNewUi
765
- ? getIt.get<NewCoinControlPage>(param1: coinTypeToSpendFrom)
766
- : getIt.get<UnspentCoinsListPage>(param1: coinTypeToSpendFrom),
767
- );
762
+ final args = settings.arguments as CoinControlPageArgs?;
763
+ return handleRouteWithPlatformAwareness((context) =>
764
+ getIt.get<NewCoinControlPage>(param1: args?.coinTypeToSpendFrom, param2: args?.canEdit));
765
766
case Routes.unspentCoinsDetails:
767
final args = settings.arguments as List;
lib/src/screens/settings/privacy_page.dart
+2
-1
@@ -1,6 +1,7 @@
1
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart';
2
import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_toggle.dart';
3
import 'package:cake_wallet/generated/i18n.dart';
4
+import 'package:cake_wallet/new-ui/pages/coin_control_page.dart';
5
import 'package:cake_wallet/new-ui/widgets/modal_header.dart';
6
import 'package:cake_wallet/new-ui/widgets/modal_page_wrapper.dart';
7
import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
@@ -95,7 +96,7 @@ class PrivacyPage extends BasePage {
96
keyValue: "coin_control",
97
label: "Coin Control",
98
onTap: () =>
98
- Navigator.of(context).pushNamed(Routes.unspentCoinsList)),
99
+ Navigator.of(context).pushNamed(Routes.unspentCoinsList, arguments: CoinControlPageArgs(canEdit: false, coinTypeToSpendFrom: null))),
100
],
101
}
102
),
res/values/strings_en.arb
+1
@@ -208,6 +208,7 @@
208
"close": "Close",
209
"coin_control": "Coin Control (optional)",
210
"coin_control_desc": "Filter outputs for this transaction. The changes you make here will only reflect on the current transaction.",
211
+ "coin_control_desc_no_edit": "Freeze outputs if needed. The changes will be persistent across all transactions. You can also filter outputs for one transaction on the Send or Swap screens.",
212
"coin_control_load_failed": "Failed to load unspent coins",
213
"cold_or_recover_wallet": "Add an air-gapped cold wallet or recover a paper wallet.",
214
"collection_address": "Collection Address",