dev
dart 224 lines 7.94 KB
Raw
1 import "package:cake_wallet/generated/i18n.dart";
2 import "package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart";
3 import "package:cake_wallet/new-ui/widgets/send_page/directional_switcher.dart";
4 import "package:cake_wallet/routes.dart";
5 import "package:cake_wallet/src/screens/connect_device/connect_device_page.dart";
6 import "package:cake_wallet/src/widgets/alert_with_two_actions.dart";
7 import "package:cake_wallet/src/widgets/base_alert_dialog.dart";
8 import "package:cake_wallet/src/widgets/cake_image_widget.dart";
9 import "package:cake_wallet/src/widgets/primary_button.dart";
10 import "package:cake_wallet/store/app_store.dart";
11 import "package:cake_wallet/utils/show_pop_up.dart";
12 import "package:cake_wallet/view_model/hardware_wallet/trezor_connect_view_model.dart";
13 import "package:cw_core/wallet_base.dart";
14 import "package:cw_core/wallet_info.dart";
15 import "package:flutter/cupertino.dart";
16 import "package:flutter/material.dart";
17
18 class SyncKeyImagesSheet extends StatefulWidget {
19 const SyncKeyImagesSheet({
20 required this.appStore,
21 required this.trezorConnectVM,
22 super.key,
23 });
24
25 final AppStore appStore;
26 final TrezorConnectViewModelBase trezorConnectVM;
27
28 WalletBase get wallet => appStore.wallet!;
29
30 @override
31 State<SyncKeyImagesSheet> createState() => _HardwareWalletProceedOnDeviceSheetState();
32 }
33
34 class _HardwareWalletProceedOnDeviceSheetState extends State<SyncKeyImagesSheet> {
35 _KeyImageSyncState _state = _KeyImageSyncState.initial;
36
37 @override
38 Widget build(BuildContext context) => PopScope(
39 canPop: false,
40 child: SafeArea(
41 bottom: false,
42 child: Container(
43 width: MediaQuery.of(context).size.width,
44 decoration: BoxDecoration(
45 color: Theme.of(context).colorScheme.surface,
46 borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
47 ),
48 child: SafeArea(
49 child: Padding(
50 padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
51 child: Column(
52 children: [
53 ModalTopBar(
54 title: S.of(context).resync_device,
55 leadingIcon: Icon(
56 Icons.close,
57 color: Theme.of(context).colorScheme.onSurfaceVariant,
58 ),
59 onLeadingPressed: () => showPopUp(
60 context: context,
61 builder: (context) => AlertWithTwoActions(
62 alertTitle: S.of(context).are_you_sure_exit,
63 alertContent: S.of(context).resync_device_cancel_warning_desc,
64 leftButtonText: S.of(context).cancel,
65 rightButtonText: S.of(context).yes_exit,
66 rightAlertButtonStyle: AlertButtonStyle.error(context),
67 actionLeftButton: Navigator.of(context).pop,
68 actionRightButton: () {
69 Navigator.of(context).pop();
70 Navigator.of(context).pop();
71 },
72 ),
73 ),
74 ),
75 Expanded(
76 child: Column(
77 spacing: 12,
78 mainAxisAlignment: MainAxisAlignment.center,
79 children: [
80 CakeImageWidget(
81 imageUrl: hardwareWalletIcon,
82 width: 100,
83 colorFilter: ColorFilter.mode(
84 Theme.of(context).colorScheme.onSurfaceVariant,
85 BlendMode.srcIn,
86 ),
87 ),
88 DirectionalAnimatedSwitcher(
89 duration: const Duration(milliseconds: 400),
90 child: content,
91 ),
92 ],
93 ),
94 ),
95 Padding(
96 padding: const EdgeInsets.all(24),
97 child: AnimatedOpacity(
98 curve: Curves.easeOutQuad,
99 opacity: _state == _KeyImageSyncState.initial ? 1 : 0,
100 duration: const Duration(milliseconds: 300),
101 child: PrimaryButton(
102 text: S.of(context).continue_text,
103 color: Theme.of(context).colorScheme.primary,
104 textColor: Theme.of(context).colorScheme.onPrimary,
105 onPressed: _onContinuePressed,
106 ),
107 ),
108 ),
109 ],
110 ),
111 ),
112 ),
113 ),
114 ),
115 );
116
117 Widget get content {
118 if (_state == _KeyImageSyncState.syncing) {
119 return _syncingKeyImages();
120 }
121
122 return _initial();
123 }
124
125 String? get hardwareWalletIcon {
126 switch (widget.wallet.hardwareWalletType) {
127 case HardwareWalletType.bitbox:
128 return "assets/new-ui/hardware_wallets/device_bitbox.svg";
129 case HardwareWalletType.ledger:
130 return "assets/new-ui/hardware_wallets/device_ledger_nano_x.svg";
131 case HardwareWalletType.trezor:
132 return "assets/new-ui/hardware_wallets/device_trezor_safe_7.svg";
133 case HardwareWalletType.cupcake:
134 return "assets/images/cupcake.svg";
135 case HardwareWalletType.coldcard:
136 case HardwareWalletType.seedsigner:
137 case HardwareWalletType.keystone:
138 case null:
139 return "assets/images/hardware_wallet/device_qr.svg";
140 }
141 }
142
143 Widget _initial() => Column(
144 key: const ValueKey(0),
145 spacing: 12,
146 mainAxisAlignment: MainAxisAlignment.center,
147 children: [
148 Padding(
149 padding: const EdgeInsets.symmetric(horizontal: 20),
150 child: Text(
151 S.of(context).resync_device_desc,
152 textAlign: TextAlign.center,
153 style: TextStyle(
154 fontSize: 16,
155 color: Theme.of(context).colorScheme.onSurfaceVariant,
156 ),
157 ),
158 ),
159 ],
160 );
161
162 Widget _syncingKeyImages() => Column(
163 key: const ValueKey(1),
164 spacing: 12,
165 mainAxisAlignment: MainAxisAlignment.center,
166 children: [
167 Text(
168 S.of(context).proceed_on_device,
169 style: TextStyle(
170 fontWeight: FontWeight.w500,
171 fontSize: 20,
172 ),
173 ),
174 Padding(
175 padding: EdgeInsets.symmetric(horizontal: 20),
176 child: Text(
177 S.of(context).proceed_on_device_description,
178 textAlign: TextAlign.center,
179 style: TextStyle(
180 fontSize: 16,
181 color: Theme.of(context).colorScheme.onSurfaceVariant,
182 ),
183 ),
184 )
185 ],
186 );
187
188 Future<void> _onContinuePressed() async {
189 setState(() => _state = _KeyImageSyncState.syncing);
190
191 if (!widget.trezorConnectVM.isConnected(widget.wallet.type)) {
192 await Navigator.of(context).pushNamed(
193 Routes.connectDevices,
194 arguments: ConnectDevicePageParams(
195 walletType: widget.wallet.type,
196 hardwareWalletType: widget.wallet.walletInfo.hardwareWalletType!,
197 onConnectDevice: (_, __) {
198 widget.trezorConnectVM.initWallet(widget.wallet);
199 Navigator.of(context).pop();
200 },
201 isReconnect: false,
202 ),
203 );
204
205 // Recheck to handle tap-backs
206 if (!widget.trezorConnectVM.isConnected(widget.wallet.type)) {
207 setState(() => _state = _KeyImageSyncState.initial);
208 return;
209 }
210 } else {
211 await widget.trezorConnectVM.initWallet(widget.wallet);
212 }
213
214 final result = await widget.trezorConnectVM.syncKeyImages(widget.wallet);
215 if (result && context.mounted) {
216 Navigator.of(context).pop();
217 }
218 }
219 }
220
221 enum _KeyImageSyncState {
222 initial,
223 syncing;
224 }