bio auth on mac + package updates for 3.19.3/5 (#1398)
* bio auth mac fix * remove comment and change duration from 2 to 0 * cherry pick previous changes * workaround for secure storage bug on mac * bump version to 3.19.5 (because breez will need this version anyways) * some code cleanup * some changess didn't get saved * just documenting the issue [skip ci] * undo accidental removal + minor code cleanup * merge conflicts * Minor UI change [skip ci] --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
Matthew Fosse committed
May 6, 2024 at 12:55 UTC
e5be7372362d1ca443ab4434ae5401f2ff04f703
32 files changed
+655
-480
.github/workflows/pr_test_build.yml
+1
-1
@@ -42,7 +42,7 @@ jobs:
42
- name: Flutter action
43
uses: subosito/flutter-action@v1
44
with:
45
- flutter-version: "3.10.x"
45
+ flutter-version: "3.19.5"
46
channel: stable
47
48
- name: Install package dependencies
cw_bitcoin/pubspec.yaml
+4
-1
@@ -43,11 +43,14 @@ dependencies:
43
dev_dependencies:
44
flutter_test:
45
sdk: flutter
46
- build_runner: ^2.1.11
46
+ build_runner: ^2.4.7
47
build_resolvers: ^2.0.9
48
mobx_codegen: ^2.0.7
49
hive_generator: ^1.1.3
50
51
+dependency_overrides:
52
+ watcher: ^1.1.0
53
+
54
# For information on the generic Dart part of this file, see the
55
# following page: https://dart.dev/tools/pub/pubspec
56
cw_bitcoin_cash/pubspec.yaml
+4
-1
@@ -39,10 +39,13 @@ dependencies:
39
dev_dependencies:
40
flutter_test:
41
sdk: flutter
42
- build_runner: ^2.1.11
42
+ build_runner: ^2.4.7
43
mobx_codegen: ^2.0.7
44
hive_generator: ^1.1.3
45
46
+dependency_overrides:
47
+ watcher: ^1.1.0
48
+
49
# For information on the generic Dart part of this file, see the
50
# following page: https://dart.dev/tools/pub/pubspec
51
cw_core/pubspec.yaml
+3
-1
@@ -28,11 +28,13 @@ dependencies:
28
dev_dependencies:
29
flutter_test:
30
sdk: flutter
31
- build_runner: ^2.1.11
31
+ build_runner: ^2.4.7
32
build_resolvers: ^2.0.9
33
mobx_codegen: ^2.0.7
34
hive_generator: ^2.0.1
35
36
+dependency_overrides:
37
+ watcher: ^1.1.0
38
39
# For information on the generic Dart part of this file, see the
40
# following page: https://dart.dev/tools/pub/pubspec
cw_ethereum/pubspec.yaml
+3
-1
@@ -24,11 +24,13 @@ dependency_overrides:
24
git:
25
url: https://github.com/cake-tech/web3dart.git
26
ref: cake
27
+ watcher: ^1.1.0
28
29
dev_dependencies:
30
flutter_test:
31
sdk: flutter
31
- build_runner: ^2.1.11
32
+ build_runner: ^2.4.7
33
+
34
flutter:
35
# assets:
36
# - images/a_dot_burr.jpeg
cw_evm/pubspec.yaml
+2
-1
@@ -36,11 +36,12 @@ dependency_overrides:
36
git:
37
url: https://github.com/cake-tech/ledger-flutter.git
38
ref: cake
39
+ watcher: ^1.1.0
40
41
dev_dependencies:
42
flutter_test:
43
sdk: flutter
43
- build_runner: ^2.1.11
44
+ build_runner: ^2.4.7
45
mobx_codegen: ^2.0.7
46
hive_generator: ^1.1.3
47
flutter_lints: ^2.0.0
cw_haven/pubspec.yaml
+4
-1
@@ -24,11 +24,14 @@ dependencies:
24
dev_dependencies:
25
flutter_test:
26
sdk: flutter
27
- build_runner: ^2.1.11
27
+ build_runner: ^2.4.7
28
mobx_codegen: ^2.0.7
29
build_resolvers: ^2.0.9
30
hive_generator: ^1.1.3
31
32
+dependency_overrides:
33
+ watcher: ^1.1.0
34
+
35
# For information on the generic Dart part of this file, see the
36
# following page: https://dart.dev/tools/pub/pubspec
37
cw_monero/pubspec.yaml
+4
-1
@@ -26,11 +26,14 @@ dependencies:
26
dev_dependencies:
27
flutter_test:
28
sdk: flutter
29
- build_runner: ^2.1.11
29
+ build_runner: ^2.4.7
30
build_resolvers: ^2.0.9
31
mobx_codegen: ^2.0.7
32
hive_generator: ^1.1.3
33
34
+dependency_overrides:
35
+ watcher: ^1.1.0
36
+
37
# For information on the generic Dart part of this file, see the
38
# following page: https://dart.dev/tools/pub/pubspec
39
cw_nano/pubspec.yaml
+4
-1
@@ -32,10 +32,13 @@ dependencies:
32
dev_dependencies:
33
flutter_test:
34
sdk: flutter
35
- build_runner: ^2.1.11
35
+ build_runner: ^2.4.7
36
mobx_codegen: ^2.0.7
37
hive_generator: ^1.1.3
38
39
+dependency_overrides:
40
+ watcher: ^1.1.0
41
+
42
# For information on the generic Dart part of this file, see the
43
# following page: https://dart.dev/tools/pub/pubspec
44
cw_polygon/pubspec.yaml
+3
-1
@@ -28,12 +28,14 @@ dependency_overrides:
28
git:
29
url: https://github.com/cake-tech/web3dart.git
30
ref: cake
31
+ watcher: ^1.1.0
32
33
dev_dependencies:
34
flutter_test:
35
sdk: flutter
36
flutter_lints: ^2.0.0
36
- build_runner: ^2.1.11
37
+ build_runner: ^2.4.7
38
+
39
40
# For information on the generic Dart part of this file, see the
41
# following page: https://dart.dev/tools/pub/pubspec
cw_solana/pubspec.yaml
+4
-1
@@ -26,10 +26,13 @@ dev_dependencies:
26
flutter_test:
27
sdk: flutter
28
flutter_lints: ^2.0.0
29
- build_runner: ^2.1.11
29
+ build_runner: ^2.4.7
30
mobx_codegen: ^2.0.7
31
hive_generator: ^1.1.3
32
33
+dependency_overrides:
34
+ watcher: ^1.1.0
35
+
36
flutter:
37
# assets:
38
# - images/a_dot_burr.jpeg
lib/core/auth_service.dart
+6
-7
@@ -42,12 +42,7 @@ class AuthService with Store {
42
Future<void> setPassword(String password) async {
43
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
44
final encodedPassword = encodedPinCode(pin: password);
45
- // secure storage has a weird bug on macOS, where overwriting a key doesn't work, unless
46
- // we delete what's there first:
47
- if (Platform.isMacOS) {
48
- await secureStorage.delete(key: key);
49
- }
50
- await secureStorage.write(key: key, value: encodedPassword);
45
+ await writeSecureStorage(secureStorage, key: key, value: encodedPassword);
46
}
47
48
Future<bool> canAuthenticate() async {
@@ -74,7 +69,11 @@ class AuthService with Store {
69
70
void saveLastAuthTime() {
71
int timestamp = DateTime.now().millisecondsSinceEpoch;
77
- secureStorage.write(key: SecureKey.lastAuthTimeMilliseconds, value: timestamp.toString());
72
+ writeSecureStorage(
73
+ secureStorage,
74
+ key: SecureKey.lastAuthTimeMilliseconds,
75
+ value: timestamp.toString(),
76
+ );
77
}
78
79
Future<bool> requireAuth() async {
lib/core/backup_service.dart
+8
-9
@@ -1,6 +1,7 @@
1
import 'dart:convert';
2
import 'dart:io';
3
import 'dart:typed_data';
4
+import 'package:cake_wallet/core/secure_storage.dart';
5
import 'package:cake_wallet/themes/theme_list.dart';
6
import 'package:cake_wallet/utils/device_info.dart';
7
import 'package:cw_core/wallet_type.dart';
@@ -275,7 +276,7 @@ class BackupService {
276
if (currentTransactionPriorityKeyLegacy != null)
277
await _sharedPreferences.setInt(
278
PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy);
278
-
279
+
280
if (currentBitcoinElectrumSererId != null)
281
await _sharedPreferences.setInt(
282
PreferencesKey.currentBitcoinElectrumSererIdKey, currentBitcoinElectrumSererId);
@@ -373,16 +374,15 @@ class BackupService {
374
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
375
final backupPassword = keychainJSON[backupPasswordKey] as String;
376
376
- await _flutterSecureStorage.delete(key: backupPasswordKey);
377
- await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword);
377
+ await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword);
378
379
keychainWalletsInfo.forEach((dynamic rawInfo) async {
380
final info = rawInfo as Map<String, dynamic>;
381
await importWalletKeychainInfo(info);
382
});
383
384
- await _flutterSecureStorage.delete(key: pinCodeKey);
385
- await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
384
+ await writeSecureStorage(_flutterSecureStorage,
385
+ key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
386
387
keychainDumpFile.deleteSync();
388
}
@@ -401,16 +401,15 @@ class BackupService {
401
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
402
final backupPassword = keychainJSON[backupPasswordKey] as String;
403
404
- await _flutterSecureStorage.delete(key: backupPasswordKey);
405
- await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword);
404
+ await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword);
405
406
keychainWalletsInfo.forEach((dynamic rawInfo) async {
407
final info = rawInfo as Map<String, dynamic>;
408
await importWalletKeychainInfo(info);
409
});
410
412
- await _flutterSecureStorage.delete(key: pinCodeKey);
413
- await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
411
+ await writeSecureStorage(_flutterSecureStorage,
412
+ key: pinCodeKey, value: encodedPinCode(pin: decodedPin));
413
414
keychainDumpFile.deleteSync();
415
}
lib/core/key_service.dart
+1
-2
@@ -20,8 +20,7 @@ class KeyService {
20
key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
21
final encodedPassword = encodeWalletPassword(password: password);
22
23
- await _secureStorage.delete(key: key);
24
- await _secureStorage.write(key: key, value: encodedPassword);
23
+ await writeSecureStorage(_secureStorage, key: key, value: encodedPassword);
24
}
25
26
Future<void> deleteWalletPassword({required String walletName}) async {
lib/core/secure_storage.dart
+11
@@ -1,4 +1,5 @@
1
import 'dart:async';
2
+import 'dart:io';
3
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
4
// For now, we can create a utility function to handle this.
5
//
@@ -25,3 +26,13 @@ Future<String?> readSecureStorage(FlutterSecureStorage secureStorage, String key
26
27
return result;
28
}
29
+
30
+Future<void> writeSecureStorage(FlutterSecureStorage secureStorage,
31
+ {required String key, required String value}) async {
32
+ // delete the value before writing on macOS because of a weird bug
33
+ // https://github.com/mogol/flutter_secure_storage/issues/581
34
+ if (Platform.isMacOS) {
35
+ await secureStorage.delete(key: key);
36
+ }
37
+ await secureStorage.write(key: key, value: value);
38
+}
lib/entities/biometric_auth.dart
+12
-15
@@ -1,32 +1,29 @@
1
-import 'package:local_auth/local_auth.dart';
1
import 'package:flutter/services.dart';
3
-import 'package:cake_wallet/generated/i18n.dart';
2
+import 'package:flutter_local_authentication/flutter_local_authentication.dart';
3
4
class BiometricAuth {
6
- final _localAuth = LocalAuthentication();
5
+ final _flutterLocalAuthenticationPlugin = FlutterLocalAuthentication();
6
7
Future<bool> isAuthenticated() async {
8
try {
10
- return await _localAuth.authenticate(
11
- localizedReason: S.current.biometric_auth_reason,
12
- options: AuthenticationOptions(
13
- biometricOnly: true,
14
- useErrorDialogs: true,
15
- stickyAuth: false));
16
- } on PlatformException catch (e) {
9
+ final authenticated = await _flutterLocalAuthenticationPlugin.authenticate();
10
+ return authenticated;
11
+ } catch (e) {
12
print(e);
13
}
19
-
14
return false;
15
}
16
17
Future<bool> canCheckBiometrics() async {
18
+ bool canAuthenticate;
19
try {
25
- return await _localAuth.canCheckBiometrics;
26
- } on PlatformException catch (e) {
27
- print(e);
20
+ canAuthenticate = await _flutterLocalAuthenticationPlugin.canAuthenticate();
21
+ await _flutterLocalAuthenticationPlugin.setTouchIDAuthenticationAllowableReuseDuration(0);
22
+ } catch (error) {
23
+ print("Exception checking support. $error");
24
+ canAuthenticate = false;
25
}
26
30
- return false;
27
+ return canAuthenticate;
28
}
29
}
\ No newline at end of file
lib/entities/fs_migration.dart
+3
-2
@@ -1,5 +1,6 @@
1
import 'dart:io';
2
import 'dart:convert';
3
+import 'package:cake_wallet/core/secure_storage.dart';
4
import 'package:collection/collection.dart';
5
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
6
import 'package:shared_preferences/shared_preferences.dart';
@@ -147,8 +148,8 @@ Future<void> ios_migrate_pin() async {
148
149
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
150
final encodedPassword = encodedPinCode(pin: pinPassword);
150
- await flutterSecureStorage.delete(key: key);
151
- await flutterSecureStorage.write(key: key, value: encodedPassword);
151
+ await writeSecureStorage(flutterSecureStorage, key: key, value: encodedPassword);
152
+
153
await prefs.setBool('ios_migration_pin_completed', true);
154
}
155
lib/entities/get_encryption_key.dart
+2
-2
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/core/secure_storage.dart';
2
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
3
import 'package:cw_core/cake_hive.dart';
4
@@ -10,8 +11,7 @@ Future<List<int>> getEncryptionKey(
11
key = CakeHive.generateSecureKey();
12
final keyStringified = key.join(',');
13
String storageKey = 'transactionDescriptionsBoxKey';
13
- await secureStorage.delete(key: storageKey);
14
- await secureStorage.write(key: storageKey, value: keyStringified);
14
+ await writeSecureStorage(secureStorage, key: storageKey, value: keyStringified);
15
} else {
16
key = stringifiedKey.split(',').map((i) => int.parse(i)).toList();
17
}
lib/locales/hausa_intl.dart
+64
@@ -751,6 +751,50 @@ class HaMaterialLocalizations extends GlobalMaterialLocalizations {
751
752
@override
753
String get scrimOnTapHintRaw => "Scrip on Tap";
754
+
755
+ @override
756
+ // TODO: implement collapsedHint
757
+ String get collapsedHint => "collapsedHint";
758
+
759
+ @override
760
+ // TODO: implement expandedHint
761
+ String get expandedHint => "expandedHint";
762
+
763
+ @override
764
+ // TODO: implement expansionTileCollapsedHint
765
+ String get expansionTileCollapsedHint => "expansionTileCollapsedHint";
766
+
767
+ @override
768
+ // TODO: implement expansionTileCollapsedTapHint
769
+ String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint";
770
+
771
+ @override
772
+ // TODO: implement expansionTileExpandedHint
773
+ String get expansionTileExpandedHint => "expansionTileExpandedHint";
774
+
775
+ @override
776
+ // TODO: implement expansionTileExpandedTapHint
777
+ String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint";
778
+
779
+ @override
780
+ // TODO: implement scanTextButtonLabel
781
+ String get scanTextButtonLabel => "scanTextButtonLabel";
782
+
783
+ @override
784
+ // TODO: implement lookUpButtonLabel
785
+ String get lookUpButtonLabel => "lookUpButtonLabel";
786
+
787
+ @override
788
+ // TODO: implement menuDismissLabel
789
+ String get menuDismissLabel => "menuDismissLabel";
790
+
791
+ @override
792
+ // TODO: implement searchWebButtonLabel
793
+ String get searchWebButtonLabel => "searchWebButtonLabel";
794
+
795
+ @override
796
+ // TODO: implement shareButtonLabel
797
+ String get shareButtonLabel => "shareButtonLabel";
798
}
799
800
/// Cupertino Support
@@ -955,4 +999,24 @@ class HaCupertinoLocalizations extends GlobalCupertinoLocalizations {
999
1000
@override
1001
String get noSpellCheckReplacementsLabel => "";
1002
+
1003
+ @override
1004
+ // TODO: implement clearButtonLabel
1005
+ String get clearButtonLabel => "clearButtonLabel";
1006
+
1007
+ @override
1008
+ // TODO: implement lookUpButtonLabel
1009
+ String get lookUpButtonLabel => "lookUpButtonLabel";
1010
+
1011
+ @override
1012
+ // TODO: implement menuDismissLabel
1013
+ String get menuDismissLabel => "menuDismissLabel";
1014
+
1015
+ @override
1016
+ // TODO: implement searchWebButtonLabel
1017
+ String get searchWebButtonLabel => "searchWebButtonLabel";
1018
+
1019
+ @override
1020
+ // TODO: implement shareButtonLabel
1021
+ String get shareButtonLabel => "shareButtonLabel";
1022
}
lib/locales/yoruba_intl.dart
+426
-363
@@ -1,4 +1,3 @@
1
-
1
import 'dart:async';
2
3
import 'package:flutter/cupertino.dart';
@@ -164,62 +163,62 @@ const yoDateSymbols = {
163
'ọjọ́ Àbámẹ́ta',
164
],
165
'STANDALONEWEEKDAYS': <dynamic>[
167
-'Ọjọ́ Ajé',
168
-'Ọjọ́ Ìsẹ́gun',
169
-'Ọjọ́ Ìsẹ́gun-Ẹtì',
170
-'Ọjọ́ Ìsẹ́gun-Ọ̀rú',
171
-'Ọjọ́ Àìkú',
172
-'Ọjọ́ Jímọ̀',
173
-'Ọjọ́ Àbámẹ́ta',
174
-],
175
-'SHORTWEEKDAYS': <dynamic>[
176
-'Ajé',
177
-'Ìsẹ́gun',
178
-'Ìsẹ́gun-Ẹtì',
179
-'Ìsẹ́gun-Ọ̀rú',
180
-'Àìkú',
181
-'Jímọ̀',
182
-'Àbámẹ́ta',
183
-],
184
-'STANDALONESHORTWEEKDAYS': <dynamic>[
185
-'Ajé',
186
-'Ìsẹ́gun',
187
-'Ìsẹ́gun-Ẹtì',
188
-'Ìsẹ́gun-Ọ̀rú',
189
-'Àìkú',
190
-'Jímọ̀',
191
-'Àbámẹ́ta',
192
-],
193
-'NARROWWEEKDAYS': <dynamic>[
194
-'A',
195
-'A',
196
-'Ì',
197
-'A',
198
-'À',
199
-'J',
200
-'À',
201
-],
202
-'STANDALONENARROWWEEKDAYS': <dynamic>[
203
-'A',
204
-'A',
205
-'Ì',
206
-'A',
207
-'À',
208
-'J',
209
-'À',
210
-],
211
-'SHORTQUARTERS': <dynamic>[
212
-'K1',
213
-'K2',
214
-'K3',
215
-'K4',
216
-],
217
-'QUARTERS': <dynamic>[
218
-'1. kwata',
219
-'2. kwata',
220
-'3. kwata',
221
-'4. kwata',
222
-],
166
+ 'Ọjọ́ Ajé',
167
+ 'Ọjọ́ Ìsẹ́gun',
168
+ 'Ọjọ́ Ìsẹ́gun-Ẹtì',
169
+ 'Ọjọ́ Ìsẹ́gun-Ọ̀rú',
170
+ 'Ọjọ́ Àìkú',
171
+ 'Ọjọ́ Jímọ̀',
172
+ 'Ọjọ́ Àbámẹ́ta',
173
+ ],
174
+ 'SHORTWEEKDAYS': <dynamic>[
175
+ 'Ajé',
176
+ 'Ìsẹ́gun',
177
+ 'Ìsẹ́gun-Ẹtì',
178
+ 'Ìsẹ́gun-Ọ̀rú',
179
+ 'Àìkú',
180
+ 'Jímọ̀',
181
+ 'Àbámẹ́ta',
182
+ ],
183
+ 'STANDALONESHORTWEEKDAYS': <dynamic>[
184
+ 'Ajé',
185
+ 'Ìsẹ́gun',
186
+ 'Ìsẹ́gun-Ẹtì',
187
+ 'Ìsẹ́gun-Ọ̀rú',
188
+ 'Àìkú',
189
+ 'Jímọ̀',
190
+ 'Àbámẹ́ta',
191
+ ],
192
+ 'NARROWWEEKDAYS': <dynamic>[
193
+ 'A',
194
+ 'A',
195
+ 'Ì',
196
+ 'A',
197
+ 'À',
198
+ 'J',
199
+ 'À',
200
+ ],
201
+ 'STANDALONENARROWWEEKDAYS': <dynamic>[
202
+ 'A',
203
+ 'A',
204
+ 'Ì',
205
+ 'A',
206
+ 'À',
207
+ 'J',
208
+ 'À',
209
+ ],
210
+ 'SHORTQUARTERS': <dynamic>[
211
+ 'K1',
212
+ 'K2',
213
+ 'K3',
214
+ 'K4',
215
+ ],
216
+ 'QUARTERS': <dynamic>[
217
+ '1. kwata',
218
+ '2. kwata',
219
+ '3. kwata',
220
+ '4. kwata',
221
+ ],
222
'AMPMS': <dynamic>[
223
'a.m.',
224
'p.m.',
@@ -316,339 +315,339 @@ class YoMaterialLocalizations extends GlobalMaterialLocalizations {
315
});
316
317
// #docregion Getters
319
-@override
320
-String get moreButtonTooltip => r'Kò sí ìròhùn tí ó múni';
318
+ @override
319
+ String get moreButtonTooltip => r'Kò sí ìròhùn tí ó múni';
320
322
-@override
323
-String get aboutListTileTitleRaw => r'Fun Àpótí àwọn $applicationname';
321
+ @override
322
+ String get aboutListTileTitleRaw => r'Fun Àpótí àwọn $applicationname';
323
325
-@override
326
-String get alertDialogLabel => r'Ìròhùn Àlàyé';
324
+ @override
325
+ String get alertDialogLabel => r'Ìròhùn Àlàyé';
326
327
// #enddocregion Getters
328
330
-@override
331
-String get anteMeridiemAbbreviation => r'AM';
329
+ @override
330
+ String get anteMeridiemAbbreviation => r'AM';
331
333
-@override
334
-String get backButtonTooltip => r'Fíran';
332
+ @override
333
+ String get backButtonTooltip => r'Fíran';
334
336
-@override
337
-String get cancelButtonLabel => r'FAGILE';
335
+ @override
336
+ String get cancelButtonLabel => r'FAGILE';
337
339
-@override
340
-String get closeButtonLabel => r'KÚ';
338
+ @override
339
+ String get closeButtonLabel => r'KÚ';
340
342
-@override
343
-String get closeButtonTooltip => r'Kú';
341
+ @override
342
+ String get closeButtonTooltip => r'Kú';
343
345
-@override
346
-String get collapsedIconTapHint => r'Tá';
344
+ @override
345
+ String get collapsedIconTapHint => r'Tá';
346
348
-@override
349
-String get continueButtonLabel => r'TÓ WÁ';
347
+ @override
348
+ String get continueButtonLabel => r'TÓ WÁ';
349
351
-@override
352
-String get copyButtonLabel => r'DÚPLÍKÉTÍ';
350
+ @override
351
+ String get copyButtonLabel => r'DÚPLÍKÉTÍ';
352
354
-@override
355
-String get cutButtonLabel => r'TÒ';
353
+ @override
354
+ String get cutButtonLabel => r'TÒ';
355
357
-@override
358
-String get deleteButtonTooltip => r'Máa kú';
356
+ @override
357
+ String get deleteButtonTooltip => r'Máa kú';
358
360
-@override
361
-String get dialogLabel => r'Ìròhùn';
359
+ @override
360
+ String get dialogLabel => r'Ìròhùn';
361
363
-@override
364
-String get drawerLabel => r'Àgbèjọ àwọn àpọ̀tí';
362
+ @override
363
+ String get drawerLabel => r'Àgbèjọ àwọn àpọ̀tí';
364
366
-@override
367
-String get expandedIconTapHint => r'Tá';
365
+ @override
366
+ String get expandedIconTapHint => r'Tá';
367
369
-@override
370
-String get firstPageTooltip => r'Ojú ewe';
368
+ @override
369
+ String get firstPageTooltip => r'Ojú ewe';
370
372
-@override
373
-String get hideAccountsLabel => r'Fí èrò àpótí wáyé sílẹ̀';
371
+ @override
372
+ String get hideAccountsLabel => r'Fí èrò àpótí wáyé sílẹ̀';
373
375
-@override
376
-String get lastPageTooltip => r'Ojú ayé';
374
+ @override
375
+ String get lastPageTooltip => r'Ojú ayé';
376
378
-@override
379
-String get licensesPageTitle => r'Ìròhùn Ọdún';
377
+ @override
378
+ String get licensesPageTitle => r'Ìròhùn Ọdún';
379
381
-@override
382
-String get modalBarrierDismissLabel => r'Sọ';
380
+ @override
381
+ String get modalBarrierDismissLabel => r'Sọ';
382
384
-@override
385
-String get nextMonthTooltip => r'Oṣù kọja';
383
+ @override
384
+ String get nextMonthTooltip => r'Oṣù kọja';
385
387
-@override
388
-String get nextPageTooltip => r'Ojú ọjọ́ kẹta';
386
+ @override
387
+ String get nextPageTooltip => r'Ojú ọjọ́ kẹta';
388
390
-@override
391
-String get okButtonLabel => r'Ò daájú';
392
-@override
389
+ @override
390
+ String get okButtonLabel => r'Ò daájú';
391
+ @override
392
// A custom drawer tooltip message.
394
-String get openAppDrawerTooltip => r'Aya ntọju Iwe Awọn Aka';
393
+ String get openAppDrawerTooltip => r'Aya ntọju Iwe Awọn Aka';
394
395
// #docregion Raw
397
-@override
398
-String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow lati $rowCount';
396
+ @override
397
+ String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow lati $rowCount';
398
400
-@override
401
-String get pageRowsInfoTitleApproximateRaw => r'$firstRow–$lastRow lati kiakia $rowCount';
399
+ @override
400
+ String get pageRowsInfoTitleApproximateRaw => r'$firstRow–$lastRow lati kiakia $rowCount';
401
// #enddocregion Raw
402
404
-@override
405
-String get pasteButtonLabel => r'TÌ';
403
+ @override
404
+ String get pasteButtonLabel => r'TÌ';
405
+
406
+ @override
407
+ String get popupMenuLabel => r'Meniu Pop-up';
408
407
-@override
408
-String get popupMenuLabel => r'Meniu Pop-up';
409
+ @override
410
+ String get menuBarMenuLabel => r'Meniu Akọkọ';
411
410
-@override
411
-String get menuBarMenuLabel => r'Meniu Akọkọ';
412
+ @override
413
+ String get postMeridiemAbbreviation => r'PM';
414
413
-@override
414
-String get postMeridiemAbbreviation => r'PM';
415
+ @override
416
+ String get previousMonthTooltip => r'Oṣu Kanakana';
417
416
-@override
417
-String get previousMonthTooltip => r'Oṣu Kanakana';
418
+ @override
419
+ String get previousPageTooltip => r'Ojú ewé akọkọ kan';
420
419
-@override
420
-String get previousPageTooltip => r'Ojú ewé akọkọ kan';
421
+ @override
422
+ String get refreshIndicatorSemanticLabel => r'Gbiyanju';
423
422
-@override
423
-String get refreshIndicatorSemanticLabel => r'Gbiyanju';
424
+ @override
425
+ String? get remainingTextFieldCharacterCountFew => null;
426
425
-@override
426
-String? get remainingTextFieldCharacterCountFew => null;
427
+ @override
428
+ String? get remainingTextFieldCharacterCountMany => null;
429
428
-@override
429
-String? get remainingTextFieldCharacterCountMany => null;
430
+ @override
431
+ String get remainingTextFieldCharacterCountOne => r'1 àmì báálẹ̀';
432
431
-@override
432
-String get remainingTextFieldCharacterCountOne => r'1 àmì báálẹ̀';
433
+ @override
434
+ String get remainingTextFieldCharacterCountOther => r'$remainingCount àmì báálẹ̀';
435
434
-@override
435
-String get remainingTextFieldCharacterCountOther => r'$remainingCount àmì báálẹ̀';
436
+ @override
437
+ String? get remainingTextFieldCharacterCountTwo => null;
438
437
-@override
438
-String? get remainingTextFieldCharacterCountTwo => null;
439
+ @override
440
+ String get remainingTextFieldCharacterCountZero => r'Kò sí ìwọlé létà láti ń ṣe';
441
440
-@override
441
-String get remainingTextFieldCharacterCountZero => r'Kò sí ìwọlé létà láti ń ṣe';
442
+ @override
443
+ String get reorderItemDown => r'Jù sí ilẹ';
444
443
-@override
444
-String get reorderItemDown => r'Jù sí ilẹ';
445
+ @override
446
+ String get reorderItemLeft => r'Jù sí àrà';
447
446
-@override
447
-String get reorderItemLeft => r'Jù sí àrà';
448
+ @override
449
+ String get reorderItemRight => r'Jù sí òtútù';
450
449
-@override
450
-String get reorderItemRight => r'Jù sí òtútù';
451
+ @override
452
+ String get reorderItemToEnd => r'Jù sí ìbẹ̀jì';
453
452
-@override
453
-String get reorderItemToEnd => r'Jù sí ìbẹ̀jì';
454
+ @override
455
+ String get reorderItemToStart => r'Jù sí àkọ́kọ́';
456
455
-@override
456
-String get reorderItemToStart => r'Jù sí àkọ́kọ́';
457
+ @override
458
+ String get reorderItemUp => r'Jù sí ọ̀rùn';
459
458
-@override
459
-String get reorderItemUp => r'Jù sí ọ̀rùn';
460
+ @override
461
+ String get rowsPerPageTitle => r'Ìlò Fún àwọn Ìtọ́kasíwájú:';
462
461
-@override
462
-String get rowsPerPageTitle => r'Ìlò Fún àwọn Ìtọ́kasíwájú:';
463
+ @override
464
+ ScriptCategory get scriptCategory => ScriptCategory.englishLike;
465
464
-@override
465
-ScriptCategory get scriptCategory => ScriptCategory.englishLike;
466
+ @override
467
+ String get searchFieldLabel => 'Ṣẹda';
468
467
-@override
468
-String get searchFieldLabel => 'Ṣẹda';
469
+ @override
470
+ String get selectAllButtonLabel => 'FADỌHỌN DỌFÚN GBÁJÚMỌ̀';
471
470
-@override
471
-String get selectAllButtonLabel => 'FADỌHỌN DỌFÚN GBÁJÚMỌ̀';
472
+ @override
473
+ String? get selectedRowCountTitleFew => null;
474
473
-@override
474
-String? get selectedRowCountTitleFew => null;
475
+ @override
476
+ String? get selectedRowCountTitleMany => null;
477
476
-@override
477
-String? get selectedRowCountTitleMany => null;
478
+ @override
479
+ String get selectedRowCountTitleOne => '1 káyé';
480
479
-@override
480
-String get selectedRowCountTitleOne => '1 káyé';
481
+ @override
482
+ String get selectedRowCountTitleOther => r'$selectedRowCount káyé';
483
482
-@override
483
-String get selectedRowCountTitleOther => r'$selectedRowCount káyé';
484
+ @override
485
+ String? get selectedRowCountTitleTwo => null;
486
485
-@override
486
-String? get selectedRowCountTitleTwo => null;
487
+ @override
488
+ String get selectedRowCountTitleZero => 'Kò sí káyé ti o wọlé';
489
488
-@override
489
-String get selectedRowCountTitleZero => 'Kò sí káyé ti o wọlé';
490
+ @override
491
+ String get showAccountsLabel => 'Fi iyipada mu kọ';
492
491
-@override
492
-String get showAccountsLabel => 'Fi iyipada mu kọ';
493
+ @override
494
+ String get showMenuTooltip => 'Fi Meniu mu kọ';
495
494
-@override
495
-String get showMenuTooltip => 'Fi Meniu mu kọ';
496
+ @override
497
+ String get signedInLabel => 'Ọ̀nà';
498
497
-@override
498
-String get signedInLabel => 'Ọ̀nà';
499
+ @override
500
+ String get tabLabelRaw => r'Àwọn tabin $tabIndex lati $tabCount';
501
500
-@override
501
-String get tabLabelRaw => r'Àwọn tabin $tabIndex lati $tabCount';
502
-
502
@override
504
-TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a;
503
+ TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a;
504
506
-@override
507
-String get timePickerHourModeAnnouncement => 'Tuntun waqtu lọ';
505
+ @override
506
+ String get timePickerHourModeAnnouncement => 'Tuntun waqtu lọ';
507
509
-@override
510
-String get timePickerMinuteModeAnnouncement => 'Tuntun daɗi minti';
508
+ @override
509
+ String get timePickerMinuteModeAnnouncement => 'Tuntun daɗi minti';
510
512
-@override
513
-String get viewLicensesButtonLabel => 'WO NIKI';
511
+ @override
512
+ String get viewLicensesButtonLabel => 'WO NIKI';
513
515
-@override
516
-List<String> get narrowWeekdays => const <String>['L', 'L', 'A', 'O', 'Ọ', 'Ẹ', 'Ẹ'];
514
+ @override
515
+ List<String> get narrowWeekdays => const <String>['L', 'L', 'A', 'O', 'Ọ', 'Ẹ', 'Ẹ'];
516
518
-@override
519
-int get firstDayOfWeekIndex => 0;
517
+ @override
518
+ int get firstDayOfWeekIndex => 0;
519
521
-static const LocalizationsDelegate<MaterialLocalizations> delegate =
522
-_YoMaterialLocalizationsDelegate();
520
+ static const LocalizationsDelegate<MaterialLocalizations> delegate =
521
+ _YoMaterialLocalizationsDelegate();
522
524
-@override
525
-String get calendarModeButtonLabel => 'Tọ́rọ̀ kálẹ̀ndà';
523
+ @override
524
+ String get calendarModeButtonLabel => 'Tọ́rọ̀ kálẹ̀ndà';
525
527
-@override
528
-String get dateHelpText => 'mm/dd/yyyy';
526
+ @override
527
+ String get dateHelpText => 'mm/dd/yyyy';
528
530
-@override
531
-String get dateInputLabel => 'Firanṣẹ̀ Ọjọ́';
529
+ @override
530
+ String get dateInputLabel => 'Firanṣẹ̀ Ọjọ́';
531
533
-@override
534
-String get dateOutOfRangeLabel => 'Nínú iwọ̀ lọ́wọ́';
532
+ @override
533
+ String get dateOutOfRangeLabel => 'Nínú iwọ̀ lọ́wọ́';
534
536
-@override
537
-String get datePickerHelpText => 'WÁSÍ';
535
+ @override
536
+ String get datePickerHelpText => 'WÁSÍ';
537
539
-@override
540
-String get dateRangeEndDateSemanticLabelRaw => r'Ọjọ́ tuntun to ṣà';
538
+ @override
539
+ String get dateRangeEndDateSemanticLabelRaw => r'Ọjọ́ tuntun to ṣà';
540
542
-@override
543
-String get dateRangeEndLabel => 'Ọjọ́ tuntun to ṣà';
541
+ @override
542
+ String get dateRangeEndLabel => 'Ọjọ́ tuntun to ṣà';
543
545
-@override
546
-String get dateRangePickerHelpText => 'WÁSÍ ÌGBÀ';
544
+ @override
545
+ String get dateRangePickerHelpText => 'WÁSÍ ÌGBÀ';
546
548
-@override
549
-String get dateRangeStartDateSemanticLabelRaw => 'Ọjọ́ tuntun ti dá';
547
+ @override
548
+ String get dateRangeStartDateSemanticLabelRaw => 'Ọjọ́ tuntun ti dá';
549
551
-@override
552
-String get dateRangeStartLabel => 'Ọjọ́ tuntun ti dá';
550
+ @override
551
+ String get dateRangeStartLabel => 'Ọjọ́ tuntun ti dá';
552
554
-@override
555
-String get dateSeparator => '/';
553
+ @override
554
+ String get dateSeparator => '/';
555
557
-@override
558
-String get dialModeButtonLabel => 'Tọ́rọ̀ wakati';
556
+ @override
557
+ String get dialModeButtonLabel => 'Tọ́rọ̀ wakati';
558
560
-@override
561
-String get inputDateModeButtonLabel => 'Tọ́rọ̀ firanṣẹ̀ ọjọ́';
559
+ @override
560
+ String get inputDateModeButtonLabel => 'Tọ́rọ̀ firanṣẹ̀ ọjọ́';
561
563
-@override
564
-String get inputTimeModeButtonLabel => 'Tọ́rọ̀ wakati bayi lọ́wọ́';
562
+ @override
563
+ String get inputTimeModeButtonLabel => 'Tọ́rọ̀ wakati bayi lọ́wọ́';
564
566
-@override
567
-String get invalidDateFormatLabel => 'Akọ́kọ́tọ́ tó jẹ́kúnrin';
565
+ @override
566
+ String get invalidDateFormatLabel => 'Akọ́kọ́tọ́ tó jẹ́kúnrin';
567
569
-@override
570
-String get invalidDateRangeLabel => 'Àmì jẹ́ káàkiri lẹ́yìn ilé';
568
+ @override
569
+ String get invalidDateRangeLabel => 'Àmì jẹ́ káàkiri lẹ́yìn ilé';
570
572
-@override
573
-String get invalidTimeLabel => 'Akọ́kọ́tọ́ àkójọ ìwádìí';
571
+ @override
572
+ String get invalidTimeLabel => 'Akọ́kọ́tọ́ àkójọ ìwádìí';
573
575
-@override
576
-String get licensesPackageDetailTextOther => r'$licenseCount àwọn níkí';
574
+ @override
575
+ String get licensesPackageDetailTextOther => r'$licenseCount àwọn níkí';
576
578
-@override
579
-String get saveButtonLabel => 'TÙN DÁRA';
577
+ @override
578
+ String get saveButtonLabel => 'TÙN DÁRA';
579
581
-@override
582
-String get selectYearSemanticsLabel => 'Fọ́ọ̀ shẹ́kàrà';
580
+ @override
581
+ String get selectYearSemanticsLabel => 'Fọ́ọ̀ shẹ́kàrà';
582
584
-@override
585
-String get timePickerDialHelpText => 'WÁSÍ WÁKÀTÌ';
583
+ @override
584
+ String get timePickerDialHelpText => 'WÁSÍ WÁKÀTÌ';
585
587
-@override
588
-String get timePickerHourLabel => 'Wákàtì àṣà';
586
+ @override
587
+ String get timePickerHourLabel => 'Wákàtì àṣà';
588
590
-@override
591
-String get timePickerInputHelpText => 'Shìgárà wákàtì';
589
+ @override
590
+ String get timePickerInputHelpText => 'Shìgárà wákàtì';
591
593
-@override
594
-String get timePickerMinuteLabel => 'Mìntì';
592
+ @override
593
+ String get timePickerMinuteLabel => 'Mìntì';
594
596
-@override
597
-String get unspecifiedDate => 'Ọjọ̀kúnrin';
595
+ @override
596
+ String get unspecifiedDate => 'Ọjọ̀kúnrin';
597
599
-@override
600
-String get unspecifiedDateRange => 'Ọjọ̀kúnrin àdáyọ̀';
598
+ @override
599
+ String get unspecifiedDateRange => 'Ọjọ̀kúnrin àdáyọ̀';
600
602
-@override
603
-String get keyboardKeyAlt => 'Alt';
601
+ @override
602
+ String get keyboardKeyAlt => 'Alt';
603
605
-@override
606
-String get keyboardKeyAltGraph => 'AltGraph';
604
+ @override
605
+ String get keyboardKeyAltGraph => 'AltGraph';
606
608
-@override
609
-String get keyboardKeyBackspace => 'Báckspàcè';
607
+ @override
608
+ String get keyboardKeyBackspace => 'Báckspàcè';
609
611
-@override
612
-String get keyboardKeyCapsLock => 'Caps Lock';
610
+ @override
611
+ String get keyboardKeyCapsLock => 'Caps Lock';
612
614
-@override
615
-String get keyboardKeyChannelDown => 'Báyàkàmmàlàsàké';
613
+ @override
614
+ String get keyboardKeyChannelDown => 'Báyàkàmmàlàsàké';
615
617
-@override
618
-String get keyboardKeyChannelUp => 'Yíkàmmàlàsàké';
616
+ @override
617
+ String get keyboardKeyChannelUp => 'Yíkàmmàlàsàké';
618
620
-@override
621
-String get keyboardKeyControl => 'Kọ́ntírọ̀l';
619
+ @override
620
+ String get keyboardKeyControl => 'Kọ́ntírọ̀l';
621
623
-@override
624
-String get keyboardKeyDelete => 'Shápè';
622
+ @override
623
+ String get keyboardKeyDelete => 'Shápè';
624
626
-@override
627
-String get keyboardKeyEject => 'Èjẹ̀tì';
625
+ @override
626
+ String get keyboardKeyEject => 'Èjẹ̀tì';
627
629
-@override
630
-String get keyboardKeyEnd => 'Tàbí';
628
+ @override
629
+ String get keyboardKeyEnd => 'Tàbí';
630
632
-@override
633
-String get keyboardKeyEscape => 'Tòkè';
631
+ @override
632
+ String get keyboardKeyEscape => 'Tòkè';
633
634
@override
636
-String get keyboardKeyFn => 'Fn';
635
+ String get keyboardKeyFn => 'Fn';
636
638
-@override
639
-String get keyboardKeyHome => 'Ile';
637
+ @override
638
+ String get keyboardKeyHome => 'Ile';
639
641
-@override
642
-String get keyboardKeyInsert => 'Fi sori';
640
+ @override
641
+ String get keyboardKeyInsert => 'Fi sori';
642
644
-@override
645
-String get keyboardKeyMeta => 'Meta';
643
+ @override
644
+ String get keyboardKeyMeta => 'Meta';
645
647
-@override
648
-String get keyboardKeyMetaMacOs => 'Amfani pẹlu Command';
646
+ @override
647
+ String get keyboardKeyMetaMacOs => 'Amfani pẹlu Command';
648
650
-@override
651
-String get keyboardKeyMetaWindows => 'Windows';
649
+ @override
650
+ String get keyboardKeyMetaWindows => 'Windows';
651
652
@override
653
String get keyboardKeyNumLock => 'Num Lock';
@@ -751,6 +750,50 @@ String get keyboardKeyMetaWindows => 'Windows';
750
751
@override
752
String get scrimOnTapHintRaw => "Scrip on Tap";
753
+
754
+ @override
755
+ // TODO: implement collapsedHint
756
+ String get collapsedHint => "collapsedHint";
757
+
758
+ @override
759
+ // TODO: implement expandedHint
760
+ String get expandedHint => "expandedHint";
761
+
762
+ @override
763
+ // TODO: implement expansionTileCollapsedHint
764
+ String get expansionTileCollapsedHint => "expansionTileCollapsedHint";
765
+
766
+ @override
767
+ // TODO: implement expansionTileCollapsedTapHint
768
+ String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint";
769
+
770
+ @override
771
+ // TODO: implement expansionTileExpandedHint
772
+ String get expansionTileExpandedHint => "expansionTileExpandedHint";
773
+
774
+ @override
775
+ // TODO: implement expansionTileExpandedTapHint
776
+ String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint";
777
+
778
+ @override
779
+ // TODO: implement scanTextButtonLabel
780
+ String get scanTextButtonLabel => "scanTextButtonLabel";
781
+
782
+ @override
783
+ // TODO: implement lookUpButtonLabel
784
+ String get lookUpButtonLabel => "lookUpButtonLabel";
785
+
786
+ @override
787
+ // TODO: implement menuDismissLabel
788
+ String get menuDismissLabel => "menuDismissLabel";
789
+
790
+ @override
791
+ // TODO: implement searchWebButtonLabel
792
+ String get searchWebButtonLabel => "searchWebButtonLabel";
793
+
794
+ @override
795
+ // TODO: implement shareButtonLabel
796
+ String get shareButtonLabel => "shareButtonLabel";
797
}
798
799
/// Cupertino Support
@@ -821,138 +864,158 @@ class YoCupertinoLocalizations extends GlobalCupertinoLocalizations {
864
required super.singleDigitSecondFormat,
865
});
866
824
-@override
825
-String get alertDialogLabel => 'Àdàkárò';
867
+ @override
868
+ String get alertDialogLabel => 'Àdàkárò';
869
827
-@override
828
-String get anteMeridiemAbbreviation => 'AM';
870
+ @override
871
+ String get anteMeridiemAbbreviation => 'AM';
872
830
-@override
831
-String get copyButtonLabel => 'Kòpy';
873
+ @override
874
+ String get copyButtonLabel => 'Kòpy';
875
833
-@override
834
-String get cutButtonLabel => 'Kọ́t';
876
+ @override
877
+ String get cutButtonLabel => 'Kọ́t';
878
836
-@override
837
-String get datePickerDateOrderString => 'mdy';
879
+ @override
880
+ String get datePickerDateOrderString => 'mdy';
881
839
-@override
840
-String get datePickerDateTimeOrderString => 'date_time_dayPeriod';
882
+ @override
883
+ String get datePickerDateTimeOrderString => 'date_time_dayPeriod';
884
842
-@override
843
-String? get datePickerHourSemanticsLabelFew => null;
885
+ @override
886
+ String? get datePickerHourSemanticsLabelFew => null;
887
845
-@override
846
-String? get datePickerHourSemanticsLabelMany => null;
888
+ @override
889
+ String? get datePickerHourSemanticsLabelMany => null;
890
848
-@override
849
-String? get datePickerHourSemanticsLabelOne => r"$hour o'clock";
891
+ @override
892
+ String? get datePickerHourSemanticsLabelOne => r"$hour o'clock";
893
851
-@override
852
-String get datePickerHourSemanticsLabelOther => r"$hour o'clock";
894
+ @override
895
+ String get datePickerHourSemanticsLabelOther => r"$hour o'clock";
896
854
-@override
855
-String? get datePickerHourSemanticsLabelTwo => null;
897
+ @override
898
+ String? get datePickerHourSemanticsLabelTwo => null;
899
857
-@override
858
-String? get datePickerHourSemanticsLabelZero => null;
900
+ @override
901
+ String? get datePickerHourSemanticsLabelZero => null;
902
860
-@override
861
-String? get datePickerMinuteSemanticsLabelFew => null;
903
+ @override
904
+ String? get datePickerMinuteSemanticsLabelFew => null;
905
863
-@override
864
-String? get datePickerMinuteSemanticsLabelMany => null;
906
+ @override
907
+ String? get datePickerMinuteSemanticsLabelMany => null;
908
866
-@override
867
-String? get datePickerMinuteSemanticsLabelOne => '1 wakati';
909
+ @override
910
+ String? get datePickerMinuteSemanticsLabelOne => '1 wakati';
911
869
-@override
870
-String get datePickerMinuteSemanticsLabelOther => r'$minute wakati';
912
+ @override
913
+ String get datePickerMinuteSemanticsLabelOther => r'$minute wakati';
914
872
-@override
873
-String? get datePickerMinuteSemanticsLabelTwo => null;
915
+ @override
916
+ String? get datePickerMinuteSemanticsLabelTwo => null;
917
875
-@override
876
-String? get datePickerMinuteSemanticsLabelZero => null;
918
+ @override
919
+ String? get datePickerMinuteSemanticsLabelZero => null;
920
878
-@override
879
-String get modalBarrierDismissLabel => 'Búta';
921
+ @override
922
+ String get modalBarrierDismissLabel => 'Búta';
923
881
-@override
882
-String get pasteButtonLabel => 'Tẹ́ẹ́';
924
+ @override
925
+ String get pasteButtonLabel => 'Tẹ́ẹ́';
926
884
-@override
885
-String get postMeridiemAbbreviation => 'PM';
927
+ @override
928
+ String get postMeridiemAbbreviation => 'PM';
929
887
-@override
888
-String get searchTextFieldPlaceholderLabel => 'Wúró àtúntà';
930
+ @override
931
+ String get searchTextFieldPlaceholderLabel => 'Wúró àtúntà';
932
890
-@override
891
-String get selectAllButtonLabel => 'Fírànsé gbógbo';
933
+ @override
934
+ String get selectAllButtonLabel => 'Fírànsé gbógbo';
935
893
-@override
894
-String get tabSemanticsLabelRaw => r'Tab $tabIndex nínú $tabCount';
936
+ @override
937
+ String get tabSemanticsLabelRaw => r'Tab $tabIndex nínú $tabCount';
938
896
-@override
897
-String? get timerPickerHourLabelFew => null;
939
+ @override
940
+ String? get timerPickerHourLabelFew => null;
941
899
-@override
900
-String? get timerPickerHourLabelMany => null;
942
+ @override
943
+ String? get timerPickerHourLabelMany => null;
944
902
-@override
903
-String? get timerPickerHourLabelOne => 'òǹdì';
945
+ @override
946
+ String? get timerPickerHourLabelOne => 'òǹdì';
947
905
-@override
906
-String get timerPickerHourLabelOther => 'òǹdì';
948
+ @override
949
+ String get timerPickerHourLabelOther => 'òǹdì';
950
908
-@override
909
-String? get timerPickerHourLabelTwo => null;
951
+ @override
952
+ String? get timerPickerHourLabelTwo => null;
953
911
-@override
912
-String? get timerPickerHourLabelZero => null;
954
+ @override
955
+ String? get timerPickerHourLabelZero => null;
956
914
-@override
915
-String? get timerPickerMinuteLabelFew => null;
957
+ @override
958
+ String? get timerPickerMinuteLabelFew => null;
959
917
-@override
918
-String? get timerPickerMinuteLabelMany => null;
960
+ @override
961
+ String? get timerPickerMinuteLabelMany => null;
962
920
-@override
921
-String? get timerPickerMinuteLabelOne => 'wakati.';
963
+ @override
964
+ String? get timerPickerMinuteLabelOne => 'wakati.';
965
923
-@override
924
-String get timerPickerMinuteLabelOther => 'wakati.';
966
+ @override
967
+ String get timerPickerMinuteLabelOther => 'wakati.';
968
926
-@override
927
-String? get timerPickerMinuteLabelTwo => null;
969
+ @override
970
+ String? get timerPickerMinuteLabelTwo => null;
971
929
-@override
930
-String? get timerPickerMinuteLabelZero => null;
972
+ @override
973
+ String? get timerPickerMinuteLabelZero => null;
974
932
-@override
933
-String? get timerPickerSecondLabelFew => null;
975
+ @override
976
+ String? get timerPickerSecondLabelFew => null;
977
935
-@override
936
-String? get timerPickerSecondLabelMany => null;
978
+ @override
979
+ String? get timerPickerSecondLabelMany => null;
980
938
-@override
939
-String? get timerPickerSecondLabelOne => 'dákìkà.';
981
+ @override
982
+ String? get timerPickerSecondLabelOne => 'dákìkà.';
983
941
-@override
942
-String get timerPickerSecondLabelOther => 'dákìkà.';
984
+ @override
985
+ String get timerPickerSecondLabelOther => 'dákìkà.';
986
944
-@override
945
-String? get timerPickerSecondLabelTwo => null;
987
+ @override
988
+ String? get timerPickerSecondLabelTwo => null;
989
947
-@override
948
-String? get timerPickerSecondLabelZero => null;
990
+ @override
991
+ String? get timerPickerSecondLabelZero => null;
992
950
-@override
951
-String get todayLabel => 'Oyọ';
993
+ @override
994
+ String get todayLabel => 'Oyọ';
995
996
static const LocalizationsDelegate<CupertinoLocalizations> delegate =
997
_YoCupertinoLocalizationsDelegate();
998
999
@override
1000
String get noSpellCheckReplacementsLabel => "";
958
-}
\ No newline at end of file
1001
+
1002
+ @override
1003
+ // TODO: implement clearButtonLabel
1004
+ String get clearButtonLabel => "clearButtonLabel";
1005
+
1006
+ @override
1007
+ // TODO: implement lookUpButtonLabel
1008
+ String get lookUpButtonLabel => "lookUpButtonLabel";
1009
+
1010
+ @override
1011
+ // TODO: implement menuDismissLabel
1012
+ String get menuDismissLabel => "menuDismissLabel";
1013
+
1014
+ @override
1015
+ // TODO: implement searchWebButtonLabel
1016
+ String get searchWebButtonLabel => "searchWebButtonLabel";
1017
+
1018
+ @override
1019
+ // TODO: implement shareButtonLabel
1020
+ String get shareButtonLabel => "shareButtonLabel";
1021
+}
lib/src/screens/settings/desktop_settings/desktop_settings_page.dart
+29
-31
@@ -12,7 +12,6 @@ final _settingsNavigatorKey = GlobalKey<NavigatorState>();
12
class DesktopSettingsPage extends StatefulWidget {
13
const DesktopSettingsPage({super.key});
14
15
-
15
@override
16
State<DesktopSettingsPage> createState() => _DesktopSettingsPageState();
17
}
@@ -33,22 +32,21 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
32
return Scaffold(
33
body: Container(
34
height: MediaQuery.of(context).size.height,
36
- child: Column(
37
- mainAxisSize: MainAxisSize.min,
38
- crossAxisAlignment: CrossAxisAlignment.start,
35
+ child: Row(
36
children: [
40
- Padding(
41
- padding: const EdgeInsets.fromLTRB(24, 24, 24, 4),
42
- child: Text(
43
- S.current.settings,
44
- style: textXLarge(),
45
- ),
46
- ),
37
Expanded(
48
- child: Row(
38
+ flex: 1,
39
+ child: Column(
40
+ crossAxisAlignment: CrossAxisAlignment.start,
41
children: [
42
+ Padding(
43
+ padding: const EdgeInsets.fromLTRB(24, 24, 24, 4),
44
+ child: Text(
45
+ S.current.settings,
46
+ style: textXLarge(),
47
+ ),
48
+ ),
49
Expanded(
51
- flex: 1,
50
child: ListView.separated(
51
padding: EdgeInsets.only(top: 0),
52
itemBuilder: (_, index) {
@@ -78,27 +76,27 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
76
itemCount: itemCount,
77
),
78
),
81
- Flexible(
82
- flex: 2,
83
- child: ConstrainedBox(
84
- constraints: BoxConstraints(maxWidth: 500),
85
- child: Navigator(
86
- key: _settingsNavigatorKey,
87
- initialRoute: Routes.empty_no_route,
88
- onGenerateRoute: (settings) => Router.createRoute(settings),
89
- onGenerateInitialRoutes:
90
- (NavigatorState navigator, String initialRouteName) {
91
- return [
92
- navigator
93
- .widget.onGenerateRoute!(RouteSettings(name: initialRouteName))!
94
- ];
95
- },
96
- ),
97
- ),
98
- )
79
],
80
),
81
),
82
+ Flexible(
83
+ flex: 2,
84
+ child: ConstrainedBox(
85
+ constraints: BoxConstraints(maxWidth: 500),
86
+ child: Navigator(
87
+ key: _settingsNavigatorKey,
88
+ initialRoute: Routes.empty_no_route,
89
+ onGenerateRoute: (settings) => Router.createRoute(settings),
90
+ onGenerateInitialRoutes:
91
+ (NavigatorState navigator, String initialRouteName) {
92
+ return [
93
+ navigator
94
+ .widget.onGenerateRoute!(RouteSettings(name: initialRouteName))!
95
+ ];
96
+ },
97
+ ),
98
+ ),
99
+ )
100
],
101
),
102
),
lib/src/screens/settings/security_backup_page.dart
+3
-1
@@ -1,3 +1,5 @@
1
+import 'dart:io';
2
+
3
import 'package:cake_wallet/core/auth_service.dart';
4
import 'package:cake_wallet/entities/pin_code_required_duration.dart';
5
import 'package:cake_wallet/routes.dart';
@@ -58,7 +60,7 @@ class SecurityBackupPage extends BasePage {
60
.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
61
),
62
),
61
- if (DeviceInfo.instance.isMobile)
63
+ if (DeviceInfo.instance.isMobile || Platform.isMacOS || Platform.isLinux)
64
Observer(builder: (_) {
65
return SettingsSwitcherCell(
66
title: S.current.settings_allow_biometrical_authentication,
lib/src/screens/settings/tor_page.dart
+2
-2
@@ -146,7 +146,7 @@ class ConnectScreen extends StatelessWidget {
146
ElevatedButton(
147
onPressed: connect,
148
style: ElevatedButton.styleFrom(
149
- primary: Colors.blue,
149
+ // primary: Colors.blue,
150
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
151
shape: RoundedRectangleBorder(
152
borderRadius: BorderRadius.circular(30),
@@ -211,7 +211,7 @@ class DisconnectScreen extends StatelessWidget {
211
ElevatedButton(
212
onPressed: disconnect,
213
style: ElevatedButton.styleFrom(
214
- primary: Colors.red,
214
+ // primary: Colors.red,
215
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15),
216
shape: RoundedRectangleBorder(
217
borderRadius: BorderRadius.circular(30),
lib/src/screens/support_chat/widgets/chatwoot_widget.dart
+2
-2
@@ -1,5 +1,6 @@
1
import 'dart:convert';
2
3
+import 'package:cake_wallet/core/secure_storage.dart';
4
import 'package:flutter/material.dart';
5
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
6
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
@@ -58,7 +59,6 @@ class ChatwootWidgetState extends State<ChatwootWidget> {
59
}
60
61
Future<void> storeCookie(String value) async {
61
- await widget.secureStorage.delete(key: COOKIE_KEY);
62
- await widget.secureStorage.write(key: COOKIE_KEY, value: value);
62
+ await writeSecureStorage(widget.secureStorage, key: COOKIE_KEY, value: value);
63
}
64
}
lib/src/widgets/validable_annotated_editable_text.dart
+10
-4
@@ -1,8 +1,14 @@
1
-import 'package:cake_wallet/core/seed_validator.dart';
2
-import 'package:cw_core/wallet_type.dart';
1
import 'package:flutter/material.dart';
2
5
-class Annotation extends Comparable<Annotation> {
3
+
4
+extension Compare<T> on Comparable<T> {
5
+ bool operator <=(T other) => compareTo(other) <= 0;
6
+ bool operator >=(T other) => compareTo(other) >= 0;
7
+ bool operator <(T other) => compareTo(other) < 0;
8
+ bool operator >(T other) => compareTo(other) > 0;
9
+}
10
+
11
+class Annotation implements Comparable<Annotation> {
12
Annotation({required this.range, required this.style});
13
14
final TextRange range;
@@ -12,7 +18,7 @@ class Annotation extends Comparable<Annotation> {
18
int compareTo(Annotation other) => range.start.compareTo(other.range.start);
19
}
20
15
-class TextAnnotation extends Comparable<TextAnnotation> {
21
+class TextAnnotation implements Comparable<TextAnnotation> {
22
TextAnnotation({required this.text, required this.style});
23
24
final TextStyle style;
lib/store/settings_store.dart
+21
-16
@@ -2,6 +2,7 @@ import 'dart:io';
2
3
import 'package:cake_wallet/bitcoin/bitcoin.dart';
4
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
5
+import 'package:cake_wallet/core/secure_storage.dart';
6
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
7
import 'package:cake_wallet/entities/provider_types.dart';
8
import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
@@ -434,79 +435,83 @@ abstract class SettingsStoreBase with Store {
435
// secure storage keys:
436
reaction(
437
(_) => allowBiometricalAuthentication,
437
- (bool biometricalAuthentication) => secureStorage.write(
438
+ (bool biometricalAuthentication) => writeSecureStorage(secureStorage,
439
key: SecureKey.allowBiometricalAuthenticationKey,
440
value: biometricalAuthentication.toString()));
441
442
reaction(
443
(_) => selectedCake2FAPreset,
443
- (Cake2FAPresetsOptions selectedCake2FAPreset) => secureStorage.write(
444
+ (Cake2FAPresetsOptions selectedCake2FAPreset) => writeSecureStorage(secureStorage,
445
key: SecureKey.selectedCake2FAPreset,
446
value: selectedCake2FAPreset.serialize().toString()));
447
448
reaction(
449
(_) => shouldRequireTOTP2FAForAccessingWallet,
449
- (bool requireTOTP2FAForAccessingWallet) => secureStorage.write(
450
+ (bool requireTOTP2FAForAccessingWallet) => writeSecureStorage(secureStorage,
451
key: SecureKey.shouldRequireTOTP2FAForAccessingWallet,
452
value: requireTOTP2FAForAccessingWallet.toString()));
453
454
reaction(
455
(_) => shouldRequireTOTP2FAForSendsToContact,
455
- (bool requireTOTP2FAForSendsToContact) => secureStorage.write(
456
+ (bool requireTOTP2FAForSendsToContact) => writeSecureStorage(secureStorage,
457
key: SecureKey.shouldRequireTOTP2FAForSendsToContact,
458
value: requireTOTP2FAForSendsToContact.toString()));
459
460
reaction(
461
(_) => shouldRequireTOTP2FAForSendsToNonContact,
461
- (bool requireTOTP2FAForSendsToNonContact) => secureStorage.write(
462
+ (bool requireTOTP2FAForSendsToNonContact) => writeSecureStorage(secureStorage,
463
key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact,
464
value: requireTOTP2FAForSendsToNonContact.toString()));
465
466
reaction(
467
(_) => shouldRequireTOTP2FAForSendsToInternalWallets,
467
- (bool requireTOTP2FAForSendsToInternalWallets) => secureStorage.write(
468
+ (bool requireTOTP2FAForSendsToInternalWallets) => writeSecureStorage(secureStorage,
469
key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets,
470
value: requireTOTP2FAForSendsToInternalWallets.toString()));
471
472
reaction(
473
(_) => shouldRequireTOTP2FAForExchangesToInternalWallets,
473
- (bool requireTOTP2FAForExchangesToInternalWallets) => secureStorage.write(
474
+ (bool requireTOTP2FAForExchangesToInternalWallets) => writeSecureStorage(secureStorage,
475
key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets,
476
value: requireTOTP2FAForExchangesToInternalWallets.toString()));
477
478
reaction(
479
(_) => shouldRequireTOTP2FAForExchangesToExternalWallets,
479
- (bool requireTOTP2FAForExchangesToExternalWallets) => secureStorage.write(
480
+ (bool requireTOTP2FAForExchangesToExternalWallets) => writeSecureStorage(secureStorage,
481
key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets,
482
value: requireTOTP2FAForExchangesToExternalWallets.toString()));
483
484
reaction(
485
(_) => shouldRequireTOTP2FAForAddingContacts,
485
- (bool requireTOTP2FAForAddingContacts) => secureStorage.write(
486
+ (bool requireTOTP2FAForAddingContacts) => writeSecureStorage(secureStorage,
487
key: SecureKey.shouldRequireTOTP2FAForAddingContacts,
488
value: requireTOTP2FAForAddingContacts.toString()));
489
490
reaction(
491
(_) => shouldRequireTOTP2FAForCreatingNewWallets,
491
- (bool requireTOTP2FAForCreatingNewWallets) => secureStorage.write(
492
+ (bool requireTOTP2FAForCreatingNewWallets) => writeSecureStorage(secureStorage,
493
key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets,
494
value: requireTOTP2FAForCreatingNewWallets.toString()));
495
496
reaction(
497
(_) => shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
497
- (bool requireTOTP2FAForAllSecurityAndBackupSettings) => secureStorage.write(
498
+ (bool requireTOTP2FAForAllSecurityAndBackupSettings) => writeSecureStorage(secureStorage,
499
key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
500
value: requireTOTP2FAForAllSecurityAndBackupSettings.toString()));
501
501
- reaction((_) => useTOTP2FA,
502
- (bool use) => secureStorage.write(key: SecureKey.useTOTP2FA, value: use.toString()));
502
+ reaction(
503
+ (_) => useTOTP2FA,
504
+ (bool use) =>
505
+ writeSecureStorage(secureStorage, key: SecureKey.useTOTP2FA, value: use.toString()));
506
504
- reaction((_) => totpSecretKey,
505
- (String totpKey) => secureStorage.write(key: SecureKey.totpSecretKey, value: totpKey));
507
+ reaction(
508
+ (_) => totpSecretKey,
509
+ (String totpKey) =>
510
+ writeSecureStorage(secureStorage, key: SecureKey.totpSecretKey, value: totpKey));
511
512
reaction(
513
(_) => pinTimeOutDuration,
509
- (PinCodeRequiredDuration pinCodeInterval) => secureStorage.write(
514
+ (PinCodeRequiredDuration pinCodeInterval) => writeSecureStorage(secureStorage,
515
key: SecureKey.pinTimeOutDuration, value: pinCodeInterval.value.toString()));
516
517
reaction(
lib/view_model/auth_view_model.dart
+4
-8
@@ -106,14 +106,10 @@ abstract class AuthViewModelBase with Store {
106
@action
107
Future<void> biometricAuth() async {
108
try {
109
- final canBiometricAuth = await _biometricAuth.canCheckBiometrics();
110
-
111
- if (canBiometricAuth) {
112
- final isAuthenticated = await _biometricAuth.isAuthenticated();
113
-
114
- if (isAuthenticated) {
115
- state = ExecutedSuccessfullyState();
116
- }
109
+ if (await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated()) {
110
+ state = ExecutedSuccessfullyState();
111
+ } else {
112
+ throw Exception('Biometric authentication failed');
113
}
114
} catch (e) {
115
state = FailureState(e.toString());
lib/view_model/edit_backup_password_view_model.dart
+2
-2
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/core/secure_storage.dart';
2
import 'package:mobx/mobx.dart';
3
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
4
import 'package:cake_wallet/entities/secret_store_key.dart';
@@ -37,8 +38,7 @@ abstract class EditBackupPasswordViewModelBase with Store {
38
@action
39
Future<void> save() async {
40
final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
40
- await secureStorage.delete(key: key);
41
- await secureStorage.write(key: key, value: backupPassword);
41
+ await writeSecureStorage(secureStorage, key: key, value: backupPassword);
42
secretStore.write(key: key, value: backupPassword);
43
}
44
}
macos/Flutter/GeneratedPluginRegistrant.swift
+2
@@ -10,6 +10,7 @@ import cw_monero
10
import device_info_plus
11
import devicelocale
12
import flutter_inappwebview_macos
13
+import flutter_local_authentication
14
import flutter_secure_storage_macos
15
import in_app_review
16
import package_info
@@ -26,6 +27,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
27
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
28
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
29
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
30
+ FlutterLocalAuthenticationPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalAuthenticationPlugin"))
31
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
32
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
33
FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin"))
macos/Podfile.lock
+6
@@ -26,6 +26,8 @@ PODS:
26
- flutter_inappwebview_macos (0.0.1):
27
- FlutterMacOS
28
- OrderedSet (~> 5.0)
29
+ - flutter_local_authentication (1.2.0):
30
+ - FlutterMacOS
31
- flutter_secure_storage_macos (6.1.1):
32
- FlutterMacOS
33
- FlutterMacOS (1.0.0)
@@ -56,6 +58,7 @@ DEPENDENCIES:
58
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
59
- devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`)
60
- flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`)
61
+ - flutter_local_authentication (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_authentication/macos`)
62
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
63
- FlutterMacOS (from `Flutter/ephemeral`)
64
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
@@ -83,6 +86,8 @@ EXTERNAL SOURCES:
86
:path: Flutter/ephemeral/.symlinks/plugins/devicelocale/macos
87
flutter_inappwebview_macos:
88
:path: Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos
89
+ flutter_local_authentication:
90
+ :path: Flutter/ephemeral/.symlinks/plugins/flutter_local_authentication/macos
91
flutter_secure_storage_macos:
92
:path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
93
FlutterMacOS:
@@ -110,6 +115,7 @@ SPEC CHECKSUMS:
115
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
116
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
117
flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d
118
+ flutter_local_authentication: 85674893931e1c9cfa7c9e4f5973cb8c56b018b0
119
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
120
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
121
in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0
pubspec_base.yaml
+4
-2
@@ -26,15 +26,17 @@ dependencies:
26
path_provider: ^2.0.11
27
mobx: ^2.1.4
28
flutter_mobx: ^2.0.6+5
29
- flutter_slidable: ^2.0.0
29
+ flutter_slidable: ^3.0.1
30
share_plus: ^4.0.10
31
# date_range_picker: ^1.0.6
32
#https://api.flutter.dev/flutter/material/showDateRangePicker.html
33
dio: ^4.0.6
34
hive: ^2.2.3
35
hive_flutter: ^1.1.0
36
- local_auth: ^2.1.0
36
local_auth_android: 1.0.21
37
+ flutter_local_authentication:
38
+ git:
39
+ url: https://github.com/cake-tech/flutter_local_authentication
40
package_info: ^2.0.0
41
#package_info_plus: ^1.4.2
42
devicelocale:
pubspec_description.yaml
+1
-1
@@ -4,4 +4,4 @@ version: 0.0.0
4
publish_to: none
5
6
environment:
7
- sdk: ">=2.17.5 <3.0.0"
\ No newline at end of file
7
+ sdk: ">=3.1.0 <4.0.0"
\ No newline at end of file