dev
dart 235 lines 8.18 KB
Raw
1 import 'dart:io';
2
3 import 'package:cake_wallet/generated/i18n.dart';
4 import 'package:cake_wallet/routes.dart';
5 import 'package:cake_wallet/src/screens/base_page.dart';
6 import 'package:cake_wallet/src/screens/connect_device/widgets/dotted_divider.dart';
7 import 'package:cake_wallet/src/screens/connect_device/widgets/manufacturer_option_tile.dart';
8 import 'package:cake_wallet/utils/permission_handler.dart';
9 import 'package:cake_wallet/view_model/restore/wallet_restore_from_qr_code.dart';
10 import 'package:cw_core/utils/print_verbose.dart';
11 import 'package:cw_core/wallet_info.dart';
12 import 'package:flutter/material.dart';
13 import 'package:flutter_svg/flutter_svg.dart';
14 import 'package:fluttertoast/fluttertoast.dart';
15 import 'package:permission_handler/permission_handler.dart';
16
17 class SelectDeviceManufacturerPage extends BasePage {
18 SelectDeviceManufacturerPage({
19 this.showUnavailable = true,
20 this.onSelect,
21 this.availableHardwareWalletTypes,
22 });
23
24 final bool showUnavailable;
25 final void Function(BuildContext, HardwareWalletType)? onSelect;
26 final List<HardwareWalletType>? availableHardwareWalletTypes;
27
28 @override
29 String get title => S.current.select_manufacturer_title;
30
31 @override
32 AppBarStyle get appBarStyle => AppBarStyle.regular;
33
34 ColorFilter get _colorFilter =>
35 ColorFilter.mode(currentTheme.colorScheme.onSurface, BlendMode.srcIn);
36
37 List<_DeviceManufacturer> get availableManufacturers => [
38 _DeviceManufacturer(
39 image: SvgPicture.asset(
40 'assets/images/hardware_wallet/ledger_man.svg',
41 height: 25,
42 colorFilter: _colorFilter,
43 ),
44 hardwareWalletType: HardwareWalletType.ledger,
45 ),
46 _DeviceManufacturer(
47 image: SvgPicture.asset(
48 'assets/images/hardware_wallet/trezor_man.svg',
49 height: 25,
50 colorFilter: _colorFilter,
51 ),
52 hardwareWalletType: HardwareWalletType.trezor,
53 // tag: S.current.new_tag,
54 ),
55 if (Platform.isAndroid) ...[
56 _DeviceManufacturer(
57 image: SvgPicture.asset(
58 'assets/images/hardware_wallet/bitbox_man.svg',
59 height: 25,
60 colorFilter: _colorFilter,
61 ),
62 hardwareWalletType: HardwareWalletType.bitbox,
63 // tag: S.current.new_tag,
64 ),
65 ],
66 _DeviceManufacturer(
67 image: SvgPicture.asset(
68 'assets/images/hardware_wallet/cupcake_man.svg',
69 height: 25,
70 colorFilter: _colorFilter,
71 ),
72 hardwareWalletType: HardwareWalletType.cupcake,
73 // tag: S.current.new_tag,
74 ),
75 _DeviceManufacturer(
76 image: SvgPicture.asset(
77 'assets/images/hardware_wallet/coldcard_man.svg',
78 height: 25,
79 colorFilter: _colorFilter,
80 ),
81 hardwareWalletType: HardwareWalletType.coldcard,
82 // tag: S.current.new_tag,
83 ),
84 // _DeviceManufacturer(
85 // image: SvgPicture.asset(
86 // 'assets/images/hardware_wallet/seedsigner_man.svg',
87 // height: 25,
88 // colorFilter: _colorFilter,
89 // ),
90 // hardwareWalletType: HardwareWalletType.seedsigner,
91 // tag: S.current.new_tag,
92 // ),
93 ]
94 .where((e) => availableHardwareWalletTypes == null
95 ? ![HardwareWalletType.cupcake].contains(e.hardwareWalletType)
96 : availableHardwareWalletTypes!.contains(e.hardwareWalletType))
97 .toList();
98
99 List<_DeviceManufacturer> get comingManufacturers => [
100 if (!Platform.isAndroid) ...[
101 _DeviceManufacturer(
102 image: SvgPicture.asset(
103 'assets/images/hardware_wallet/bitbox_man.svg',
104 height: 25,
105 colorFilter: _colorFilter,
106 ),
107 hardwareWalletType: HardwareWalletType.bitbox,
108 tag: S.current.coming_soon_tag,
109 ),
110 ],
111 _DeviceManufacturer(
112 image: SvgPicture.asset(
113 'assets/images/hardware_wallet/seedsigner_man.svg',
114 height: 25,
115 colorFilter: _colorFilter,
116 ),
117 hardwareWalletType: HardwareWalletType.seedsigner,
118 tag: S.current.coming_soon_tag,
119 ),
120 _DeviceManufacturer(
121 image: SvgPicture.asset(
122 'assets/images/hardware_wallet/foundation_man.svg',
123 height: 25,
124 colorFilter: _colorFilter,
125 ),
126 tag: S.current.coming_soon_tag,
127 ),
128 _DeviceManufacturer(
129 image: SvgPicture.asset(
130 'assets/images/hardware_wallet/keystone_man.svg',
131 height: 25,
132 colorFilter: _colorFilter,
133 ),
134 tag: S.current.coming_soon_tag,
135 ),
136 ];
137
138 @override
139 Widget body(BuildContext context) => Container(
140 child: Center(
141 child: Container(
142 padding: EdgeInsets.only(left: 24, right: 24),
143 height: double.infinity,
144 child: SingleChildScrollView(
145 child: Column(
146 children: [
147 ...availableManufacturers.map(
148 (manufacturer) => Padding(
149 padding: EdgeInsets.only(top: 10),
150 child: ManufacturerOptionTile(
151 image: manufacturer.image,
152 tag: manufacturer.tag,
153 onPressed: () {
154 if (onSelect != null)
155 return onSelect!.call(context, manufacturer.hardwareWalletType!);
156
157 if (isAirgappedWallet(manufacturer.hardwareWalletType)) {
158 _onScanQRCode(context, manufacturer.hardwareWalletType!);
159 } else if (manufacturer.hardwareWalletType != null) {
160 Navigator.pushNamed(context, Routes.connectHardwareWallet,
161 arguments: [manufacturer.hardwareWalletType]);
162 }
163 },
164 ),
165 ),
166 ),
167 if (showUnavailable) ...[
168 Padding(
169 padding: EdgeInsets.only(top: 20, bottom: 10),
170 child: DottedDivider(color: Theme.of(context).colorScheme.surfaceContainer),
171 ),
172 ...comingManufacturers.map(
173 (manufacturer) => Padding(
174 padding: EdgeInsets.only(top: 10),
175 child: ManufacturerOptionTile(
176 image: manufacturer.image,
177 tag: manufacturer.tag,
178 onPressed: () =>
179 Fluttertoast.showToast(msg: 'One more tap and it might work'),
180 // Ester egg
181
182 isUnavailable: true,
183 ),
184 ),
185 ),
186 ]
187 ],
188 ),
189 ),
190 ),
191 ),
192 );
193
194 bool isAirgappedWallet(HardwareWalletType? type) => [
195 HardwareWalletType.cupcake,
196 HardwareWalletType.coldcard,
197 HardwareWalletType.seedsigner,
198 HardwareWalletType.keystone,
199 ].contains(type);
200
201 bool isRestoring = false;
202
203 Future<void> _onScanQRCode(BuildContext context, HardwareWalletType type) async {
204 final isCameraPermissionGranted =
205 await PermissionHandler.checkPermission(Permission.camera, context);
206
207 if (!isCameraPermissionGranted) return;
208 try {
209 if (isRestoring) return;
210
211 isRestoring = true;
212
213 final restoredWallet = await WalletRestoreFromQRCode.scanQRCodeForRestoring(context);
214
215 final params = {
216 'walletType': restoredWallet.type,
217 'restoredWallet': restoredWallet,
218 'hardwareWalletType': type,
219 };
220
221 Navigator.pushNamed(context, Routes.restoreWallet, arguments: params)
222 .then((_) => isRestoring = false);
223 } catch (e) {
224 printV(e.toString());
225 }
226 }
227 }
228
229 class _DeviceManufacturer {
230 final SvgPicture image;
231 final HardwareWalletType? hardwareWalletType;
232 final String? tag;
233
234 _DeviceManufacturer({required this.image, this.hardwareWalletType, this.tag});
235 }