From e5be7372362d1ca443ab4434ae5401f2ff04f703 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Mon, 6 May 2024 12:55:05 -0700 Subject: [PATCH] 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 --- .github/workflows/pr_test_build.yml | 2 +- cw_bitcoin/pubspec.yaml | 5 +- cw_bitcoin_cash/pubspec.yaml | 5 +- cw_core/pubspec.yaml | 4 +- cw_ethereum/pubspec.yaml | 4 +- cw_evm/pubspec.yaml | 3 +- cw_haven/pubspec.yaml | 5 +- cw_monero/pubspec.yaml | 5 +- cw_nano/pubspec.yaml | 5 +- cw_polygon/pubspec.yaml | 4 +- cw_solana/pubspec.yaml | 5 +- lib/core/auth_service.dart | 13 +- lib/core/backup_service.dart | 17 +- lib/core/key_service.dart | 3 +- lib/core/secure_storage.dart | 11 + lib/entities/biometric_auth.dart | 27 +- lib/entities/fs_migration.dart | 5 +- lib/entities/get_encryption_key.dart | 4 +- lib/locales/hausa_intl.dart | 64 ++ lib/locales/yoruba_intl.dart | 939 ++++++++++-------- .../desktop_settings_page.dart | 60 +- .../settings/security_backup_page.dart | 4 +- lib/src/screens/settings/tor_page.dart | 4 +- .../support_chat/widgets/chatwoot_widget.dart | 4 +- .../validable_annotated_editable_text.dart | 14 +- lib/store/settings_store.dart | 37 +- lib/view_model/auth_view_model.dart | 12 +- .../edit_backup_password_view_model.dart | 4 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Podfile.lock | 6 + pubspec_base.yaml | 6 +- pubspec_description.yaml | 2 +- 32 files changed, 730 insertions(+), 555 deletions(-) diff --git a/.github/workflows/pr_test_build.yml b/.github/workflows/pr_test_build.yml index 46924cb35..23902f110 100644 --- a/.github/workflows/pr_test_build.yml +++ b/.github/workflows/pr_test_build.yml @@ -42,7 +42,7 @@ jobs: - name: Flutter action uses: subosito/flutter-action@v1 with: - flutter-version: "3.10.x" + flutter-version: "3.19.5" channel: stable - name: Install package dependencies diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 9adf77652..84254b5b5 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -43,11 +43,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_bitcoin_cash/pubspec.yaml b/cw_bitcoin_cash/pubspec.yaml index 37827f1ba..ceef539c3 100644 --- a/cw_bitcoin_cash/pubspec.yaml +++ b/cw_bitcoin_cash/pubspec.yaml @@ -39,10 +39,13 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_core/pubspec.yaml b/cw_core/pubspec.yaml index 36fe9967e..51d671dc7 100644 --- a/cw_core/pubspec.yaml +++ b/cw_core/pubspec.yaml @@ -28,11 +28,13 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^2.0.1 +dependency_overrides: + watcher: ^1.1.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_ethereum/pubspec.yaml b/cw_ethereum/pubspec.yaml index 5f78fba3d..462e1d77e 100644 --- a/cw_ethereum/pubspec.yaml +++ b/cw_ethereum/pubspec.yaml @@ -24,11 +24,13 @@ dependency_overrides: git: url: https://github.com/cake-tech/web3dart.git ref: cake + watcher: ^1.1.0 dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 + flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/cw_evm/pubspec.yaml b/cw_evm/pubspec.yaml index fb0384064..e4b29b676 100644 --- a/cw_evm/pubspec.yaml +++ b/cw_evm/pubspec.yaml @@ -36,11 +36,12 @@ dependency_overrides: git: url: https://github.com/cake-tech/ledger-flutter.git ref: cake + watcher: ^1.1.0 dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 flutter_lints: ^2.0.0 diff --git a/cw_haven/pubspec.yaml b/cw_haven/pubspec.yaml index c215ab779..d868c986d 100644 --- a/cw_haven/pubspec.yaml +++ b/cw_haven/pubspec.yaml @@ -24,11 +24,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 build_resolvers: ^2.0.9 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_monero/pubspec.yaml b/cw_monero/pubspec.yaml index a6fe7f967..c49a541ab 100644 --- a/cw_monero/pubspec.yaml +++ b/cw_monero/pubspec.yaml @@ -26,11 +26,14 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 build_resolvers: ^2.0.9 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_nano/pubspec.yaml b/cw_nano/pubspec.yaml index a4b8732fd..768c1bb4e 100644 --- a/cw_nano/pubspec.yaml +++ b/cw_nano/pubspec.yaml @@ -32,10 +32,13 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_polygon/pubspec.yaml b/cw_polygon/pubspec.yaml index dbef40b46..8421562b4 100644 --- a/cw_polygon/pubspec.yaml +++ b/cw_polygon/pubspec.yaml @@ -28,12 +28,14 @@ dependency_overrides: git: url: https://github.com/cake-tech/web3dart.git ref: cake + watcher: ^1.1.0 dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.1.11 + build_runner: ^2.4.7 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/cw_solana/pubspec.yaml b/cw_solana/pubspec.yaml index 7e24983bf..6b59282b4 100644 --- a/cw_solana/pubspec.yaml +++ b/cw_solana/pubspec.yaml @@ -26,10 +26,13 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^2.0.0 - build_runner: ^2.1.11 + build_runner: ^2.4.7 mobx_codegen: ^2.0.7 hive_generator: ^1.1.3 +dependency_overrides: + watcher: ^1.1.0 + flutter: # assets: # - images/a_dot_burr.jpeg diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart index 48610784c..66943bb7f 100644 --- a/lib/core/auth_service.dart +++ b/lib/core/auth_service.dart @@ -42,12 +42,7 @@ class AuthService with Store { Future setPassword(String password) async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final encodedPassword = encodedPinCode(pin: password); - // secure storage has a weird bug on macOS, where overwriting a key doesn't work, unless - // we delete what's there first: - if (Platform.isMacOS) { - await secureStorage.delete(key: key); - } - await secureStorage.write(key: key, value: encodedPassword); + await writeSecureStorage(secureStorage, key: key, value: encodedPassword); } Future canAuthenticate() async { @@ -74,7 +69,11 @@ class AuthService with Store { void saveLastAuthTime() { int timestamp = DateTime.now().millisecondsSinceEpoch; - secureStorage.write(key: SecureKey.lastAuthTimeMilliseconds, value: timestamp.toString()); + writeSecureStorage( + secureStorage, + key: SecureKey.lastAuthTimeMilliseconds, + value: timestamp.toString(), + ); } Future requireAuth() async { diff --git a/lib/core/backup_service.dart b/lib/core/backup_service.dart index 2ec5f293d..d1092b024 100644 --- a/lib/core/backup_service.dart +++ b/lib/core/backup_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/themes/theme_list.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cw_core/wallet_type.dart'; @@ -275,7 +276,7 @@ class BackupService { if (currentTransactionPriorityKeyLegacy != null) await _sharedPreferences.setInt( PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy); - + if (currentBitcoinElectrumSererId != null) await _sharedPreferences.setInt( PreferencesKey.currentBitcoinElectrumSererIdKey, currentBitcoinElectrumSererId); @@ -373,16 +374,15 @@ class BackupService { final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; - await _flutterSecureStorage.delete(key: backupPasswordKey); - await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword); + await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword); keychainWalletsInfo.forEach((dynamic rawInfo) async { final info = rawInfo as Map; await importWalletKeychainInfo(info); }); - await _flutterSecureStorage.delete(key: pinCodeKey); - await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); + await writeSecureStorage(_flutterSecureStorage, + key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); keychainDumpFile.deleteSync(); } @@ -401,16 +401,15 @@ class BackupService { final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword); final backupPassword = keychainJSON[backupPasswordKey] as String; - await _flutterSecureStorage.delete(key: backupPasswordKey); - await _flutterSecureStorage.write(key: backupPasswordKey, value: backupPassword); + await writeSecureStorage(_flutterSecureStorage, key: backupPasswordKey, value: backupPassword); keychainWalletsInfo.forEach((dynamic rawInfo) async { final info = rawInfo as Map; await importWalletKeychainInfo(info); }); - await _flutterSecureStorage.delete(key: pinCodeKey); - await _flutterSecureStorage.write(key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); + await writeSecureStorage(_flutterSecureStorage, + key: pinCodeKey, value: encodedPinCode(pin: decodedPin)); keychainDumpFile.deleteSync(); } diff --git a/lib/core/key_service.dart b/lib/core/key_service.dart index f829c22b5..ba2da4de6 100644 --- a/lib/core/key_service.dart +++ b/lib/core/key_service.dart @@ -20,8 +20,7 @@ class KeyService { key: SecretStoreKey.moneroWalletPassword, walletName: walletName); final encodedPassword = encodeWalletPassword(password: password); - await _secureStorage.delete(key: key); - await _secureStorage.write(key: key, value: encodedPassword); + await writeSecureStorage(_secureStorage, key: key, value: encodedPassword); } Future deleteWalletPassword({required String walletName}) async { diff --git a/lib/core/secure_storage.dart b/lib/core/secure_storage.dart index 4d9334a10..5afb36d29 100644 --- a/lib/core/secure_storage.dart +++ b/lib/core/secure_storage.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:io'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; // For now, we can create a utility function to handle this. // @@ -25,3 +26,13 @@ Future readSecureStorage(FlutterSecureStorage secureStorage, String key return result; } + +Future writeSecureStorage(FlutterSecureStorage secureStorage, + {required String key, required String value}) async { + // delete the value before writing on macOS because of a weird bug + // https://github.com/mogol/flutter_secure_storage/issues/581 + if (Platform.isMacOS) { + await secureStorage.delete(key: key); + } + await secureStorage.write(key: key, value: value); +} diff --git a/lib/entities/biometric_auth.dart b/lib/entities/biometric_auth.dart index 4b2bfd906..353cd0492 100644 --- a/lib/entities/biometric_auth.dart +++ b/lib/entities/biometric_auth.dart @@ -1,32 +1,29 @@ -import 'package:local_auth/local_auth.dart'; import 'package:flutter/services.dart'; -import 'package:cake_wallet/generated/i18n.dart'; +import 'package:flutter_local_authentication/flutter_local_authentication.dart'; class BiometricAuth { - final _localAuth = LocalAuthentication(); + final _flutterLocalAuthenticationPlugin = FlutterLocalAuthentication(); Future isAuthenticated() async { try { - return await _localAuth.authenticate( - localizedReason: S.current.biometric_auth_reason, - options: AuthenticationOptions( - biometricOnly: true, - useErrorDialogs: true, - stickyAuth: false)); - } on PlatformException catch (e) { + final authenticated = await _flutterLocalAuthenticationPlugin.authenticate(); + return authenticated; + } catch (e) { print(e); } - return false; } Future canCheckBiometrics() async { + bool canAuthenticate; try { - return await _localAuth.canCheckBiometrics; - } on PlatformException catch (e) { - print(e); + canAuthenticate = await _flutterLocalAuthenticationPlugin.canAuthenticate(); + await _flutterLocalAuthenticationPlugin.setTouchIDAuthenticationAllowableReuseDuration(0); + } catch (error) { + print("Exception checking support. $error"); + canAuthenticate = false; } - return false; + return canAuthenticate; } } \ No newline at end of file diff --git a/lib/entities/fs_migration.dart b/lib/entities/fs_migration.dart index 4280949cd..869ed66ff 100644 --- a/lib/entities/fs_migration.dart +++ b/lib/entities/fs_migration.dart @@ -1,5 +1,6 @@ import 'dart:io'; import 'dart:convert'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:collection/collection.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -147,8 +148,8 @@ Future ios_migrate_pin() async { final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword); final encodedPassword = encodedPinCode(pin: pinPassword); - await flutterSecureStorage.delete(key: key); - await flutterSecureStorage.write(key: key, value: encodedPassword); + await writeSecureStorage(flutterSecureStorage, key: key, value: encodedPassword); + await prefs.setBool('ios_migration_pin_completed', true); } diff --git a/lib/entities/get_encryption_key.dart b/lib/entities/get_encryption_key.dart index a32d4e311..04c3a65f7 100644 --- a/lib/entities/get_encryption_key.dart +++ b/lib/entities/get_encryption_key.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:cw_core/cake_hive.dart'; @@ -10,8 +11,7 @@ Future> getEncryptionKey( key = CakeHive.generateSecureKey(); final keyStringified = key.join(','); String storageKey = 'transactionDescriptionsBoxKey'; - await secureStorage.delete(key: storageKey); - await secureStorage.write(key: storageKey, value: keyStringified); + await writeSecureStorage(secureStorage, key: storageKey, value: keyStringified); } else { key = stringifiedKey.split(',').map((i) => int.parse(i)).toList(); } diff --git a/lib/locales/hausa_intl.dart b/lib/locales/hausa_intl.dart index 749d39a4d..6cf757b60 100644 --- a/lib/locales/hausa_intl.dart +++ b/lib/locales/hausa_intl.dart @@ -751,6 +751,50 @@ class HaMaterialLocalizations extends GlobalMaterialLocalizations { @override String get scrimOnTapHintRaw => "Scrip on Tap"; + + @override + // TODO: implement collapsedHint + String get collapsedHint => "collapsedHint"; + + @override + // TODO: implement expandedHint + String get expandedHint => "expandedHint"; + + @override + // TODO: implement expansionTileCollapsedHint + String get expansionTileCollapsedHint => "expansionTileCollapsedHint"; + + @override + // TODO: implement expansionTileCollapsedTapHint + String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint"; + + @override + // TODO: implement expansionTileExpandedHint + String get expansionTileExpandedHint => "expansionTileExpandedHint"; + + @override + // TODO: implement expansionTileExpandedTapHint + String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint"; + + @override + // TODO: implement scanTextButtonLabel + String get scanTextButtonLabel => "scanTextButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; } /// Cupertino Support @@ -955,4 +999,24 @@ class HaCupertinoLocalizations extends GlobalCupertinoLocalizations { @override String get noSpellCheckReplacementsLabel => ""; + + @override + // TODO: implement clearButtonLabel + String get clearButtonLabel => "clearButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; } diff --git a/lib/locales/yoruba_intl.dart b/lib/locales/yoruba_intl.dart index f16188529..3c720b80e 100644 --- a/lib/locales/yoruba_intl.dart +++ b/lib/locales/yoruba_intl.dart @@ -1,4 +1,3 @@ - import 'dart:async'; import 'package:flutter/cupertino.dart'; @@ -164,62 +163,62 @@ const yoDateSymbols = { 'ọjọ́ Àbámẹ́ta', ], 'STANDALONEWEEKDAYS': [ -'Ọjọ́ Ajé', -'Ọjọ́ Ìsẹ́gun', -'Ọjọ́ Ìsẹ́gun-Ẹtì', -'Ọjọ́ Ìsẹ́gun-Ọ̀rú', -'Ọjọ́ Àìkú', -'Ọjọ́ Jímọ̀', -'Ọjọ́ Àbámẹ́ta', -], -'SHORTWEEKDAYS': [ -'Ajé', -'Ìsẹ́gun', -'Ìsẹ́gun-Ẹtì', -'Ìsẹ́gun-Ọ̀rú', -'Àìkú', -'Jímọ̀', -'Àbámẹ́ta', -], -'STANDALONESHORTWEEKDAYS': [ -'Ajé', -'Ìsẹ́gun', -'Ìsẹ́gun-Ẹtì', -'Ìsẹ́gun-Ọ̀rú', -'Àìkú', -'Jímọ̀', -'Àbámẹ́ta', -], -'NARROWWEEKDAYS': [ -'A', -'A', -'Ì', -'A', -'À', -'J', -'À', -], -'STANDALONENARROWWEEKDAYS': [ -'A', -'A', -'Ì', -'A', -'À', -'J', -'À', -], -'SHORTQUARTERS': [ -'K1', -'K2', -'K3', -'K4', -], -'QUARTERS': [ -'1. kwata', -'2. kwata', -'3. kwata', -'4. kwata', -], + 'Ọjọ́ Ajé', + 'Ọjọ́ Ìsẹ́gun', + 'Ọjọ́ Ìsẹ́gun-Ẹtì', + 'Ọjọ́ Ìsẹ́gun-Ọ̀rú', + 'Ọjọ́ Àìkú', + 'Ọjọ́ Jímọ̀', + 'Ọjọ́ Àbámẹ́ta', + ], + 'SHORTWEEKDAYS': [ + 'Ajé', + 'Ìsẹ́gun', + 'Ìsẹ́gun-Ẹtì', + 'Ìsẹ́gun-Ọ̀rú', + 'Àìkú', + 'Jímọ̀', + 'Àbámẹ́ta', + ], + 'STANDALONESHORTWEEKDAYS': [ + 'Ajé', + 'Ìsẹ́gun', + 'Ìsẹ́gun-Ẹtì', + 'Ìsẹ́gun-Ọ̀rú', + 'Àìkú', + 'Jímọ̀', + 'Àbámẹ́ta', + ], + 'NARROWWEEKDAYS': [ + 'A', + 'A', + 'Ì', + 'A', + 'À', + 'J', + 'À', + ], + 'STANDALONENARROWWEEKDAYS': [ + 'A', + 'A', + 'Ì', + 'A', + 'À', + 'J', + 'À', + ], + 'SHORTQUARTERS': [ + 'K1', + 'K2', + 'K3', + 'K4', + ], + 'QUARTERS': [ + '1. kwata', + '2. kwata', + '3. kwata', + '4. kwata', + ], 'AMPMS': [ 'a.m.', 'p.m.', @@ -316,339 +315,339 @@ class YoMaterialLocalizations extends GlobalMaterialLocalizations { }); // #docregion Getters -@override -String get moreButtonTooltip => r'Kò sí ìròhùn tí ó múni'; + @override + String get moreButtonTooltip => r'Kò sí ìròhùn tí ó múni'; -@override -String get aboutListTileTitleRaw => r'Fun Àpótí àwọn $applicationname'; + @override + String get aboutListTileTitleRaw => r'Fun Àpótí àwọn $applicationname'; -@override -String get alertDialogLabel => r'Ìròhùn Àlàyé'; + @override + String get alertDialogLabel => r'Ìròhùn Àlàyé'; // #enddocregion Getters -@override -String get anteMeridiemAbbreviation => r'AM'; + @override + String get anteMeridiemAbbreviation => r'AM'; -@override -String get backButtonTooltip => r'Fíran'; + @override + String get backButtonTooltip => r'Fíran'; -@override -String get cancelButtonLabel => r'FAGILE'; + @override + String get cancelButtonLabel => r'FAGILE'; -@override -String get closeButtonLabel => r'KÚ'; + @override + String get closeButtonLabel => r'KÚ'; -@override -String get closeButtonTooltip => r'Kú'; + @override + String get closeButtonTooltip => r'Kú'; -@override -String get collapsedIconTapHint => r'Tá'; + @override + String get collapsedIconTapHint => r'Tá'; -@override -String get continueButtonLabel => r'TÓ WÁ'; + @override + String get continueButtonLabel => r'TÓ WÁ'; -@override -String get copyButtonLabel => r'DÚPLÍKÉTÍ'; + @override + String get copyButtonLabel => r'DÚPLÍKÉTÍ'; -@override -String get cutButtonLabel => r'TÒ'; + @override + String get cutButtonLabel => r'TÒ'; -@override -String get deleteButtonTooltip => r'Máa kú'; + @override + String get deleteButtonTooltip => r'Máa kú'; -@override -String get dialogLabel => r'Ìròhùn'; + @override + String get dialogLabel => r'Ìròhùn'; -@override -String get drawerLabel => r'Àgbèjọ àwọn àpọ̀tí'; + @override + String get drawerLabel => r'Àgbèjọ àwọn àpọ̀tí'; -@override -String get expandedIconTapHint => r'Tá'; + @override + String get expandedIconTapHint => r'Tá'; -@override -String get firstPageTooltip => r'Ojú ewe'; + @override + String get firstPageTooltip => r'Ojú ewe'; -@override -String get hideAccountsLabel => r'Fí èrò àpótí wáyé sílẹ̀'; + @override + String get hideAccountsLabel => r'Fí èrò àpótí wáyé sílẹ̀'; -@override -String get lastPageTooltip => r'Ojú ayé'; + @override + String get lastPageTooltip => r'Ojú ayé'; -@override -String get licensesPageTitle => r'Ìròhùn Ọdún'; + @override + String get licensesPageTitle => r'Ìròhùn Ọdún'; -@override -String get modalBarrierDismissLabel => r'Sọ'; + @override + String get modalBarrierDismissLabel => r'Sọ'; -@override -String get nextMonthTooltip => r'Oṣù kọja'; + @override + String get nextMonthTooltip => r'Oṣù kọja'; -@override -String get nextPageTooltip => r'Ojú ọjọ́ kẹta'; + @override + String get nextPageTooltip => r'Ojú ọjọ́ kẹta'; -@override -String get okButtonLabel => r'Ò daájú'; -@override + @override + String get okButtonLabel => r'Ò daájú'; + @override // A custom drawer tooltip message. -String get openAppDrawerTooltip => r'Aya ntọju Iwe Awọn Aka'; + String get openAppDrawerTooltip => r'Aya ntọju Iwe Awọn Aka'; // #docregion Raw -@override -String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow lati $rowCount'; + @override + String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow lati $rowCount'; -@override -String get pageRowsInfoTitleApproximateRaw => r'$firstRow–$lastRow lati kiakia $rowCount'; + @override + String get pageRowsInfoTitleApproximateRaw => r'$firstRow–$lastRow lati kiakia $rowCount'; // #enddocregion Raw -@override -String get pasteButtonLabel => r'TÌ'; - -@override -String get popupMenuLabel => r'Meniu Pop-up'; - -@override -String get menuBarMenuLabel => r'Meniu Akọkọ'; - -@override -String get postMeridiemAbbreviation => r'PM'; - -@override -String get previousMonthTooltip => r'Oṣu Kanakana'; - -@override -String get previousPageTooltip => r'Ojú ewé akọkọ kan'; - -@override -String get refreshIndicatorSemanticLabel => r'Gbiyanju'; - -@override -String? get remainingTextFieldCharacterCountFew => null; - -@override -String? get remainingTextFieldCharacterCountMany => null; - -@override -String get remainingTextFieldCharacterCountOne => r'1 àmì báálẹ̀'; - -@override -String get remainingTextFieldCharacterCountOther => r'$remainingCount àmì báálẹ̀'; - -@override -String? get remainingTextFieldCharacterCountTwo => null; - -@override -String get remainingTextFieldCharacterCountZero => r'Kò sí ìwọlé létà láti ń ṣe'; - -@override -String get reorderItemDown => r'Jù sí ilẹ'; - -@override -String get reorderItemLeft => r'Jù sí àrà'; - -@override -String get reorderItemRight => r'Jù sí òtútù'; - -@override -String get reorderItemToEnd => r'Jù sí ìbẹ̀jì'; - -@override -String get reorderItemToStart => r'Jù sí àkọ́kọ́'; - -@override -String get reorderItemUp => r'Jù sí ọ̀rùn'; - -@override -String get rowsPerPageTitle => r'Ìlò Fún àwọn Ìtọ́kasíwájú:'; - -@override -ScriptCategory get scriptCategory => ScriptCategory.englishLike; - -@override -String get searchFieldLabel => 'Ṣẹda'; - -@override -String get selectAllButtonLabel => 'FADỌHỌN DỌFÚN GBÁJÚMỌ̀'; - -@override -String? get selectedRowCountTitleFew => null; - -@override -String? get selectedRowCountTitleMany => null; - -@override -String get selectedRowCountTitleOne => '1 káyé'; - -@override -String get selectedRowCountTitleOther => r'$selectedRowCount káyé'; - -@override -String? get selectedRowCountTitleTwo => null; - -@override -String get selectedRowCountTitleZero => 'Kò sí káyé ti o wọlé'; - -@override -String get showAccountsLabel => 'Fi iyipada mu kọ'; - -@override -String get showMenuTooltip => 'Fi Meniu mu kọ'; - -@override -String get signedInLabel => 'Ọ̀nà'; - -@override -String get tabLabelRaw => r'Àwọn tabin $tabIndex lati $tabCount'; - @override -TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a; - -@override -String get timePickerHourModeAnnouncement => 'Tuntun waqtu lọ'; - -@override -String get timePickerMinuteModeAnnouncement => 'Tuntun daɗi minti'; - -@override -String get viewLicensesButtonLabel => 'WO NIKI'; - -@override -List get narrowWeekdays => const ['L', 'L', 'A', 'O', 'Ọ', 'Ẹ', 'Ẹ']; - -@override -int get firstDayOfWeekIndex => 0; - -static const LocalizationsDelegate delegate = -_YoMaterialLocalizationsDelegate(); - -@override -String get calendarModeButtonLabel => 'Tọ́rọ̀ kálẹ̀ndà'; - -@override -String get dateHelpText => 'mm/dd/yyyy'; - -@override -String get dateInputLabel => 'Firanṣẹ̀ Ọjọ́'; - -@override -String get dateOutOfRangeLabel => 'Nínú iwọ̀ lọ́wọ́'; - -@override -String get datePickerHelpText => 'WÁSÍ'; - -@override -String get dateRangeEndDateSemanticLabelRaw => r'Ọjọ́ tuntun to ṣà'; - -@override -String get dateRangeEndLabel => 'Ọjọ́ tuntun to ṣà'; - -@override -String get dateRangePickerHelpText => 'WÁSÍ ÌGBÀ'; - -@override -String get dateRangeStartDateSemanticLabelRaw => 'Ọjọ́ tuntun ti dá'; - -@override -String get dateRangeStartLabel => 'Ọjọ́ tuntun ti dá'; - -@override -String get dateSeparator => '/'; - -@override -String get dialModeButtonLabel => 'Tọ́rọ̀ wakati'; - -@override -String get inputDateModeButtonLabel => 'Tọ́rọ̀ firanṣẹ̀ ọjọ́'; - -@override -String get inputTimeModeButtonLabel => 'Tọ́rọ̀ wakati bayi lọ́wọ́'; - -@override -String get invalidDateFormatLabel => 'Akọ́kọ́tọ́ tó jẹ́kúnrin'; - -@override -String get invalidDateRangeLabel => 'Àmì jẹ́ káàkiri lẹ́yìn ilé'; - -@override -String get invalidTimeLabel => 'Akọ́kọ́tọ́ àkójọ ìwádìí'; - -@override -String get licensesPackageDetailTextOther => r'$licenseCount àwọn níkí'; - -@override -String get saveButtonLabel => 'TÙN DÁRA'; - -@override -String get selectYearSemanticsLabel => 'Fọ́ọ̀ shẹ́kàrà'; - -@override -String get timePickerDialHelpText => 'WÁSÍ WÁKÀTÌ'; - -@override -String get timePickerHourLabel => 'Wákàtì àṣà'; - -@override -String get timePickerInputHelpText => 'Shìgárà wákàtì'; - -@override -String get timePickerMinuteLabel => 'Mìntì'; - -@override -String get unspecifiedDate => 'Ọjọ̀kúnrin'; - -@override -String get unspecifiedDateRange => 'Ọjọ̀kúnrin àdáyọ̀'; - -@override -String get keyboardKeyAlt => 'Alt'; - -@override -String get keyboardKeyAltGraph => 'AltGraph'; - -@override -String get keyboardKeyBackspace => 'Báckspàcè'; - -@override -String get keyboardKeyCapsLock => 'Caps Lock'; - -@override -String get keyboardKeyChannelDown => 'Báyàkàmmàlàsàké'; - -@override -String get keyboardKeyChannelUp => 'Yíkàmmàlàsàké'; - -@override -String get keyboardKeyControl => 'Kọ́ntírọ̀l'; - -@override -String get keyboardKeyDelete => 'Shápè'; - -@override -String get keyboardKeyEject => 'Èjẹ̀tì'; - -@override -String get keyboardKeyEnd => 'Tàbí'; - -@override -String get keyboardKeyEscape => 'Tòkè'; + String get pasteButtonLabel => r'TÌ'; @override -String get keyboardKeyFn => 'Fn'; + String get popupMenuLabel => r'Meniu Pop-up'; -@override -String get keyboardKeyHome => 'Ile'; + @override + String get menuBarMenuLabel => r'Meniu Akọkọ'; -@override -String get keyboardKeyInsert => 'Fi sori'; + @override + String get postMeridiemAbbreviation => r'PM'; -@override -String get keyboardKeyMeta => 'Meta'; + @override + String get previousMonthTooltip => r'Oṣu Kanakana'; -@override -String get keyboardKeyMetaMacOs => 'Amfani pẹlu Command'; + @override + String get previousPageTooltip => r'Ojú ewé akọkọ kan'; -@override -String get keyboardKeyMetaWindows => 'Windows'; + @override + String get refreshIndicatorSemanticLabel => r'Gbiyanju'; + + @override + String? get remainingTextFieldCharacterCountFew => null; + + @override + String? get remainingTextFieldCharacterCountMany => null; + + @override + String get remainingTextFieldCharacterCountOne => r'1 àmì báálẹ̀'; + + @override + String get remainingTextFieldCharacterCountOther => r'$remainingCount àmì báálẹ̀'; + + @override + String? get remainingTextFieldCharacterCountTwo => null; + + @override + String get remainingTextFieldCharacterCountZero => r'Kò sí ìwọlé létà láti ń ṣe'; + + @override + String get reorderItemDown => r'Jù sí ilẹ'; + + @override + String get reorderItemLeft => r'Jù sí àrà'; + + @override + String get reorderItemRight => r'Jù sí òtútù'; + + @override + String get reorderItemToEnd => r'Jù sí ìbẹ̀jì'; + + @override + String get reorderItemToStart => r'Jù sí àkọ́kọ́'; + + @override + String get reorderItemUp => r'Jù sí ọ̀rùn'; + + @override + String get rowsPerPageTitle => r'Ìlò Fún àwọn Ìtọ́kasíwájú:'; + + @override + ScriptCategory get scriptCategory => ScriptCategory.englishLike; + + @override + String get searchFieldLabel => 'Ṣẹda'; + + @override + String get selectAllButtonLabel => 'FADỌHỌN DỌFÚN GBÁJÚMỌ̀'; + + @override + String? get selectedRowCountTitleFew => null; + + @override + String? get selectedRowCountTitleMany => null; + + @override + String get selectedRowCountTitleOne => '1 káyé'; + + @override + String get selectedRowCountTitleOther => r'$selectedRowCount káyé'; + + @override + String? get selectedRowCountTitleTwo => null; + + @override + String get selectedRowCountTitleZero => 'Kò sí káyé ti o wọlé'; + + @override + String get showAccountsLabel => 'Fi iyipada mu kọ'; + + @override + String get showMenuTooltip => 'Fi Meniu mu kọ'; + + @override + String get signedInLabel => 'Ọ̀nà'; + + @override + String get tabLabelRaw => r'Àwọn tabin $tabIndex lati $tabCount'; + + @override + TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a; + + @override + String get timePickerHourModeAnnouncement => 'Tuntun waqtu lọ'; + + @override + String get timePickerMinuteModeAnnouncement => 'Tuntun daɗi minti'; + + @override + String get viewLicensesButtonLabel => 'WO NIKI'; + + @override + List get narrowWeekdays => const ['L', 'L', 'A', 'O', 'Ọ', 'Ẹ', 'Ẹ']; + + @override + int get firstDayOfWeekIndex => 0; + + static const LocalizationsDelegate delegate = + _YoMaterialLocalizationsDelegate(); + + @override + String get calendarModeButtonLabel => 'Tọ́rọ̀ kálẹ̀ndà'; + + @override + String get dateHelpText => 'mm/dd/yyyy'; + + @override + String get dateInputLabel => 'Firanṣẹ̀ Ọjọ́'; + + @override + String get dateOutOfRangeLabel => 'Nínú iwọ̀ lọ́wọ́'; + + @override + String get datePickerHelpText => 'WÁSÍ'; + + @override + String get dateRangeEndDateSemanticLabelRaw => r'Ọjọ́ tuntun to ṣà'; + + @override + String get dateRangeEndLabel => 'Ọjọ́ tuntun to ṣà'; + + @override + String get dateRangePickerHelpText => 'WÁSÍ ÌGBÀ'; + + @override + String get dateRangeStartDateSemanticLabelRaw => 'Ọjọ́ tuntun ti dá'; + + @override + String get dateRangeStartLabel => 'Ọjọ́ tuntun ti dá'; + + @override + String get dateSeparator => '/'; + + @override + String get dialModeButtonLabel => 'Tọ́rọ̀ wakati'; + + @override + String get inputDateModeButtonLabel => 'Tọ́rọ̀ firanṣẹ̀ ọjọ́'; + + @override + String get inputTimeModeButtonLabel => 'Tọ́rọ̀ wakati bayi lọ́wọ́'; + + @override + String get invalidDateFormatLabel => 'Akọ́kọ́tọ́ tó jẹ́kúnrin'; + + @override + String get invalidDateRangeLabel => 'Àmì jẹ́ káàkiri lẹ́yìn ilé'; + + @override + String get invalidTimeLabel => 'Akọ́kọ́tọ́ àkójọ ìwádìí'; + + @override + String get licensesPackageDetailTextOther => r'$licenseCount àwọn níkí'; + + @override + String get saveButtonLabel => 'TÙN DÁRA'; + + @override + String get selectYearSemanticsLabel => 'Fọ́ọ̀ shẹ́kàrà'; + + @override + String get timePickerDialHelpText => 'WÁSÍ WÁKÀTÌ'; + + @override + String get timePickerHourLabel => 'Wákàtì àṣà'; + + @override + String get timePickerInputHelpText => 'Shìgárà wákàtì'; + + @override + String get timePickerMinuteLabel => 'Mìntì'; + + @override + String get unspecifiedDate => 'Ọjọ̀kúnrin'; + + @override + String get unspecifiedDateRange => 'Ọjọ̀kúnrin àdáyọ̀'; + + @override + String get keyboardKeyAlt => 'Alt'; + + @override + String get keyboardKeyAltGraph => 'AltGraph'; + + @override + String get keyboardKeyBackspace => 'Báckspàcè'; + + @override + String get keyboardKeyCapsLock => 'Caps Lock'; + + @override + String get keyboardKeyChannelDown => 'Báyàkàmmàlàsàké'; + + @override + String get keyboardKeyChannelUp => 'Yíkàmmàlàsàké'; + + @override + String get keyboardKeyControl => 'Kọ́ntírọ̀l'; + + @override + String get keyboardKeyDelete => 'Shápè'; + + @override + String get keyboardKeyEject => 'Èjẹ̀tì'; + + @override + String get keyboardKeyEnd => 'Tàbí'; + + @override + String get keyboardKeyEscape => 'Tòkè'; + + @override + String get keyboardKeyFn => 'Fn'; + + @override + String get keyboardKeyHome => 'Ile'; + + @override + String get keyboardKeyInsert => 'Fi sori'; + + @override + String get keyboardKeyMeta => 'Meta'; + + @override + String get keyboardKeyMetaMacOs => 'Amfani pẹlu Command'; + + @override + String get keyboardKeyMetaWindows => 'Windows'; @override String get keyboardKeyNumLock => 'Num Lock'; @@ -751,6 +750,50 @@ String get keyboardKeyMetaWindows => 'Windows'; @override String get scrimOnTapHintRaw => "Scrip on Tap"; + + @override + // TODO: implement collapsedHint + String get collapsedHint => "collapsedHint"; + + @override + // TODO: implement expandedHint + String get expandedHint => "expandedHint"; + + @override + // TODO: implement expansionTileCollapsedHint + String get expansionTileCollapsedHint => "expansionTileCollapsedHint"; + + @override + // TODO: implement expansionTileCollapsedTapHint + String get expansionTileCollapsedTapHint => "expansionTileCollapsedTapHint"; + + @override + // TODO: implement expansionTileExpandedHint + String get expansionTileExpandedHint => "expansionTileExpandedHint"; + + @override + // TODO: implement expansionTileExpandedTapHint + String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint"; + + @override + // TODO: implement scanTextButtonLabel + String get scanTextButtonLabel => "scanTextButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; } /// Cupertino Support @@ -821,138 +864,158 @@ class YoCupertinoLocalizations extends GlobalCupertinoLocalizations { required super.singleDigitSecondFormat, }); -@override -String get alertDialogLabel => 'Àdàkárò'; + @override + String get alertDialogLabel => 'Àdàkárò'; -@override -String get anteMeridiemAbbreviation => 'AM'; + @override + String get anteMeridiemAbbreviation => 'AM'; -@override -String get copyButtonLabel => 'Kòpy'; + @override + String get copyButtonLabel => 'Kòpy'; -@override -String get cutButtonLabel => 'Kọ́t'; + @override + String get cutButtonLabel => 'Kọ́t'; -@override -String get datePickerDateOrderString => 'mdy'; + @override + String get datePickerDateOrderString => 'mdy'; -@override -String get datePickerDateTimeOrderString => 'date_time_dayPeriod'; + @override + String get datePickerDateTimeOrderString => 'date_time_dayPeriod'; -@override -String? get datePickerHourSemanticsLabelFew => null; + @override + String? get datePickerHourSemanticsLabelFew => null; -@override -String? get datePickerHourSemanticsLabelMany => null; + @override + String? get datePickerHourSemanticsLabelMany => null; -@override -String? get datePickerHourSemanticsLabelOne => r"$hour o'clock"; + @override + String? get datePickerHourSemanticsLabelOne => r"$hour o'clock"; -@override -String get datePickerHourSemanticsLabelOther => r"$hour o'clock"; + @override + String get datePickerHourSemanticsLabelOther => r"$hour o'clock"; -@override -String? get datePickerHourSemanticsLabelTwo => null; + @override + String? get datePickerHourSemanticsLabelTwo => null; -@override -String? get datePickerHourSemanticsLabelZero => null; + @override + String? get datePickerHourSemanticsLabelZero => null; -@override -String? get datePickerMinuteSemanticsLabelFew => null; + @override + String? get datePickerMinuteSemanticsLabelFew => null; -@override -String? get datePickerMinuteSemanticsLabelMany => null; + @override + String? get datePickerMinuteSemanticsLabelMany => null; -@override -String? get datePickerMinuteSemanticsLabelOne => '1 wakati'; + @override + String? get datePickerMinuteSemanticsLabelOne => '1 wakati'; -@override -String get datePickerMinuteSemanticsLabelOther => r'$minute wakati'; + @override + String get datePickerMinuteSemanticsLabelOther => r'$minute wakati'; -@override -String? get datePickerMinuteSemanticsLabelTwo => null; + @override + String? get datePickerMinuteSemanticsLabelTwo => null; -@override -String? get datePickerMinuteSemanticsLabelZero => null; + @override + String? get datePickerMinuteSemanticsLabelZero => null; -@override -String get modalBarrierDismissLabel => 'Búta'; + @override + String get modalBarrierDismissLabel => 'Búta'; -@override -String get pasteButtonLabel => 'Tẹ́ẹ́'; + @override + String get pasteButtonLabel => 'Tẹ́ẹ́'; -@override -String get postMeridiemAbbreviation => 'PM'; + @override + String get postMeridiemAbbreviation => 'PM'; -@override -String get searchTextFieldPlaceholderLabel => 'Wúró àtúntà'; + @override + String get searchTextFieldPlaceholderLabel => 'Wúró àtúntà'; -@override -String get selectAllButtonLabel => 'Fírànsé gbógbo'; + @override + String get selectAllButtonLabel => 'Fírànsé gbógbo'; -@override -String get tabSemanticsLabelRaw => r'Tab $tabIndex nínú $tabCount'; + @override + String get tabSemanticsLabelRaw => r'Tab $tabIndex nínú $tabCount'; -@override -String? get timerPickerHourLabelFew => null; + @override + String? get timerPickerHourLabelFew => null; -@override -String? get timerPickerHourLabelMany => null; + @override + String? get timerPickerHourLabelMany => null; -@override -String? get timerPickerHourLabelOne => 'òǹdì'; + @override + String? get timerPickerHourLabelOne => 'òǹdì'; -@override -String get timerPickerHourLabelOther => 'òǹdì'; + @override + String get timerPickerHourLabelOther => 'òǹdì'; -@override -String? get timerPickerHourLabelTwo => null; + @override + String? get timerPickerHourLabelTwo => null; -@override -String? get timerPickerHourLabelZero => null; + @override + String? get timerPickerHourLabelZero => null; -@override -String? get timerPickerMinuteLabelFew => null; + @override + String? get timerPickerMinuteLabelFew => null; -@override -String? get timerPickerMinuteLabelMany => null; + @override + String? get timerPickerMinuteLabelMany => null; -@override -String? get timerPickerMinuteLabelOne => 'wakati.'; + @override + String? get timerPickerMinuteLabelOne => 'wakati.'; -@override -String get timerPickerMinuteLabelOther => 'wakati.'; + @override + String get timerPickerMinuteLabelOther => 'wakati.'; -@override -String? get timerPickerMinuteLabelTwo => null; + @override + String? get timerPickerMinuteLabelTwo => null; -@override -String? get timerPickerMinuteLabelZero => null; + @override + String? get timerPickerMinuteLabelZero => null; -@override -String? get timerPickerSecondLabelFew => null; + @override + String? get timerPickerSecondLabelFew => null; -@override -String? get timerPickerSecondLabelMany => null; + @override + String? get timerPickerSecondLabelMany => null; -@override -String? get timerPickerSecondLabelOne => 'dákìkà.'; + @override + String? get timerPickerSecondLabelOne => 'dákìkà.'; -@override -String get timerPickerSecondLabelOther => 'dákìkà.'; + @override + String get timerPickerSecondLabelOther => 'dákìkà.'; -@override -String? get timerPickerSecondLabelTwo => null; + @override + String? get timerPickerSecondLabelTwo => null; -@override -String? get timerPickerSecondLabelZero => null; + @override + String? get timerPickerSecondLabelZero => null; -@override -String get todayLabel => 'Oyọ'; + @override + String get todayLabel => 'Oyọ'; static const LocalizationsDelegate delegate = _YoCupertinoLocalizationsDelegate(); @override String get noSpellCheckReplacementsLabel => ""; -} \ No newline at end of file + + @override + // TODO: implement clearButtonLabel + String get clearButtonLabel => "clearButtonLabel"; + + @override + // TODO: implement lookUpButtonLabel + String get lookUpButtonLabel => "lookUpButtonLabel"; + + @override + // TODO: implement menuDismissLabel + String get menuDismissLabel => "menuDismissLabel"; + + @override + // TODO: implement searchWebButtonLabel + String get searchWebButtonLabel => "searchWebButtonLabel"; + + @override + // TODO: implement shareButtonLabel + String get shareButtonLabel => "shareButtonLabel"; +} diff --git a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart index 6896177e4..5355b7bb8 100644 --- a/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart +++ b/lib/src/screens/settings/desktop_settings/desktop_settings_page.dart @@ -12,7 +12,6 @@ final _settingsNavigatorKey = GlobalKey(); class DesktopSettingsPage extends StatefulWidget { const DesktopSettingsPage({super.key}); - @override State createState() => _DesktopSettingsPageState(); } @@ -33,22 +32,21 @@ class _DesktopSettingsPageState extends State { return Scaffold( body: Container( height: MediaQuery.of(context).size.height, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + child: Row( children: [ - Padding( - padding: const EdgeInsets.fromLTRB(24, 24, 24, 4), - child: Text( - S.current.settings, - style: textXLarge(), - ), - ), Expanded( - child: Row( + flex: 1, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ + Padding( + padding: const EdgeInsets.fromLTRB(24, 24, 24, 4), + child: Text( + S.current.settings, + style: textXLarge(), + ), + ), Expanded( - flex: 1, child: ListView.separated( padding: EdgeInsets.only(top: 0), itemBuilder: (_, index) { @@ -78,27 +76,27 @@ class _DesktopSettingsPageState extends State { itemCount: itemCount, ), ), - Flexible( - flex: 2, - child: ConstrainedBox( - constraints: BoxConstraints(maxWidth: 500), - child: Navigator( - key: _settingsNavigatorKey, - initialRoute: Routes.empty_no_route, - onGenerateRoute: (settings) => Router.createRoute(settings), - onGenerateInitialRoutes: - (NavigatorState navigator, String initialRouteName) { - return [ - navigator - .widget.onGenerateRoute!(RouteSettings(name: initialRouteName))! - ]; - }, - ), - ), - ) ], ), ), + Flexible( + flex: 2, + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: 500), + child: Navigator( + key: _settingsNavigatorKey, + initialRoute: Routes.empty_no_route, + onGenerateRoute: (settings) => Router.createRoute(settings), + onGenerateInitialRoutes: + (NavigatorState navigator, String initialRouteName) { + return [ + navigator + .widget.onGenerateRoute!(RouteSettings(name: initialRouteName))! + ]; + }, + ), + ), + ) ], ), ), diff --git a/lib/src/screens/settings/security_backup_page.dart b/lib/src/screens/settings/security_backup_page.dart index e559e9b15..1f0f58ad4 100644 --- a/lib/src/screens/settings/security_backup_page.dart +++ b/lib/src/screens/settings/security_backup_page.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:cake_wallet/core/auth_service.dart'; import 'package:cake_wallet/entities/pin_code_required_duration.dart'; import 'package:cake_wallet/routes.dart'; @@ -58,7 +60,7 @@ class SecurityBackupPage extends BasePage { .shouldRequireTOTP2FAForAllSecurityAndBackupSettings, ), ), - if (DeviceInfo.instance.isMobile) + if (DeviceInfo.instance.isMobile || Platform.isMacOS || Platform.isLinux) Observer(builder: (_) { return SettingsSwitcherCell( title: S.current.settings_allow_biometrical_authentication, diff --git a/lib/src/screens/settings/tor_page.dart b/lib/src/screens/settings/tor_page.dart index ae1ef1677..2f544be35 100644 --- a/lib/src/screens/settings/tor_page.dart +++ b/lib/src/screens/settings/tor_page.dart @@ -146,7 +146,7 @@ class ConnectScreen extends StatelessWidget { ElevatedButton( onPressed: connect, style: ElevatedButton.styleFrom( - primary: Colors.blue, + // primary: Colors.blue, padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), @@ -211,7 +211,7 @@ class DisconnectScreen extends StatelessWidget { ElevatedButton( onPressed: disconnect, style: ElevatedButton.styleFrom( - primary: Colors.red, + // primary: Colors.red, padding: EdgeInsets.symmetric(horizontal: 40, vertical: 15), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), diff --git a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart index 2557761a7..60c9ea97f 100644 --- a/lib/src/screens/support_chat/widgets/chatwoot_widget.dart +++ b/lib/src/screens/support_chat/widgets/chatwoot_widget.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; @@ -58,7 +59,6 @@ class ChatwootWidgetState extends State { } Future storeCookie(String value) async { - await widget.secureStorage.delete(key: COOKIE_KEY); - await widget.secureStorage.write(key: COOKIE_KEY, value: value); + await writeSecureStorage(widget.secureStorage, key: COOKIE_KEY, value: value); } } diff --git a/lib/src/widgets/validable_annotated_editable_text.dart b/lib/src/widgets/validable_annotated_editable_text.dart index 16ccc76f6..134eb16a8 100644 --- a/lib/src/widgets/validable_annotated_editable_text.dart +++ b/lib/src/widgets/validable_annotated_editable_text.dart @@ -1,8 +1,14 @@ -import 'package:cake_wallet/core/seed_validator.dart'; -import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; -class Annotation extends Comparable { + +extension Compare on Comparable { + bool operator <=(T other) => compareTo(other) <= 0; + bool operator >=(T other) => compareTo(other) >= 0; + bool operator <(T other) => compareTo(other) < 0; + bool operator >(T other) => compareTo(other) > 0; +} + +class Annotation implements Comparable { Annotation({required this.range, required this.style}); final TextRange range; @@ -12,7 +18,7 @@ class Annotation extends Comparable { int compareTo(Annotation other) => range.start.compareTo(other.range.start); } -class TextAnnotation extends Comparable { +class TextAnnotation implements Comparable { TextAnnotation({required this.text, required this.style}); final TextStyle style; diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart index 607551827..cd9b44391 100644 --- a/lib/store/settings_store.dart +++ b/lib/store/settings_store.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart'; +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart'; import 'package:cake_wallet/entities/provider_types.dart'; import 'package:cake_wallet/entities/cake_2fa_preset_options.dart'; @@ -434,79 +435,83 @@ abstract class SettingsStoreBase with Store { // secure storage keys: reaction( (_) => allowBiometricalAuthentication, - (bool biometricalAuthentication) => secureStorage.write( + (bool biometricalAuthentication) => writeSecureStorage(secureStorage, key: SecureKey.allowBiometricalAuthenticationKey, value: biometricalAuthentication.toString())); reaction( (_) => selectedCake2FAPreset, - (Cake2FAPresetsOptions selectedCake2FAPreset) => secureStorage.write( + (Cake2FAPresetsOptions selectedCake2FAPreset) => writeSecureStorage(secureStorage, key: SecureKey.selectedCake2FAPreset, value: selectedCake2FAPreset.serialize().toString())); reaction( (_) => shouldRequireTOTP2FAForAccessingWallet, - (bool requireTOTP2FAForAccessingWallet) => secureStorage.write( + (bool requireTOTP2FAForAccessingWallet) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForAccessingWallet, value: requireTOTP2FAForAccessingWallet.toString())); reaction( (_) => shouldRequireTOTP2FAForSendsToContact, - (bool requireTOTP2FAForSendsToContact) => secureStorage.write( + (bool requireTOTP2FAForSendsToContact) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForSendsToContact, value: requireTOTP2FAForSendsToContact.toString())); reaction( (_) => shouldRequireTOTP2FAForSendsToNonContact, - (bool requireTOTP2FAForSendsToNonContact) => secureStorage.write( + (bool requireTOTP2FAForSendsToNonContact) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForSendsToNonContact, value: requireTOTP2FAForSendsToNonContact.toString())); reaction( (_) => shouldRequireTOTP2FAForSendsToInternalWallets, - (bool requireTOTP2FAForSendsToInternalWallets) => secureStorage.write( + (bool requireTOTP2FAForSendsToInternalWallets) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForSendsToInternalWallets, value: requireTOTP2FAForSendsToInternalWallets.toString())); reaction( (_) => shouldRequireTOTP2FAForExchangesToInternalWallets, - (bool requireTOTP2FAForExchangesToInternalWallets) => secureStorage.write( + (bool requireTOTP2FAForExchangesToInternalWallets) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForExchangesToInternalWallets, value: requireTOTP2FAForExchangesToInternalWallets.toString())); reaction( (_) => shouldRequireTOTP2FAForExchangesToExternalWallets, - (bool requireTOTP2FAForExchangesToExternalWallets) => secureStorage.write( + (bool requireTOTP2FAForExchangesToExternalWallets) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForExchangesToExternalWallets, value: requireTOTP2FAForExchangesToExternalWallets.toString())); reaction( (_) => shouldRequireTOTP2FAForAddingContacts, - (bool requireTOTP2FAForAddingContacts) => secureStorage.write( + (bool requireTOTP2FAForAddingContacts) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForAddingContacts, value: requireTOTP2FAForAddingContacts.toString())); reaction( (_) => shouldRequireTOTP2FAForCreatingNewWallets, - (bool requireTOTP2FAForCreatingNewWallets) => secureStorage.write( + (bool requireTOTP2FAForCreatingNewWallets) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForCreatingNewWallets, value: requireTOTP2FAForCreatingNewWallets.toString())); reaction( (_) => shouldRequireTOTP2FAForAllSecurityAndBackupSettings, - (bool requireTOTP2FAForAllSecurityAndBackupSettings) => secureStorage.write( + (bool requireTOTP2FAForAllSecurityAndBackupSettings) => writeSecureStorage(secureStorage, key: SecureKey.shouldRequireTOTP2FAForAllSecurityAndBackupSettings, value: requireTOTP2FAForAllSecurityAndBackupSettings.toString())); - reaction((_) => useTOTP2FA, - (bool use) => secureStorage.write(key: SecureKey.useTOTP2FA, value: use.toString())); + reaction( + (_) => useTOTP2FA, + (bool use) => + writeSecureStorage(secureStorage, key: SecureKey.useTOTP2FA, value: use.toString())); - reaction((_) => totpSecretKey, - (String totpKey) => secureStorage.write(key: SecureKey.totpSecretKey, value: totpKey)); + reaction( + (_) => totpSecretKey, + (String totpKey) => + writeSecureStorage(secureStorage, key: SecureKey.totpSecretKey, value: totpKey)); reaction( (_) => pinTimeOutDuration, - (PinCodeRequiredDuration pinCodeInterval) => secureStorage.write( + (PinCodeRequiredDuration pinCodeInterval) => writeSecureStorage(secureStorage, key: SecureKey.pinTimeOutDuration, value: pinCodeInterval.value.toString())); reaction( diff --git a/lib/view_model/auth_view_model.dart b/lib/view_model/auth_view_model.dart index 4fb93cfea..6f6e29662 100644 --- a/lib/view_model/auth_view_model.dart +++ b/lib/view_model/auth_view_model.dart @@ -106,14 +106,10 @@ abstract class AuthViewModelBase with Store { @action Future biometricAuth() async { try { - final canBiometricAuth = await _biometricAuth.canCheckBiometrics(); - - if (canBiometricAuth) { - final isAuthenticated = await _biometricAuth.isAuthenticated(); - - if (isAuthenticated) { - state = ExecutedSuccessfullyState(); - } + if (await _biometricAuth.canCheckBiometrics() && await _biometricAuth.isAuthenticated()) { + state = ExecutedSuccessfullyState(); + } else { + throw Exception('Biometric authentication failed'); } } catch (e) { state = FailureState(e.toString()); diff --git a/lib/view_model/edit_backup_password_view_model.dart b/lib/view_model/edit_backup_password_view_model.dart index aca76502a..729551e74 100644 --- a/lib/view_model/edit_backup_password_view_model.dart +++ b/lib/view_model/edit_backup_password_view_model.dart @@ -1,3 +1,4 @@ +import 'package:cake_wallet/core/secure_storage.dart'; import 'package:mobx/mobx.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:cake_wallet/entities/secret_store_key.dart'; @@ -37,8 +38,7 @@ abstract class EditBackupPasswordViewModelBase with Store { @action Future save() async { final key = generateStoreKeyFor(key: SecretStoreKey.backupPassword); - await secureStorage.delete(key: key); - await secureStorage.write(key: key, value: backupPassword); + await writeSecureStorage(secureStorage, key: key, value: backupPassword); secretStore.write(key: key, value: backupPassword); } } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 75a78404f..51f61d9e3 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -10,6 +10,7 @@ import cw_monero import device_info_plus import devicelocale import flutter_inappwebview_macos +import flutter_local_authentication import flutter_secure_storage_macos import in_app_review import package_info @@ -26,6 +27,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin")) InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) + FlutterLocalAuthenticationPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalAuthenticationPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin")) FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin")) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index b82513de2..f1f72a818 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -26,6 +26,8 @@ PODS: - flutter_inappwebview_macos (0.0.1): - FlutterMacOS - OrderedSet (~> 5.0) + - flutter_local_authentication (1.2.0): + - FlutterMacOS - flutter_secure_storage_macos (6.1.1): - FlutterMacOS - FlutterMacOS (1.0.0) @@ -56,6 +58,7 @@ DEPENDENCIES: - device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`) - devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`) - flutter_inappwebview_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos`) + - flutter_local_authentication (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_authentication/macos`) - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`) @@ -83,6 +86,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/devicelocale/macos flutter_inappwebview_macos: :path: Flutter/ephemeral/.symlinks/plugins/flutter_inappwebview_macos/macos + flutter_local_authentication: + :path: Flutter/ephemeral/.symlinks/plugins/flutter_local_authentication/macos flutter_secure_storage_macos: :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos FlutterMacOS: @@ -110,6 +115,7 @@ SPEC CHECKSUMS: device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225 flutter_inappwebview_macos: 9600c9df9fdb346aaa8933812009f8d94304203d + flutter_local_authentication: 85674893931e1c9cfa7c9e4f5973cb8c56b018b0 flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0 diff --git a/pubspec_base.yaml b/pubspec_base.yaml index cf04509ac..ddf0bd2e0 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -26,15 +26,17 @@ dependencies: path_provider: ^2.0.11 mobx: ^2.1.4 flutter_mobx: ^2.0.6+5 - flutter_slidable: ^2.0.0 + flutter_slidable: ^3.0.1 share_plus: ^4.0.10 # date_range_picker: ^1.0.6 #https://api.flutter.dev/flutter/material/showDateRangePicker.html dio: ^4.0.6 hive: ^2.2.3 hive_flutter: ^1.1.0 - local_auth: ^2.1.0 local_auth_android: 1.0.21 + flutter_local_authentication: + git: + url: https://github.com/cake-tech/flutter_local_authentication package_info: ^2.0.0 #package_info_plus: ^1.4.2 devicelocale: diff --git a/pubspec_description.yaml b/pubspec_description.yaml index ebb6bf001..b51fe96d6 100644 --- a/pubspec_description.yaml +++ b/pubspec_description.yaml @@ -4,4 +4,4 @@ version: 0.0.0 publish_to: none environment: - sdk: ">=2.17.5 <3.0.0" \ No newline at end of file + sdk: ">=3.1.0 <4.0.0" \ No newline at end of file