dev
dart 225 lines 10.6 KB
Raw
1 import 'dart:io';
2
3 import 'package:cake_wallet/core/auth_service.dart';
4 import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_regular_row.dart';
5 import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_selector.dart';
6 import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item_toggle.dart';
7 import 'package:cake_wallet/entities/pin_code_required_duration.dart';
8 import 'package:cake_wallet/new-ui/widgets/modal_header.dart';
9 import 'package:cake_wallet/new-ui/widgets/modal_page_wrapper.dart';
10 import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
11 import 'package:cake_wallet/routes.dart';
12 import 'package:cake_wallet/src/screens/base_page.dart';
13 import 'package:cake_wallet/generated/i18n.dart';
14 import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
15 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
16 import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
17 import 'package:cake_wallet/src/widgets/new_list_row/new_list_section.dart';
18 import 'package:cake_wallet/src/widgets/picker.dart';
19 import 'package:cake_wallet/utils/device_info.dart';
20 import 'package:cake_wallet/utils/feature_flag.dart';
21 import 'package:cake_wallet/utils/show_pop_up.dart';
22 import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart';
23 import 'package:flutter/material.dart';
24 import 'package:flutter_mobx/flutter_mobx.dart';
25
26 class SecurityBackupPage extends BasePage {
27 SecurityBackupPage(this._securitySettingsViewModel, this._authService,
28 [this._isHardwareWallet = false]);
29
30 final AuthService _authService;
31
32 @override
33 bool get hideAppBar => true;
34
35 @override
36 String get title => S.current.security_and_backup;
37
38 final SecuritySettingsViewModel _securitySettingsViewModel;
39
40 final bool _isHardwareWallet;
41
42 @override
43 Widget body(BuildContext context) {
44 return ModalPageWrapper(
45 topBar: ModalTopBar(
46 title: "",
47 leadingIcon: Icon(Icons.arrow_back_ios_new),
48 leadingSemanticLabel: S.of(context).seed_alert_back,
49 onLeadingPressed: () => Navigator.of(context).pop()),
50 header: ModalHeader(
51 iconPath: "assets/new-ui/settings_row_icons/security.svg",
52 message: S.of(context).privacy_and_security_desc,
53 title: S.of(context).security),
54 content: Column(
55 spacing: 16,
56 mainAxisSize: MainAxisSize.min,
57 children: [
58 Observer(
59 builder: (_) => NewListSections(sections: {
60 "": [
61 if (DeviceInfo.instance.isMobile || Platform.isMacOS || Platform.isLinux)
62 ListItemToggle(
63 keyValue: "security_backup_page_allow_biometrics_button_key",
64 label: S.current.settings_allow_biometrical_authentication,
65 value: _securitySettingsViewModel.allowBiometricalAuthentication,
66 onChanged: (bool value) {
67 if (value) {
68 _authService.authenticateAction(
69 context,
70 onAuthSuccess: (isAuthenticatedSuccessfully) async {
71 if (isAuthenticatedSuccessfully) {
72 if (await _securitySettingsViewModel.biometricAuthenticated()) {
73 _securitySettingsViewModel.setAllowBiometricalAuthentication(
74 isAuthenticatedSuccessfully);
75 }
76 } else {
77 _securitySettingsViewModel
78 .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully);
79 }
80 },
81 conditionToDetermineIfToUse2FA: _securitySettingsViewModel
82 .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
83 );
84 } else {
85 _securitySettingsViewModel.setAllowBiometricalAuthentication(value);
86 }
87 }),
88 if (DeviceInfo.instance.isMobile)
89 ListItemToggle(
90 keyValue: "display_settings_prevent_screen_capture",
91 label: S.of(context).prevent_screenshots,
92 value: _securitySettingsViewModel.isAppSecure,
93 onChanged: (val) {
94 _securitySettingsViewModel.setIsAppSecure(val);
95 }),
96 if (FeatureFlag.duressPinEnabled)
97 ListItemToggle(
98 keyValue: "security_backup_page_duress_pin_button_key",
99 label: "Duress PIN",
100 value: _securitySettingsViewModel.enableDuressPin,
101 onChanged: (bool value) {
102 _authService
103 .authenticateAction(context, route: Routes.securityBackupDuressPin,
104 onAuthSuccess: (isAuthenticatedSuccessfully) async {
105 if (isAuthenticatedSuccessfully) {
106 if (!value) {
107 _securitySettingsViewModel.setEnableDuressPin(value);
108 _securitySettingsViewModel.clearDuressPin();
109 return;
110 }
111 final res = await _showDuressPinDescription(context);
112 if (res) {
113 final confirmation = await _showDuressPinConfirmation(context);
114
115 if (confirmation) {
116 Navigator.of(context).pushNamed(
117 Routes.setupDuressPin,
118 arguments: (PinCodeState<PinCodeWidget> pinCtx, String _) async {
119 pinCtx.close();
120 _securitySettingsViewModel.setEnableDuressPin(true);
121 },
122 );
123 }
124 }
125 }
126 },
127 conditionToDetermineIfToUse2FA: _securitySettingsViewModel
128 .shouldRequireTOTP2FAForAllSecurityAndBackupSettings);
129 }),
130 ListItemSelector(
131 keyValue: "security_backup_page_require_pin_after_button_key",
132 label: S.current.require_pin_after,
133 options: [_securitySettingsViewModel.pinCodeRequiredDuration.toString()],
134 onTap: () async {
135 final items = PinCodeRequiredDuration.values;
136
137 final selectedAtIndex =
138 items.indexOf(_securitySettingsViewModel.pinCodeRequiredDuration);
139
140 await showPopUp<void>(
141 context: context,
142 builder: (_) => Picker(
143 items: items,
144 selectedAtIndex: selectedAtIndex,
145 mainAxisAlignment: MainAxisAlignment.start,
146 onItemSelected: (PinCodeRequiredDuration item) {
147 _securitySettingsViewModel.setPinCodeRequiredDuration(item);
148 },
149 isSeparated: false,
150 ),
151 );
152 }),
153 // if (!_isHardwareWallet)
154 // ListItemRegularRow(
155 // keyValue: "security_backup_page_show_keys_button_key",
156 // label: S.current.show_keys,
157 // onTap: () {
158 // _authService.authenticateAction(
159 // context,
160 // route: Routes.showKeys,
161 // conditionToDetermineIfToUse2FA: _securitySettingsViewModel
162 // .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
163 // );
164 // }),
165 ListItemRegularRow(
166 keyValue: "security_backup_page_change_pin_button_key",
167 label: S.current.settings_change_pin,
168 onTap: () {
169 _authService.authenticateAction(
170 context,
171 route: Routes.setupPin,
172 arguments: (PinCodeState<PinCodeWidget> setupPinContext, String _) {
173 setupPinContext.close();
174 },
175 conditionToDetermineIfToUse2FA: _securitySettingsViewModel
176 .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
177 );
178 }),
179 ListItemRegularRow(
180 keyValue: "security_backup_page_totp_2fa_button_key",
181 label: _securitySettingsViewModel.useTotp2FA
182 ? S.current.modify_2fa
183 : S.current.setup_2fa,
184 onTap: () {
185 _authService.authenticateAction(
186 context,
187 route: _securitySettingsViewModel.useTotp2FA
188 ? Routes.modify2FAPage
189 : Routes.setup2faInfoPage,
190 conditionToDetermineIfToUse2FA: _securitySettingsViewModel
191 .shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
192 );
193 })
194 ]
195 }),
196 ),
197 ],
198 ),
199 );
200 }
201 }
202
203 Future<bool> _showDuressPinDescription(BuildContext context) async {
204 final ok = await showPopUp<bool>(
205 context: context,
206 builder: (BuildContext context) => AlertWithOneAction(
207 alertTitle: S.of(context).alert_notice,
208 alertContent: S.current.duress_pin_description,
209 buttonText: S.of(context).ok,
210 buttonAction: () => Navigator.of(context).pop(true)));
211 return ok ?? false;
212 }
213
214 Future<bool> _showDuressPinConfirmation(BuildContext context) async {
215 final ok = await showPopUp<bool>(
216 context: context,
217 builder: (BuildContext context) => AlertWithTwoActions(
218 alertTitle: S.of(context).confirm,
219 alertContent: S.current.did_you_back_up_seeds,
220 leftButtonText: S.current.no,
221 rightButtonText: S.current.yes,
222 actionLeftButton: () => Navigator.of(context).pop(false),
223 actionRightButton: () => Navigator.of(context).pop(true)));
224 return ok ?? false;
225 }