From 745b9e265737223bea642032e7f5cf2b495b6daf Mon Sep 17 00:00:00 2001 From: Chris Tomlinson Date: Fri, 7 Nov 2025 12:53:10 +0000 Subject: [PATCH 01/10] Flutter 3.35; Dart 3.9 and static analysis updates --- .fvmrc | 2 +- .gitignore | 4 +- .vscode/settings.json | 2 +- ios/Podfile.lock | 4 +- lib/config/environment_config.dart | 2 +- .../expiring_cached_credential_hash_map.dart | 2 +- lib/cubit/app_settings_cubit.dart | 2 +- lib/cubit/autofill_cubit.dart | 8 +- lib/cubit/entry_cubit.dart | 12 +- lib/cubit/filter_cubit.dart | 2 +- lib/cubit/vault_cubit.dart | 4 +- lib/extension_methods.dart | 4 +- lib/generated/intl/messages_all.dart | 13 +- lib/generated/intl/messages_en.dart | 1512 +++++++---------- lib/generated/l10n.dart | 660 +++++-- lib/local_vault_repository.dart | 4 +- lib/logging/log_console.dart | 4 +- lib/model/entry.dart | 6 +- lib/model/field.dart | 2 +- lib/payment_service.dart | 8 +- lib/vault_backend/remote_service.dart | 2 +- lib/widgets/account_create.dart | 10 +- lib/widgets/account_expired.dart | 4 +- lib/widgets/autofill_save.dart | 2 +- lib/widgets/bottom.dart | 2 +- lib/widgets/change_email_prefs.dart | 2 +- lib/widgets/change_subscription.dart | 2 +- lib/widgets/entry_field.dart | 2 +- lib/widgets/import_credentials.dart | 4 +- lib/widgets/import_export.dart | 8 +- lib/widgets/kee_vault_app.dart | 4 +- lib/widgets/reset_account_prompt_dialog.dart | 2 +- lib/widgets/settings.dart | 4 +- lib/widgets/vault_imported.dart | 2 +- lib/widgets/vault_password_credentials.dart | 6 +- pubspec.lock | 130 +- pubspec.yaml | 59 +- 37 files changed, 1379 insertions(+), 1123 deletions(-) diff --git a/.fvmrc b/.fvmrc index 0251c4a..e8b4151 100644 --- a/.fvmrc +++ b/.fvmrc @@ -1,3 +1,3 @@ { - "flutter": "3.32.5" + "flutter": "3.35.7" } \ No newline at end of file diff --git a/.gitignore b/.gitignore index c4fa364..a80999c 100644 --- a/.gitignore +++ b/.gitignore @@ -61,4 +61,6 @@ ios/Runner.ipa .fvm/ # Remove after Flutter 3.29 bug is fixed -android/app/.cxx/ +#android/app/.cxx/ + +ios/build/ios/XCBuildData/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 522d01a..9615e51 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -57,7 +57,7 @@ "*.dll", "**/*.dll" ], - "dart.flutterSdkPath": ".fvm/versions/3.32.5", + "dart.flutterSdkPath": ".fvm/versions/3.35.7", "search.exclude": { "**/.fvm": true }, diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 0199559..986a3ef 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -148,7 +148,7 @@ SPEC CHECKSUMS: DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49 - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 flutter_file_dialog: 4c014a45b105709a27391e266c277d7e588e9299 flutter_inapp_purchase: 5c6a1ac3f11b11d0c8c0321c0c41c1f05805e4c8 flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29 @@ -167,4 +167,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 0658f7bb36458779f6da1691e33f9d925242f612 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/lib/config/environment_config.dart b/lib/config/environment_config.dart index e429dfd..1000477 100644 --- a/lib/config/environment_config.dart +++ b/lib/config/environment_config.dart @@ -7,7 +7,7 @@ class EnvironmentConfig { static const iapAppleAppStore = bool.hasEnvironment('IAP_APPLE_APP_STORE'); static const iapGooglePlay = bool.hasEnvironment('IAP_GOOGLE_PLAY'); - static get webUrl { + static String get webUrl { switch (stage) { case 'dev': return 'https://app-dev.kee.pm'; diff --git a/lib/credentials/expiring_cached_credential_hash_map.dart b/lib/credentials/expiring_cached_credential_hash_map.dart index 51faad1..e8aed97 100644 --- a/lib/credentials/expiring_cached_credential_hash_map.dart +++ b/lib/credentials/expiring_cached_credential_hash_map.dart @@ -10,7 +10,7 @@ class ExpiringCachedCredentialHashMap { Map toJson() => _map.map((u, c) => MapEntry(u, c.toJson())); - update(String user, ExpiringCachedCredentials? creds) { + void update(String user, ExpiringCachedCredentials? creds) { if (creds == null) { _map.remove(user); } else { diff --git a/lib/cubit/app_settings_cubit.dart b/lib/cubit/app_settings_cubit.dart index c1e2d93..182ba13 100644 --- a/lib/cubit/app_settings_cubit.dart +++ b/lib/cubit/app_settings_cubit.dart @@ -62,7 +62,7 @@ class AppSettingsCubit extends Cubit { emit((state as AppSettingsBasic).copyWith(iamAutofillDisabled: newMessageState)); } - Future iamDisplayed(iamName) async { + Future iamDisplayed(String iamName) async { switch (iamName) { case 'iamEmailSignup': await _iamEmailSignupDisplayed(); diff --git a/lib/cubit/autofill_cubit.dart b/lib/cubit/autofill_cubit.dart index 7f85f77..4001a2e 100644 --- a/lib/cubit/autofill_cubit.dart +++ b/lib/cubit/autofill_cubit.dart @@ -17,7 +17,7 @@ class AutofillCubit extends Cubit { static const _autoFillMethodChannel = MethodChannel('com.keevault.keevault/autofill'); - refresh() async { + Future refresh() async { if (KeeVaultPlatform.isIOS) { final iosAutofillStatus = await _autoFillMethodChannel.invokeMethod('getAutofillStatus'); final iosAvailable = iosAutofillStatus > 0; @@ -85,7 +85,7 @@ class AutofillCubit extends Cubit { emit(AutofillAvailable(enabled)); } - Future setSavingPreference(value) async { + Future setSavingPreference(bool value) async { final prefs = await AutofillService().preferences; await AutofillService().setPreferences( AutofillPreferences( @@ -96,7 +96,7 @@ class AutofillCubit extends Cubit { ); } - Future setDebugEnabledPreference(value) async { + Future setDebugEnabledPreference(bool value) async { if (KeeVaultPlatform.isIOS) { final iosAutofillEnableDebug = await _autoFillMethodChannel.invokeMethod('setDebugEnabled', { @@ -118,7 +118,7 @@ class AutofillCubit extends Cubit { } } - Future setIMEIntegrationPreference(value) async { + Future setIMEIntegrationPreference(bool value) async { final prefs = await AutofillService().preferences; await AutofillService().setPreferences( AutofillPreferences(enableDebug: prefs.enableDebug, enableSaving: prefs.enableSaving, enableIMERequests: value), diff --git a/lib/cubit/entry_cubit.dart b/lib/cubit/entry_cubit.dart index 2a12ed7..4268404 100644 --- a/lib/cubit/entry_cubit.dart +++ b/lib/cubit/entry_cubit.dart @@ -54,7 +54,7 @@ class EntryCubit extends Cubit { ); } - update({ + void update({ KdbxUuid? uuid, bool isDirty = true, KdbxGroup? group, @@ -78,7 +78,7 @@ class EntryCubit extends Cubit { emit(EntryLoaded(updated)); } - updateGroupByUUID({required String uuid}) { + void updateGroupByUUID({required String uuid}) { final entry = (state as EntryLoaded).entry; try { final newGroup = entry.group.file!.findGroupByUuid(KdbxUuid(uuid)); @@ -96,7 +96,7 @@ class EntryCubit extends Cubit { emit(EntryLoaded(updated)); } - addField(FieldViewModel field) { + void addField(FieldViewModel field) { if (field.fieldKey == null) { throw Exception('Invalid field parameter supplied to addField.'); } @@ -124,7 +124,7 @@ class EntryCubit extends Cubit { return newName; } - removeField(FieldViewModel field) { + void removeField(FieldViewModel field) { final entry = (state as EntryLoaded).entry; final newList = entry.fields.toList(); newList.remove(field); @@ -132,7 +132,7 @@ class EntryCubit extends Cubit { emit(EntryLoaded(updated)); } - renameField(KdbxKey? key, String? oldBrowserDisplayName, String newName) { + void renameField(KdbxKey? key, String? oldBrowserDisplayName, String newName) { final entry = (state as EntryLoaded).entry; int fieldIndex; @@ -164,7 +164,7 @@ class EntryCubit extends Cubit { emit(EntryLoaded(updated)); } - updateField( + void updateField( KdbxKey? key, String? oldBrowserDisplayName, { bool isDirty = true, diff --git a/lib/cubit/filter_cubit.dart b/lib/cubit/filter_cubit.dart index 5694246..a225ac5 100644 --- a/lib/cubit/filter_cubit.dart +++ b/lib/cubit/filter_cubit.dart @@ -10,7 +10,7 @@ part 'filter_state.dart'; class FilterCubit extends Cubit { FilterCubit() : super(FilterInitial()); - reset() { + void reset() { emit(FilterInitial()); } diff --git a/lib/cubit/vault_cubit.dart b/lib/cubit/vault_cubit.dart index e96f186..bf82e16 100644 --- a/lib/cubit/vault_cubit.dart +++ b/lib/cubit/vault_cubit.dart @@ -325,7 +325,7 @@ class VaultCubit extends Cubit { } } - emitError(String message, {bool toast = false, bool forceNotLoaded = false}) { + void emitError(String message, {bool toast = false, bool forceNotLoaded = false}) { if (!forceNotLoaded && state is VaultLoaded) { emit(VaultBackgroundError((state as VaultLoaded).vault, message, toast)); } else { @@ -333,7 +333,7 @@ class VaultCubit extends Cubit { } } - emitKeeMissingPrimaryDBExceptionError() { + void emitKeeMissingPrimaryDBExceptionError() { const message = "Couldn't find your Kee Vault. Probably there is an incomplete account reset in progress. Please close this app and sign in to Kee Vault using a different device or your web browser. Once you can see your vault there, save it, sign out and then open this app again and everything should be working."; l.e(message); diff --git a/lib/extension_methods.dart b/lib/extension_methods.dart index ccf50f6..8701bb5 100644 --- a/lib/extension_methods.dart +++ b/lib/extension_methods.dart @@ -160,14 +160,14 @@ extension DioHelperHandleException on DioException { } } -String? enumToString(o) => o?.toString().split('.').last; +String? enumToString(Enum? o) => o?.toString().split('.').last; T? enumFromString(Iterable values, String value) { return values.firstWhereOrNull((type) => type.toString().split('.').last == value); } extension KVPurchasedItem on PurchasedItem { - get keeVaultSubscriptionId { + String get keeVaultSubscriptionId { final prefix = purchaseStateAndroid != null ? 'gp_' : 'ap_'; if (KeeVaultPlatform.isIOS) { // Apple does not give us the information needed to derive this information diff --git a/lib/generated/intl/messages_all.dart b/lib/generated/intl/messages_all.dart index 2d2f540..203415c 100644 --- a/lib/generated/intl/messages_all.dart +++ b/lib/generated/intl/messages_all.dart @@ -35,10 +35,8 @@ MessageLookupByLibrary? _findExact(String localeName) { /// User programs should call this before using [localeName] for messages. Future initializeMessages(String localeName) { var availableLocale = Intl.verifiedLocale( - localeName, - (locale) => _deferredLibraries[locale] != null, - onFailure: (_) => null, - ); + localeName, (locale) => _deferredLibraries[locale] != null, + onFailure: (_) => null); if (availableLocale == null) { return new SynchronousFuture(false); } @@ -58,11 +56,8 @@ bool _messagesExistFor(String locale) { } MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) { - var actualLocale = Intl.verifiedLocale( - locale, - _messagesExistFor, - onFailure: (_) => null, - ); + var actualLocale = + Intl.verifiedLocale(locale, _messagesExistFor, onFailure: (_) => null); if (actualLocale == null) return null; return _findExact(actualLocale); } diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index e14843f..93d0dcd 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -66,857 +66,663 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { - "accountDeletionNotes": MessageLookupByLibrary.simpleMessage( - "You don\'t need to delete your account. If you want to cancel your subscription, just do that using the information above. We\'ll then automatically delete your account, but if you really want to take additional steps to request the deletion of your account, we have created a way for you to do this on our website, which you can access by using the button below.", - ), - "add": MessageLookupByLibrary.simpleMessage("Add"), - "addAttachment": MessageLookupByLibrary.simpleMessage( - "Add small attachment", - ), - "addField": MessageLookupByLibrary.simpleMessage("Add field"), - "addTOTPSecret": MessageLookupByLibrary.simpleMessage( - "Add TOTP / 2FA secret", - ), - "additionalCharacters": MessageLookupByLibrary.simpleMessage( - "Additional characters", - ), - "additionalUrlsToMatch": MessageLookupByLibrary.simpleMessage( - "Additional URLs to match", - ), - "agreeAndCheckAccountStatus": MessageLookupByLibrary.simpleMessage( - "Agree and check account status", - ), - "alertCancel": MessageLookupByLibrary.simpleMessage("Cancel"), - "alertClose": MessageLookupByLibrary.simpleMessage("Close"), - "alertCopy": MessageLookupByLibrary.simpleMessage("Copy"), - "alertNo": MessageLookupByLibrary.simpleMessage("No"), - "alertOk": MessageLookupByLibrary.simpleMessage("OK"), - "alertYes": MessageLookupByLibrary.simpleMessage("Yes"), - "alertYesPlease": MessageLookupByLibrary.simpleMessage("Yes please"), - "androidAppIdsToMatch": MessageLookupByLibrary.simpleMessage( - "Android app technical names to match", - ), - "appCannotLock": MessageLookupByLibrary.simpleMessage( - "You have unsaved changes that will be lost. Continue?", - ), - "apply": MessageLookupByLibrary.simpleMessage("Apply"), - "attachmentConfirmDelete": m0, - "attachmentError": MessageLookupByLibrary.simpleMessage("Attachment error"), - "attachmentErrorDetails": MessageLookupByLibrary.simpleMessage( - "Sorry, we were unable to attach this file. Please check that you have enabled the necessary permissions for Kee Vault to access the file. If you still have problems please report it on the community forum along with full details of your device so that we can investigate whether we can add support for your particular device in future.", - ), - "authenticating": MessageLookupByLibrary.simpleMessage("Authenticating"), - "autofillEnabled": MessageLookupByLibrary.simpleMessage( - "Kee Vault is correctly set as your device\'s Autofill provider.", - ), - "autofillNewEntryMakeChangesThenDone": MessageLookupByLibrary.simpleMessage( - "Entry saved. Make changes below if you want and then click \"Done\" below.", - ), - "autofillRequiresQU": MessageLookupByLibrary.simpleMessage( - " You need to add a Passcode, FaceId or TouchId to your device too!", - ), - "autofilling": MessageLookupByLibrary.simpleMessage("Autofilling"), - "automaticallySignInFor": MessageLookupByLibrary.simpleMessage( - "Automatically sign-in for (seconds)", - ), - "bannerMsg1TitleA": MessageLookupByLibrary.simpleMessage( - "Want to hear about new features?", - ), - "bannerMsg1TitleB": MessageLookupByLibrary.simpleMessage( - "Want to hear about new features and how to register for automatic backups and access from your other devices?", - ), - "bannerMsgAutofillDisabled": MessageLookupByLibrary.simpleMessage( - "For easier sign-in to your apps and websites, you need to change your device\'s Autofill provider to Kee Vault.", - ), - "bannerMsgSaving1": MessageLookupByLibrary.simpleMessage( - "Your Vault is being saved when this lock icon is flashing at the bottom of the screen.", - ), - "bannerMsgSaving2": MessageLookupByLibrary.simpleMessage( - "Our high security protection is applied to your Vault every time you save it. This can take a little bit of time, and a slow internet connection can make it take longer too.", - ), - "bannerReminderDelay3days": MessageLookupByLibrary.simpleMessage( - "in 3 days", - ), - "bannerReminderDelay3months": MessageLookupByLibrary.simpleMessage( - "in 3 months", - ), - "bannerReminderDelay3weeks": MessageLookupByLibrary.simpleMessage( - "in 3 weeks", - ), - "bannerReminderDelayNever": MessageLookupByLibrary.simpleMessage("never"), - "bannerReminderDelayRemindMe": MessageLookupByLibrary.simpleMessage( - "Remind me...", - ), - "bigTechAntiCompetitionStatement": MessageLookupByLibrary.simpleMessage( - "The \"Big Tech\" companies prohibit us from directly linking to the account registration page on our website.", - ), - "biometricSignIn": MessageLookupByLibrary.simpleMessage( - "Enable Quick sign-in (biometrics)", - ), - "biometricsErrorExplanation": m1, - "biometricsMaybeExpired": MessageLookupByLibrary.simpleMessage( - "Please enter your password", - ), - "biometricsStoreDescription": m2, - "cancelExportOrImport": m3, - "changeCancelSubscription": MessageLookupByLibrary.simpleMessage( - "Change or Cancel Subscription", - ), - "changeEmail": MessageLookupByLibrary.simpleMessage("Change email address"), - "changeEmailConfirmCheckbox": MessageLookupByLibrary.simpleMessage( - "I have read the above warnings, mitigated the risks and wish to continue", - ), - "changeEmailInfo1": MessageLookupByLibrary.simpleMessage( - "Your email address has a crucial role in the advanced security protections Kee Vault offers. Changing it securely is a far more complex task than for most of the places you might wish to change it. We are happy to finally offer this feature to you but please read the information carefully and don\'t proceed when you are in a rush.", - ), - "changeEmailInfo2": MessageLookupByLibrary.simpleMessage( - "Your new email address will:", - ), - "changeEmailInfo2a": MessageLookupByLibrary.simpleMessage( - "become your new sign-in ID", - ), - "changeEmailInfo2b": MessageLookupByLibrary.simpleMessage( - "need to be verified to confirm it belongs to you", - ), - "changeEmailInfo3": MessageLookupByLibrary.simpleMessage( - "We recommend that you:", - ), - "changeEmailInfo3a": MessageLookupByLibrary.simpleMessage( - "1) Click the Cancel button below, sign in to Kee Vault again, Export your Vault to a KDBX file and store it somewhere safe as a backup.", - ), - "changeEmailInfo3b": MessageLookupByLibrary.simpleMessage( - "2) Double check you enter the correct email address - you will need to type it exactly to sign in to your account in a moment.", - ), - "changeEmailInfo3c": MessageLookupByLibrary.simpleMessage( - "3) Copy/paste what you have entered in the email address box and store somewhere like a note on your phone.", - ), - "changeEmailInfo4": MessageLookupByLibrary.simpleMessage( - "If you make a mistake, you should be able to regain access to your Vault but in some cases you may need to create a new Kee Vault subscription and import from your previously exported KDBX file - this can result in additional hassle and costs since your old subscription would not be refundable.", - ), - "changeEmailInfo5": MessageLookupByLibrary.simpleMessage( - "Your password will remain the same throughout the process. If you want to change that too, we first recommend signing in on multiple devices using your new email address and waiting at least an hour.", - ), - "changeEmailPrefs": MessageLookupByLibrary.simpleMessage( - "Change email preferences", - ), - "changePassword": MessageLookupByLibrary.simpleMessage("Change Password"), - "changePasswordDetail": MessageLookupByLibrary.simpleMessage( - "Change the password you use to sign in to Kee Vault", - ), - "changePasswordWarning": MessageLookupByLibrary.simpleMessage( - "You may lose data if you are signed in on any other devices now. Please cancel (press back) and then sign out of all other devices, including the Kee Vault 1 web app. Then wait a minute and start this process again.", - ), - "chooseAPassword": MessageLookupByLibrary.simpleMessage( - "Please choose a password", - ), - "chooseAnIcon": MessageLookupByLibrary.simpleMessage("Choose an icon"), - "chooseNewParentGroupForEntry": MessageLookupByLibrary.simpleMessage( - "Select the group for this entry", - ), - "chooseNewParentGroupForGroup": m4, - "chooseRestoreGroup": MessageLookupByLibrary.simpleMessage( - "Select the group in which to restore this item", - ), - "color": MessageLookupByLibrary.simpleMessage("Colour"), - "colorFilteringHint": MessageLookupByLibrary.simpleMessage( - "Select colours above to display only entries with a matching colour.", - ), - "colors": MessageLookupByLibrary.simpleMessage("Colours"), - "colorsExplanation": MessageLookupByLibrary.simpleMessage( - "Colours allow you to categorise your entries in a more simplistic and visual way than Groups or Labels.", - ), - "confirmItsYou": MessageLookupByLibrary.simpleMessage( - "To access your passwords please confirm it\'s you", - ), - "continueSigningIn": MessageLookupByLibrary.simpleMessage( - "Continue signing in", - ), - "copySecret": MessageLookupByLibrary.simpleMessage("Copy Secret"), - "createNewEntry": MessageLookupByLibrary.simpleMessage("Create new entry"), - "createNewPasswordApplyExplanation": MessageLookupByLibrary.simpleMessage( - "Replace your old password with the new secure one shown above.", - ), - "createNewPasswordConfigurationExplanation": - MessageLookupByLibrary.simpleMessage( - "Create a different password by choosing a preset and/or adjusting the settings below.", - ), - "createNewPasswordCopyExplanation": MessageLookupByLibrary.simpleMessage( - "Copy the new secure password shown above to your device\'s copy/paste clipboard.", - ), - "createSecurePassword": MessageLookupByLibrary.simpleMessage( - "Create secure password", - ), - "createVault": MessageLookupByLibrary.simpleMessage("Create my Vault"), - "creating": MessageLookupByLibrary.simpleMessage("Creating"), - "currentEmailAddress": MessageLookupByLibrary.simpleMessage( - "Current email address", - ), - "currentPassword": MessageLookupByLibrary.simpleMessage("Current Password"), - "currentPasswordNotCorrect": MessageLookupByLibrary.simpleMessage( - "Current password is not correct", - ), - "delete": MessageLookupByLibrary.simpleMessage("Delete"), - "deleteAccount": MessageLookupByLibrary.simpleMessage("Delete Account"), - "deleteAttachment": MessageLookupByLibrary.simpleMessage( - "Delete attachment", - ), - "deleteGroupConfirm": MessageLookupByLibrary.simpleMessage( - "Delete the group and all entries within it?", - ), - "detCreated": MessageLookupByLibrary.simpleMessage("Created"), - "detDelEntry": MessageLookupByLibrary.simpleMessage("Delete"), - "detDelEntryPerm": MessageLookupByLibrary.simpleMessage( - "Delete permanently", - ), - "detFieldCopied": MessageLookupByLibrary.simpleMessage("Copied"), - "detGroup": MessageLookupByLibrary.simpleMessage("Group"), - "detHistoryRevert": MessageLookupByLibrary.simpleMessage("Revert to state"), - "detHistoryRevertAlert": MessageLookupByLibrary.simpleMessage( - "Revert to this history state?", - ), - "detNetField": MessageLookupByLibrary.simpleMessage("New Field"), - "detOtpQrError": MessageLookupByLibrary.simpleMessage("QR code scan error"), - "detOtpQrErrorBody": MessageLookupByLibrary.simpleMessage( - "Sorry, we could not read the QR code, please try once again or contact the app authors with error details.", - ), - "detOtpQrWrong": MessageLookupByLibrary.simpleMessage("Wrong QR code"), - "detOtpQrWrongBody": MessageLookupByLibrary.simpleMessage( - "Your QR code was successfully scanned but it doesn\'t contain one-time password data.", - ), - "detSetIcon": MessageLookupByLibrary.simpleMessage("Change icon"), - "detSetupOtpManualButton": MessageLookupByLibrary.simpleMessage( - "Enter code manually", - ), - "detUpdated": MessageLookupByLibrary.simpleMessage("Updated"), - "deviceAutoFill": MessageLookupByLibrary.simpleMessage("Device AutoFill"), - "disabled": MessageLookupByLibrary.simpleMessage("Disabled"), - "discard": MessageLookupByLibrary.simpleMessage("Discard"), - "discardChanges": MessageLookupByLibrary.simpleMessage("Discard changes"), - "domain": MessageLookupByLibrary.simpleMessage("Domain"), - "done": MessageLookupByLibrary.simpleMessage("Done"), - "downloading": MessageLookupByLibrary.simpleMessage("Downloading"), - "email": MessageLookupByLibrary.simpleMessage("Email"), - "emailChanged": MessageLookupByLibrary.simpleMessage( - "Email address changed", - ), - "emailValidationFail": MessageLookupByLibrary.simpleMessage( - "Not a valid email address. Please try again.", - ), - "emailVerification": MessageLookupByLibrary.simpleMessage( - "Email verification", - ), - "enableAutofill": MessageLookupByLibrary.simpleMessage("Enable Autofill"), - "enableAutofillIosInstructions": m5, - "enableAutofillRequired": m6, - "enabled": MessageLookupByLibrary.simpleMessage("Enabled"), - "enterNewPresetName": MessageLookupByLibrary.simpleMessage( - "Enter the new name for the preset", - ), - "enterNumberBetweenXAndY": m7, - "enterOldPassword": MessageLookupByLibrary.simpleMessage( - "First, enter your current password.", - ), - "enter_your_account_password": MessageLookupByLibrary.simpleMessage( - "Enter your account password", - ), - "enter_your_email_address": MessageLookupByLibrary.simpleMessage( - "Enter your email address", - ), - "entryAttachmentSizeError": MessageLookupByLibrary.simpleMessage( - "Large-sized file attachments like this one are not allowed because including them in your Vault will significantly slow down common tasks such as signing-in to your Vault and saving changes. Keep your attachments to a maximum of 250KB", - ), - "entryAttachmentSizeWarning": MessageLookupByLibrary.simpleMessage( - "Medium-sized file attachments like this one are allowed. However, including more than a small number of them in your Vault will significantly slow down common tasks such as signing-in to your Vault and saving changes. Try to keep your attachments below 20KB", - ), - "entryHistory": MessageLookupByLibrary.simpleMessage("Entry history"), - "entryHistoryExplainer": MessageLookupByLibrary.simpleMessage( - "Old versions of this entry are listed below. If you need to revert to an older version, we will automatically add your latest saved version to this list.", - ), - "entryIntegrationHintNewId": MessageLookupByLibrary.simpleMessage( - "New ID (e.g. com.example... )", - ), - "entryIntegrationHintNewUrl": MessageLookupByLibrary.simpleMessage( - "New URL (include https://)", - ), - "errorCorruptField": MessageLookupByLibrary.simpleMessage( - " : A field in this entry is corrupt. Please check the \'Help > Console log\' for details.", - ), - "everyoneElseCanUseForFree": MessageLookupByLibrary.simpleMessage( - "Everyone else is welcome to use the app for free without an account.", - ), - "exact": MessageLookupByLibrary.simpleMessage("Exact"), - "existingUser": MessageLookupByLibrary.simpleMessage("Existing User"), - "existingUsersSignInBelow": MessageLookupByLibrary.simpleMessage( - "If you already have a Kee Vault account on the https://keevault.pm \"Web App\" you can sign-in below.", - ), - "expiredWhileSignedIn": MessageLookupByLibrary.simpleMessage( - "Your subscription has just expired. Please click \"Sign out\" from the main menu below, then sign-in and follow the instructions. Your data is still available at the moment so don\'t panic.", - ), - "export": MessageLookupByLibrary.simpleMessage("Export"), - "exportAnyway": MessageLookupByLibrary.simpleMessage("Export anyway"), - "exportDirtyFileWarning": MessageLookupByLibrary.simpleMessage( - "We export the latest saved version of your Kee Vault. You may want to save your current changes before exporting.", - ), - "exportError": MessageLookupByLibrary.simpleMessage("Export error"), - "exportErrorDetails": MessageLookupByLibrary.simpleMessage( - "Sorry, we were unable to export to this location. Please check that you have enabled the necessary permissions for Kee Vault to access the file. If you still have problems please report it on the community forum along with full details of your device so that we can investigate whether we can add support for your particular device in future.", - ), - "exportUsesCurrentPassword": MessageLookupByLibrary.simpleMessage( - "Exports are encrypted and can be unlocked using the same password you use to open your Kee Vault.", - ), - "exported": MessageLookupByLibrary.simpleMessage("Exported"), - "fieldName": MessageLookupByLibrary.simpleMessage("Field name"), - "filterTooltipClosed": MessageLookupByLibrary.simpleMessage( - "Reveal search options and other filters", - ), - "filterTooltipOpen": MessageLookupByLibrary.simpleMessage( - "Show matching entries", - ), - "filteredByCriteria": m8, - "footerTitleGen": MessageLookupByLibrary.simpleMessage("Generate"), - "forgotPasswordOrCheckAccount": MessageLookupByLibrary.simpleMessage( - "Forgot your password or unsure if you have a Kee Vault account?", - ), - "freeUserTermsPopup1": MessageLookupByLibrary.simpleMessage( - "By using this app for free without an associated Kee Vault account, you are bound by the same terms and privacy policy as a user with an Account.", - ), - "freeUserTermsPopup2": MessageLookupByLibrary.simpleMessage( - "However, some terms will obviously not be relevant to you immediately. To save time, you could skip these sections of the Terms of Service: B - Account Terms, E - Payment, F - Free Trial and G - Cancellation and Termination, although you might wish to review them anyway if you think that you may sign up for an Account one day in the future.", - ), - "freeUserTermsPopup3": MessageLookupByLibrary.simpleMessage( - "You can view the documents here:", - ), - "freeUserTermsPopup4": MessageLookupByLibrary.simpleMessage( - "You will be given a further opportunity to review these documents if you later create a Kee Vault account.", - ), - "genLen": MessageLookupByLibrary.simpleMessage("Length"), - "genPresetHigh": MessageLookupByLibrary.simpleMessage("High security"), - "genPresetMac": MessageLookupByLibrary.simpleMessage("MAC address"), - "genPresetMed": MessageLookupByLibrary.simpleMessage("Medium security"), - "genPresetPin4": MessageLookupByLibrary.simpleMessage("4-digit PIN"), - "genPresetPronounceable": MessageLookupByLibrary.simpleMessage( - "Pronounceable", - ), - "genPresetVeryHigh": MessageLookupByLibrary.simpleMessage( - "Very high security", - ), - "genPsAmbiguous": MessageLookupByLibrary.simpleMessage("Ambiguous symbols"), - "genPsBrackets": MessageLookupByLibrary.simpleMessage("Brackets"), - "genPsDefault": MessageLookupByLibrary.simpleMessage("Selected by default"), - "genPsDelete": MessageLookupByLibrary.simpleMessage("Delete preset"), - "genPsDigits": MessageLookupByLibrary.simpleMessage("Digits"), - "genPsHigh": MessageLookupByLibrary.simpleMessage("High ASCII characters"), - "genPsLower": MessageLookupByLibrary.simpleMessage( - "Lowercase latin letters", - ), - "genPsSpecial": MessageLookupByLibrary.simpleMessage("Special symbols"), - "genPsTitle": MessageLookupByLibrary.simpleMessage("Generator Presets"), - "genPsUpper": MessageLookupByLibrary.simpleMessage( - "Uppercase latin letters", - ), - "generateSinglePassword": MessageLookupByLibrary.simpleMessage( - "Generate single password", - ), - "gotIt": MessageLookupByLibrary.simpleMessage("Got it"), - "group": MessageLookupByLibrary.simpleMessage("group"), - "groupNameNewExplanation": MessageLookupByLibrary.simpleMessage( - "Enter the name for the new group", - ), - "groupNameRenameExplanation": MessageLookupByLibrary.simpleMessage( - "Enter the new name for the group", - ), - "help": MessageLookupByLibrary.simpleMessage("Help"), - "hexadecimal": MessageLookupByLibrary.simpleMessage("Hexadecimal"), - "hide": MessageLookupByLibrary.simpleMessage("Hide"), - "hostname": MessageLookupByLibrary.simpleMessage("Hostname"), - "identifying": MessageLookupByLibrary.simpleMessage("Identifying"), - "import": MessageLookupByLibrary.simpleMessage("Import"), - "importComplete": MessageLookupByLibrary.simpleMessage("Import completed"), - "importError": MessageLookupByLibrary.simpleMessage("Import error"), - "importErrorDetails": MessageLookupByLibrary.simpleMessage( - "Sorry, we were unable to import this file. Please check that it is a valid KDBX file and that you have enabled the necessary permissions for Kee Vault to access the file. If you still have problems please report it on the community forum along with full details of your device so that we can investigate whether we can add support for your particular device in future.", - ), - "importErrorKdbx": MessageLookupByLibrary.simpleMessage( - "Sorry, we were unable to import this KDBX file. You probably need to save it in a different way. More details: ", - ), - "importExport": MessageLookupByLibrary.simpleMessage("Import / Export"), - "importKdbx": MessageLookupByLibrary.simpleMessage( - ".kdbx file (Kee Vault, KeePass, etc.)", - ), - "importOtherInstructions1": MessageLookupByLibrary.simpleMessage( - "We\'ll add specialised support for some other password manager storage formats in future but won\'t ever be able to directly support every one of the hundreds available.", - ), - "importOtherInstructions4": MessageLookupByLibrary.simpleMessage( - "If you don\'t already have a file in the KDBX format, you could use the desktop computer version of KeePass Password Safe 2 to import from your original source, save the KDBX file and then import that here using the kdbx import option.", - ), - "importUnlockRequired": MessageLookupByLibrary.simpleMessage( - "Enter your other password. This may be the old password you used on this device.", - ), - "importedContinueToVault": MessageLookupByLibrary.simpleMessage( - "Continue to your Vault", - ), - "importedFree1": MessageLookupByLibrary.simpleMessage( - "Thanks for signing in to a Kee Vault account. You already had a locally stored Vault on this device.", - ), - "importedFree2": MessageLookupByLibrary.simpleMessage( - "We have automatically imported your local passwords to a new Group in your Kee Vault account. You may wish to rename the group or manually remove/edit the entries to resolve any duplication. You can read more about this and find more detailed instructions in ", - ), - "importedManual": MessageLookupByLibrary.simpleMessage( - "We have imported your passwords to a new Group in your Kee Vault. You may wish to rename the group or manually remove/edit the entries to resolve any duplication. You can read more about this and find more detailed instructions in ", - ), - "incorrectFile": MessageLookupByLibrary.simpleMessage("Incorrect file"), - "integrationSettings": MessageLookupByLibrary.simpleMessage( - "Integration settings", - ), - "integrationSettingsExplainer": MessageLookupByLibrary.simpleMessage( - "These settings help you to refine when this entry is autofilled into other apps and websites. Some settings apply only to when you use Kee on a desktop computer and others only to specific mobile platforms (such as Android).", - ), - "introFilter": MessageLookupByLibrary.simpleMessage( - "\nFilter by group, label, colour and text", - ), - "introSortYourEntries": MessageLookupByLibrary.simpleMessage( - "\nSort your entries", - ), - "keeVaultFormatExplainer": MessageLookupByLibrary.simpleMessage( - "Kee Vault uses a standard format to securely store your passwords. You are free to export your passwords in this format to create a backup of your data. You can also import additional passwords to your vault from this screen.", - ), - "keep": MessageLookupByLibrary.simpleMessage("Keep"), - "keep_your_changes_question": MessageLookupByLibrary.simpleMessage( - "Do you want to keep your changes?", - ), - "label": MessageLookupByLibrary.simpleMessage("Label"), - "labelAssignmentExplanation": MessageLookupByLibrary.simpleMessage( - "Add new or existing labels to entries by editing the entry.", - ), - "labelFilteringHint": MessageLookupByLibrary.simpleMessage( - "Select labels above to display only entries with a matching label.", - ), - "labels": MessageLookupByLibrary.simpleMessage("Labels"), - "labelsExplanation": MessageLookupByLibrary.simpleMessage( - "Labels allow you to categorise your entries.", - ), - "labelsExplanation2": MessageLookupByLibrary.simpleMessage( - "Unlike Groups, each entry can be assigned more than one label.", - ), - "loading": MessageLookupByLibrary.simpleMessage("Loading"), - "localOnlyAgree1": MessageLookupByLibrary.simpleMessage( - "You need to agree to the ", - ), - "localOnlyAgree2": MessageLookupByLibrary.simpleMessage( - "Terms of Service and Privacy Statement", - ), - "localOnlyAgree3": MessageLookupByLibrary.simpleMessage( - ". We\'ll remember this until you uninstall the app or clear the app data. You MUST avoid clearing stored App data or you will also delete the passwords, usernames and other data you store in the app!", - ), - "localOnlyAgree4": MessageLookupByLibrary.simpleMessage( - "I understand and agree to the above", - ), - "localOnlyIntro": MessageLookupByLibrary.simpleMessage( - "Kee Vault supports one free user on your device. The passwords you store into your Vault will be held securely on only this device so you should ensure that you do not delete the App\'s Data and that you take regular backups.", - ), - "lock": MessageLookupByLibrary.simpleMessage("Lock"), - "longPressGroupExplanation": MessageLookupByLibrary.simpleMessage( - "Long-press on a group to rename, move or delete it, or to create a new subgroup.", - ), - "makeMoreChangesOrSave1": MessageLookupByLibrary.simpleMessage( - "Entry updated. Don\'t forget to Save your Vault when you have finished creating and changing entries.", - ), - "makeMoreChangesOrSave2": MessageLookupByLibrary.simpleMessage( - "You don\'t need to save after every change you make but make sure you save before closing the app or locking your Vault.", - ), - "makeMoreChangesOrSave3": MessageLookupByLibrary.simpleMessage( - "Beware that some devices will randomly delete unsaved data if you switch to using a different app for a little while.", - ), - "manageAccount": MessageLookupByLibrary.simpleMessage("Manage account"), - "manageAccountDetail": MessageLookupByLibrary.simpleMessage( - "Manage your Kee Vault account", - ), - "manageAccountSettingsDetail": MessageLookupByLibrary.simpleMessage( - "Edit your subscription, payment details or email contact preferences from the Kee Vault Account website.", - ), - "managePasswordPresets": MessageLookupByLibrary.simpleMessage( - "Manage password presets", - ), - "managePresets": MessageLookupByLibrary.simpleMessage("Manage presets"), - "menuEmptyTrash": MessageLookupByLibrary.simpleMessage("Empty Bin"), - "menuEmptyTrashAlert": MessageLookupByLibrary.simpleMessage("Empty Bin?"), - "menuEmptyTrashAlertBody": MessageLookupByLibrary.simpleMessage( - "You will not be able to get the entries back", - ), - "menuSetGeneral": MessageLookupByLibrary.simpleMessage("General"), - "menuTrash": MessageLookupByLibrary.simpleMessage("Bin"), - "merging": MessageLookupByLibrary.simpleMessage("Merging"), - "minURLMatchAccuracy": MessageLookupByLibrary.simpleMessage( - "Minimum accuracy for a URL match", - ), - "minURLMatchAccuracyExactWarning": MessageLookupByLibrary.simpleMessage( - "If you select Exact (for use on desktop web browsers) we\'ll use Hostname matching on mobile instead because Android and iOS do not permit Exact matching.", - ), - "minimumMatchAccuracyDomainExplainer": MessageLookupByLibrary.simpleMessage( - "The URL only needs to be part of the same domain to match.", - ), - "minimumMatchAccuracyExactExplainer": MessageLookupByLibrary.simpleMessage( - "The URL must match exactly including full path and query string.", - ), - "minimumMatchAccuracyHostnameExplainer": - MessageLookupByLibrary.simpleMessage( - "The URL must match the hostname (domain and subdomains) and port.", - ), - "move": MessageLookupByLibrary.simpleMessage("Move"), - "name": MessageLookupByLibrary.simpleMessage("name"), - "newEmailAddress": MessageLookupByLibrary.simpleMessage( - "New email address", - ), - "newGroup": MessageLookupByLibrary.simpleMessage("New Group"), - "newPassword": MessageLookupByLibrary.simpleMessage("New password"), - "newPasswordRepeat": MessageLookupByLibrary.simpleMessage( - "New password (please repeat)", - ), - "newProfile": MessageLookupByLibrary.simpleMessage("New profile"), - "newUser": MessageLookupByLibrary.simpleMessage("New User"), - "noEntriesCreateNewInstruction": MessageLookupByLibrary.simpleMessage( - "You have no password entries yet. Create one using the + button below. If you have passwords already stored in the standard KDBX (KeePass) format you can import them.", - ), - "noLongerHaveAccessToUnverifiedEmail": MessageLookupByLibrary.simpleMessage( - "No longer have access to your email address?", - ), - "notSignedIn": MessageLookupByLibrary.simpleMessage("Not signed in"), - "notes": MessageLookupByLibrary.simpleMessage("Notes"), - "occasionalNotifications": MessageLookupByLibrary.simpleMessage( - "Please send me occasional emails including new feature announcements and tips/advice on how to stay secure and get the most out of your Kee Vault account.", - ), - "offerToSave": MessageLookupByLibrary.simpleMessage( - "Offer to save passwords", - ), - "openError": MessageLookupByLibrary.simpleMessage("Error"), - "openInBrowser": MessageLookupByLibrary.simpleMessage("Open in browser"), - "openLogConsole": MessageLookupByLibrary.simpleMessage("Share/view logs"), - "openSettings": MessageLookupByLibrary.simpleMessage("Open settings"), - "openUrl": MessageLookupByLibrary.simpleMessage("URL"), - "openWebApp": MessageLookupByLibrary.simpleMessage( - "Open Kee Vault in your browser", - ), - "opening": MessageLookupByLibrary.simpleMessage("Opening"), - "otp": MessageLookupByLibrary.simpleMessage("OTP"), - "otpCodeLabel": MessageLookupByLibrary.simpleMessage( - "TOTP code (base32 format)", - ), - "otpExplainer1": MessageLookupByLibrary.simpleMessage( - "\"One Time Passwords\" (OTP) are a feature some websites offer to improve security. It is a type of Two/Multi Factor Authentication (2FA/MFA).", - ), - "otpManualError": MessageLookupByLibrary.simpleMessage("Invalid TOTP code"), - "otpManualErrorBody": MessageLookupByLibrary.simpleMessage( - "You did not enter a valid TOTP base32 code. Please try again.", - ), - "otpManualTitle": MessageLookupByLibrary.simpleMessage( - "Time-based One Time Password", - ), - "password": MessageLookupByLibrary.simpleMessage("Password"), - "passwordChanged": MessageLookupByLibrary.simpleMessage( - "Password changed. Use it when you next unlock Kee Vault.", - ), - "passwordRepeat": MessageLookupByLibrary.simpleMessage( - "Password (please repeat)", - ), - "passwordStrength": MessageLookupByLibrary.simpleMessage( - "Password strength", - ), - "permanentlyDeleteGroupConfirm": MessageLookupByLibrary.simpleMessage( - "Permanently delete the group and all entries within it?", - ), - "permissionDeniedError": m9, - "permissionDeniedPermanentlyError": m10, - "permissionError": MessageLookupByLibrary.simpleMessage("Permission error"), - "permissionReasonAttachFile": MessageLookupByLibrary.simpleMessage( - "attach a file", - ), - "permissionReasonScanBarcodes": MessageLookupByLibrary.simpleMessage( - "quickly scan QR codes (barcodes)", - ), - "permissionSettingsOpenError": MessageLookupByLibrary.simpleMessage( - "Sorry, your device did not allow us to open the settings for this app. Please use your device settings app to find and change the permissions settings for Kee Vault and then return here to try again.", - ), - "prcRegistrationError": MessageLookupByLibrary.simpleMessage( - "Sorry, we weren\'t able to register your email address now. Please check that you have a good network connection and try again or ask for help on the community forum if the problem continues.", - ), - "prcRegistrationPrivacy1": MessageLookupByLibrary.simpleMessage( - "The same privacy policy applies as when you started using the app. In brief, we\'ll protect (encrypt) your email address when we store it and will never share it or use it for anything you haven\'t agreed to. You can unsubscribe easily from each email we send to you.", - ), - "prcRegistrationPrivacy2": MessageLookupByLibrary.simpleMessage( - "You can review the full policy here:", - ), - "prcRegistrationSignUpButton": MessageLookupByLibrary.simpleMessage( - "Sign up to receive emails", - ), - "prcRegistrationSuccess": MessageLookupByLibrary.simpleMessage( - "Success! Please check your emails soon to confirm that you want to receive updates from us.", - ), - "prcSignupOrAccountStatusCheck": m11, - "preset": MessageLookupByLibrary.simpleMessage("Preset"), - "privacyStatement": MessageLookupByLibrary.simpleMessage( - "Privacy Statement", - ), - "privacySummaryExplainer": MessageLookupByLibrary.simpleMessage( - "We take pride in how we protect your privacy and security, particularly in comparison to other password management services, so we highlight the most important information right here.", - ), - "protectField": MessageLookupByLibrary.simpleMessage("Protect field"), - "protectedClickToReveal": MessageLookupByLibrary.simpleMessage( - "Protected field. Click to reveal.", - ), - "quickSignIn": MessageLookupByLibrary.simpleMessage("Quick sign-in"), - "quickSignInExplainer": m12, - "reenterYourPassword": MessageLookupByLibrary.simpleMessage( - "Please re-enter your password", - ), - "register": MessageLookupByLibrary.simpleMessage("Register"), - "registrationBlurb1": MessageLookupByLibrary.simpleMessage( - "Choose a secure password to protect your Kee Vault. There are no \"requirements\" so just make it as strong as you can. Only you will know this password - it never leaves your device. It can not be reset so you must not forget it, but you can change it when you\'re signed in to Kee Vault.", - ), - "registrationBlurb2": MessageLookupByLibrary.simpleMessage( - "Your email address is securely sent to a Kee Vault server (a computer on the internet) and immediately encrypted so that no-one can view it, even if the Kee Vault account database is illegally accessed. Our advanced personal data protection solution means that even when you next sign in to Kee Vault, your email address is not transmitted.", - ), - "registrationBlurb3": MessageLookupByLibrary.simpleMessage( - "We will share your email address only with 3rd parties that are essential to the operation of the Kee Vault service. For example, for payment processing. We demand the highest level of security and privacy from these recipients of your personal data.", - ), - "registrationBlurb4": MessageLookupByLibrary.simpleMessage( - "Potentially personally identifiable information is only kept for as long as is needed for us to deliver the service to you and meet our legal obligations. For example, the server logs IP addresses as part of protecting your account from unauthorised access attempts.", - ), - "registrationBlurb4old": MessageLookupByLibrary.simpleMessage( - "The Kee Vault servers are connected to the internet so various internet infrastructure companies may be in a position to view your email address. As explained above, we will encrypt it during transfer and storage, and follow all other best practice to minimise this risk.", - ), - "registrationBlurb5": MessageLookupByLibrary.simpleMessage( - "To improve Kee Vault for you, we may record anonymous usage data across our apps, keevault.pm and our associated websites. This never includes personally identifiable information (or passwords!) and is never shared.", - ), - "registrationBlurb7": MessageLookupByLibrary.simpleMessage( - "The security of your information depends upon the security of the devices that you use to access Kee Vault. This is no different to every other online or offline app but we want to re-iterate that point here: any software or service that claims to protect you from a security breach on a local device is misleading you - it is your responsibility to keep your local device secure.", - ), - "registrationEmailUsage1": MessageLookupByLibrary.simpleMessage( - "We and/or our essential 3rd party partners will send you emails that relate to critical service or security issues as necessary. We\'ll send a handful of introductory emails with usage instructions and tips which are legitimately in your interest but you can unsubscribe any time from the emails themselves. Receiving marketing emails is optional. We recommend opting in to evaluate whether the frequency and content of emails is suitable for you because it\'s easy to unsubscribe at any time.", - ), - "registrationPrivacyOverview1": MessageLookupByLibrary.simpleMessage( - "The information above is intended as simple guide to what we think are the most critical privacy and security concerns relating to your use of the Kee Vault service but they are not a substitute for our full Terms of Service and Privacy Statement. Also note that your Subscription (payment) agreement may be with a 3rd party and they will show you those additional terms and conditions at the appropriate point of your subscription sign-up.", - ), - "rememberExportsDoNotUpdate": MessageLookupByLibrary.simpleMessage( - "Remember that Exports do not automatically update. The information stored within and the password required to unlock it does not change after you create the export.", - ), - "rememberFilterGroup": MessageLookupByLibrary.simpleMessage( - "Remember chosen filter group", - ), - "rememberVaultPassword": MessageLookupByLibrary.simpleMessage( - "Remember your Vault password?", - ), - "renameFieldEnterNewName": MessageLookupByLibrary.simpleMessage( - "Enter the new name for the field", - ), - "renamingField": MessageLookupByLibrary.simpleMessage("Renaming field"), - "renamingPreset": MessageLookupByLibrary.simpleMessage("Renaming preset"), - "requireFullPasswordEvery": MessageLookupByLibrary.simpleMessage( - "Require full password every (days)", - ), - "resendVerification": MessageLookupByLibrary.simpleMessage( - "Resend the verification link", - ), - "resetEntryToThis": MessageLookupByLibrary.simpleMessage( - "Reset entry to this state", - ), - "resetPasswordInstructions": MessageLookupByLibrary.simpleMessage( - "You can reset your password using the Kee Vault \"Web App\" (version 1).", - ), - "restartSubscription": MessageLookupByLibrary.simpleMessage( - "Restart subscription", - ), - "restore": MessageLookupByLibrary.simpleMessage("Restore"), - "revertUnsavedWarning": MessageLookupByLibrary.simpleMessage( - "Your unsaved changes will be permanently lost if you change to this older version now. Do you want to discard your changes?", - ), - "save": MessageLookupByLibrary.simpleMessage("Save"), - "saveChanges": MessageLookupByLibrary.simpleMessage("Confirm changes"), - "saveExplainerAlertTitle": MessageLookupByLibrary.simpleMessage( - "Saving...", - ), - "saveVault": MessageLookupByLibrary.simpleMessage("Save Vault"), - "search": MessageLookupByLibrary.simpleMessage("Search"), - "searchCase": MessageLookupByLibrary.simpleMessage("Match case"), - "searchHistory": MessageLookupByLibrary.simpleMessage( - "Include entry history", - ), - "searchOtherSecure": MessageLookupByLibrary.simpleMessage( - "Other protected fields", - ), - "searchOtherStandard": MessageLookupByLibrary.simpleMessage( - "Other standard fields", - ), - "searchRegex": MessageLookupByLibrary.simpleMessage("RegEx"), - "searchSearchIn": MessageLookupByLibrary.simpleMessage( - "Search in these entry fields:", - ), - "selectKdbxFile": MessageLookupByLibrary.simpleMessage( - "Please select a KDBX file.", - ), - "serverMITMWarning": MessageLookupByLibrary.simpleMessage( - "Sign in failed because the response we received from the server indicates that it may be compromised. The most likely explanation is that someone near you or at your internet service provider is attempting to interfere with the secure connection and connect you to a malicious server (A Miscreant In The Middle attack). Find a different internet connection immediately, shut down the Kee Vault app and try again. If it keeps happening, your local device may be compromised. The security of your Kee Vault remains intact so you need not panic. More information about the error is available at https://forum.kee.pm/", - ), - "setDefault": MessageLookupByLibrary.simpleMessage("Set as default"), - "setFilePassNotMatch": MessageLookupByLibrary.simpleMessage( - "Passwords don\'t match, please type them again", - ), - "setGenShowSubgroups": MessageLookupByLibrary.simpleMessage( - "Show entries from all subgroups", - ), - "setGenTheme": MessageLookupByLibrary.simpleMessage("Theme"), - "setGenThemeDk": MessageLookupByLibrary.simpleMessage("Dark"), - "setGenThemeLt": MessageLookupByLibrary.simpleMessage("Light"), - "setGenTitlebarStyleDefault": MessageLookupByLibrary.simpleMessage( - "Default", - ), - "settings": MessageLookupByLibrary.simpleMessage("Settings"), - "settingsNotSignedInError": MessageLookupByLibrary.simpleMessage( - "You are not signed in so we cannot proceed. Try returning to the app home page or kill and re-open the app if you are having trouble reaching the sign-in screen again.", - ), - "share": MessageLookupByLibrary.simpleMessage("Share"), - "show": MessageLookupByLibrary.simpleMessage("Show"), - "showEntryInBrowsersAndApps": MessageLookupByLibrary.simpleMessage( - "Show this entry in Kee browser extension (desktop), mobile apps and browsers", - ), - "showProtectedField": MessageLookupByLibrary.simpleMessage( - "Show protected field", - ), - "showing_all_entries": MessageLookupByLibrary.simpleMessage( - "Showing all entries", - ), - "signInAgainWhenVerified": MessageLookupByLibrary.simpleMessage( - "When your email address is successfully verified you can click the button below to continue your sign-in.", - ), - "signin": MessageLookupByLibrary.simpleMessage("Sign in"), - "signout": MessageLookupByLibrary.simpleMessage("Sign out"), - "sizeBytes": m13, - "sortCreated": MessageLookupByLibrary.simpleMessage("Newest"), - "sortCreatedReversed": MessageLookupByLibrary.simpleMessage("Oldest"), - "sortModified": MessageLookupByLibrary.simpleMessage("Recently updated"), - "sortModifiedReversed": MessageLookupByLibrary.simpleMessage( - "Least recently updated", - ), - "sortTitle": MessageLookupByLibrary.simpleMessage("Title"), - "sortTitleReversed": MessageLookupByLibrary.simpleMessage( - "Title - reversed", - ), - "startAccountReset": MessageLookupByLibrary.simpleMessage( - "Start account reset", - ), - "startFreeTrial": MessageLookupByLibrary.simpleMessage("Start free trial"), - "startNewTrialError": MessageLookupByLibrary.simpleMessage( - "Sorry, we weren\'t able to restart your trial now. Please try again later and ask for help on the community forum if the problem continues.", - ), - "startNewTrialSuccess": MessageLookupByLibrary.simpleMessage("All done!"), - "subscriptionAssociatingDescription": MessageLookupByLibrary.simpleMessage( - "Nearly there. Your subscription is being processed and we are setting up your account. This usually takes a few seconds but can take longer at busy times. We\'ll keep trying for a minute so don\'t close the app or lock your phone before then.", - ), - "subscriptionCancellationNotes": MessageLookupByLibrary.simpleMessage( - "Cancellation notes: If you cancel your subscription, once your current subscription term ends, we will delete your account in a way that protects your data at all times. After some time, your Kee Vault data will be permanently deleted so you must make sure that you have exported the latest copy of your data before you cancel your subscription. To continue using the app as a free user, you must first export your data to a KDBX file, then uninstall and reinstall the app. You can then import the exported KDBX file once you start using the app again as a free user. We recommend you plan carefully to minimise your risk of data loss.", - ), - "subscriptionExpired": MessageLookupByLibrary.simpleMessage( - "Subscription expired", - ), - "subscriptionExpiredDetails": MessageLookupByLibrary.simpleMessage( - "Your subscription or trial period has ended. Provide up to date payment details and re-enable your subscription on the Kee Vault Account Management web site.", - ), - "subscriptionExpiredIapDetails": MessageLookupByLibrary.simpleMessage( - "Your subscription or trial period has ended. Please restart your subscription to continue.", - ), - "subscriptionExpiredNoAction": MessageLookupByLibrary.simpleMessage( - "Your subscription or trial period has ended. Please contact us to discuss options for renewal.", - ), - "subscriptionExpiredTrialAvailable": MessageLookupByLibrary.simpleMessage( - "Welcome back to Kee Vault. You can enable a new 30 day free trial to see what has improved since you first created your Kee Vault account.", - ), - "tagRename": MessageLookupByLibrary.simpleMessage("Rename"), - "text": MessageLookupByLibrary.simpleMessage("Text"), - "textFilteringHint": MessageLookupByLibrary.simpleMessage( - "These options change how Search uses your text input to find entries.", - ), - "thisCommunityForumTopic": MessageLookupByLibrary.simpleMessage( - "this community forum topic", - ), - "this_field_required": MessageLookupByLibrary.simpleMessage( - "This field is required", - ), - "title": MessageLookupByLibrary.simpleMessage("title"), - "tryAgain": MessageLookupByLibrary.simpleMessage("Try again"), - "unexpected_error": m14, - "unlock": MessageLookupByLibrary.simpleMessage("Unlock"), - "unlockRequired": MessageLookupByLibrary.simpleMessage("Unlock your Vault"), - "unlock_with_biometrics": MessageLookupByLibrary.simpleMessage( - "Use biometrics", - ), - "unprotectField": MessageLookupByLibrary.simpleMessage("Unprotect field"), - "urlOpenFailed": MessageLookupByLibrary.simpleMessage( - "Your device stopped us opening that resource", - ), - "useWebAppForOtherSettings": MessageLookupByLibrary.simpleMessage( - "You can change some additional settings from the Kee Vault web app by using your web browser to sign in to Kee Vault.", - ), - "user": MessageLookupByLibrary.simpleMessage("user"), - "userEmail": MessageLookupByLibrary.simpleMessage("User/Email"), - "vaultStatusActionNeeded": MessageLookupByLibrary.simpleMessage( - "Action needed", - ), - "vaultStatusDescLoaded": MessageLookupByLibrary.simpleMessage( - "Your Vault is loaded and ready for use.", - ), - "vaultStatusDescMerging": MessageLookupByLibrary.simpleMessage( - "Merging your changes from your other devices", - ), - "vaultStatusDescPasswordChanged": MessageLookupByLibrary.simpleMessage( - "Your password has changed", - ), - "vaultStatusDescRefreshing": MessageLookupByLibrary.simpleMessage( - "Checking for changes from your other devices", - ), - "vaultStatusDescSaveNeeded": MessageLookupByLibrary.simpleMessage( - "There are changes from other devices which will be merged with this device when you next save.", - ), - "vaultStatusDescSaving": MessageLookupByLibrary.simpleMessage( - "Saving your changes", - ), - "vaultStatusDescUnknown": MessageLookupByLibrary.simpleMessage( - "If this situation does not automatically resolve itself within a minute, please check the Console Log in the Help section, report the problem and restart the app.", - ), - "vaultStatusDescUploading": MessageLookupByLibrary.simpleMessage( - "Uploading your changes", - ), - "vaultStatusError": MessageLookupByLibrary.simpleMessage("Error"), - "vaultStatusLoaded": MessageLookupByLibrary.simpleMessage("Loaded"), - "vaultStatusRefreshing": MessageLookupByLibrary.simpleMessage("Refreshing"), - "vaultStatusSaveNeeded": MessageLookupByLibrary.simpleMessage( - "Save needed", - ), - "vaultStatusSaving": MessageLookupByLibrary.simpleMessage("Saving"), - "vaultStatusUnknownState": MessageLookupByLibrary.simpleMessage( - "Unknown state", - ), - "vaultStatusUploading": MessageLookupByLibrary.simpleMessage("Uploading"), - "vaultTooLarge": MessageLookupByLibrary.simpleMessage( - "Your Kee Vault is too large to save and sync to other devices. Delete some large file attachments, empty the bin, etc. and then try again.", - ), - "verificationRequest": m15, - "viewDocumentation": MessageLookupByLibrary.simpleMessage( - "View documentation", - ), - "viewEntries": MessageLookupByLibrary.simpleMessage("View Entries"), - "visitTheForum": MessageLookupByLibrary.simpleMessage("Visit the forum"), - "website": MessageLookupByLibrary.simpleMessage("Website"), - "welcomeToKeeVault": MessageLookupByLibrary.simpleMessage( - "Welcome to Kee Vault", - ), - "welcome_message": m16, - "willTrySamePasswordFirst": MessageLookupByLibrary.simpleMessage( - "We\'ll try using the same password you have used to open your current Kee Vault. If that doesn\'t work, you can type in the correct password in a moment.", - ), - "yourPasswordEntries": MessageLookupByLibrary.simpleMessage( - "Your password entries", - ), - "yourSubscription": MessageLookupByLibrary.simpleMessage( - "Your Subscription", - ), - }; + "accountDeletionNotes": MessageLookupByLibrary.simpleMessage( + "You don\'t need to delete your account. If you want to cancel your subscription, just do that using the information above. We\'ll then automatically delete your account, but if you really want to take additional steps to request the deletion of your account, we have created a way for you to do this on our website, which you can access by using the button below."), + "add": MessageLookupByLibrary.simpleMessage("Add"), + "addAttachment": + MessageLookupByLibrary.simpleMessage("Add small attachment"), + "addField": MessageLookupByLibrary.simpleMessage("Add field"), + "addTOTPSecret": + MessageLookupByLibrary.simpleMessage("Add TOTP / 2FA secret"), + "additionalCharacters": + MessageLookupByLibrary.simpleMessage("Additional characters"), + "additionalUrlsToMatch": + MessageLookupByLibrary.simpleMessage("Additional URLs to match"), + "agreeAndCheckAccountStatus": MessageLookupByLibrary.simpleMessage( + "Agree and check account status"), + "alertCancel": MessageLookupByLibrary.simpleMessage("Cancel"), + "alertClose": MessageLookupByLibrary.simpleMessage("Close"), + "alertCopy": MessageLookupByLibrary.simpleMessage("Copy"), + "alertNo": MessageLookupByLibrary.simpleMessage("No"), + "alertOk": MessageLookupByLibrary.simpleMessage("OK"), + "alertYes": MessageLookupByLibrary.simpleMessage("Yes"), + "alertYesPlease": MessageLookupByLibrary.simpleMessage("Yes please"), + "androidAppIdsToMatch": MessageLookupByLibrary.simpleMessage( + "Android app technical names to match"), + "appCannotLock": MessageLookupByLibrary.simpleMessage( + "You have unsaved changes that will be lost. Continue?"), + "apply": MessageLookupByLibrary.simpleMessage("Apply"), + "attachmentConfirmDelete": m0, + "attachmentError": + MessageLookupByLibrary.simpleMessage("Attachment error"), + "attachmentErrorDetails": MessageLookupByLibrary.simpleMessage( + "Sorry, we were unable to attach this file. Please check that you have enabled the necessary permissions for Kee Vault to access the file. If you still have problems please report it on the community forum along with full details of your device so that we can investigate whether we can add support for your particular device in future."), + "authenticating": + MessageLookupByLibrary.simpleMessage("Authenticating"), + "autofillEnabled": MessageLookupByLibrary.simpleMessage( + "Kee Vault is correctly set as your device\'s Autofill provider."), + "autofillNewEntryMakeChangesThenDone": MessageLookupByLibrary.simpleMessage( + "Entry saved. Make changes below if you want and then click \"Done\" below."), + "autofillRequiresQU": MessageLookupByLibrary.simpleMessage( + " You need to add a Passcode, FaceId or TouchId to your device too!"), + "autofilling": MessageLookupByLibrary.simpleMessage("Autofilling"), + "automaticallySignInFor": MessageLookupByLibrary.simpleMessage( + "Automatically sign-in for (seconds)"), + "bannerMsg1TitleA": MessageLookupByLibrary.simpleMessage( + "Want to hear about new features?"), + "bannerMsg1TitleB": MessageLookupByLibrary.simpleMessage( + "Want to hear about new features and how to register for automatic backups and access from your other devices?"), + "bannerMsgAutofillDisabled": MessageLookupByLibrary.simpleMessage( + "For easier sign-in to your apps and websites, you need to change your device\'s Autofill provider to Kee Vault."), + "bannerMsgSaving1": MessageLookupByLibrary.simpleMessage( + "Your Vault is being saved when this lock icon is flashing at the bottom of the screen."), + "bannerMsgSaving2": MessageLookupByLibrary.simpleMessage( + "Our high security protection is applied to your Vault every time you save it. This can take a little bit of time, and a slow internet connection can make it take longer too."), + "bannerReminderDelay3days": + MessageLookupByLibrary.simpleMessage("in 3 days"), + "bannerReminderDelay3months": + MessageLookupByLibrary.simpleMessage("in 3 months"), + "bannerReminderDelay3weeks": + MessageLookupByLibrary.simpleMessage("in 3 weeks"), + "bannerReminderDelayNever": + MessageLookupByLibrary.simpleMessage("never"), + "bannerReminderDelayRemindMe": + MessageLookupByLibrary.simpleMessage("Remind me..."), + "bigTechAntiCompetitionStatement": MessageLookupByLibrary.simpleMessage( + "The \"Big Tech\" companies prohibit us from directly linking to the account registration page on our website."), + "biometricSignIn": MessageLookupByLibrary.simpleMessage( + "Enable Quick sign-in (biometrics)"), + "biometricsErrorExplanation": m1, + "biometricsMaybeExpired": + MessageLookupByLibrary.simpleMessage("Please enter your password"), + "biometricsStoreDescription": m2, + "cancelExportOrImport": m3, + "changeCancelSubscription": MessageLookupByLibrary.simpleMessage( + "Change or Cancel Subscription"), + "changeEmail": + MessageLookupByLibrary.simpleMessage("Change email address"), + "changeEmailConfirmCheckbox": MessageLookupByLibrary.simpleMessage( + "I have read the above warnings, mitigated the risks and wish to continue"), + "changeEmailInfo1": MessageLookupByLibrary.simpleMessage( + "Your email address has a crucial role in the advanced security protections Kee Vault offers. Changing it securely is a far more complex task than for most of the places you might wish to change it. We are happy to finally offer this feature to you but please read the information carefully and don\'t proceed when you are in a rush."), + "changeEmailInfo2": MessageLookupByLibrary.simpleMessage( + "Your new email address will:"), + "changeEmailInfo2a": + MessageLookupByLibrary.simpleMessage("become your new sign-in ID"), + "changeEmailInfo2b": MessageLookupByLibrary.simpleMessage( + "need to be verified to confirm it belongs to you"), + "changeEmailInfo3": + MessageLookupByLibrary.simpleMessage("We recommend that you:"), + "changeEmailInfo3a": MessageLookupByLibrary.simpleMessage( + "1) Click the Cancel button below, sign in to Kee Vault again, Export your Vault to a KDBX file and store it somewhere safe as a backup."), + "changeEmailInfo3b": MessageLookupByLibrary.simpleMessage( + "2) Double check you enter the correct email address - you will need to type it exactly to sign in to your account in a moment."), + "changeEmailInfo3c": MessageLookupByLibrary.simpleMessage( + "3) Copy/paste what you have entered in the email address box and store somewhere like a note on your phone."), + "changeEmailInfo4": MessageLookupByLibrary.simpleMessage( + "If you make a mistake, you should be able to regain access to your Vault but in some cases you may need to create a new Kee Vault subscription and import from your previously exported KDBX file - this can result in additional hassle and costs since your old subscription would not be refundable."), + "changeEmailInfo5": MessageLookupByLibrary.simpleMessage( + "Your password will remain the same throughout the process. If you want to change that too, we first recommend signing in on multiple devices using your new email address and waiting at least an hour."), + "changeEmailPrefs": + MessageLookupByLibrary.simpleMessage("Change email preferences"), + "changePassword": + MessageLookupByLibrary.simpleMessage("Change Password"), + "changePasswordDetail": MessageLookupByLibrary.simpleMessage( + "Change the password you use to sign in to Kee Vault"), + "changePasswordWarning": MessageLookupByLibrary.simpleMessage( + "You may lose data if you are signed in on any other devices now. Please cancel (press back) and then sign out of all other devices, including the Kee Vault 1 web app. Then wait a minute and start this process again."), + "chooseAPassword": + MessageLookupByLibrary.simpleMessage("Please choose a password"), + "chooseAnIcon": MessageLookupByLibrary.simpleMessage("Choose an icon"), + "chooseNewParentGroupForEntry": MessageLookupByLibrary.simpleMessage( + "Select the group for this entry"), + "chooseNewParentGroupForGroup": m4, + "chooseRestoreGroup": MessageLookupByLibrary.simpleMessage( + "Select the group in which to restore this item"), + "color": MessageLookupByLibrary.simpleMessage("Colour"), + "colorFilteringHint": MessageLookupByLibrary.simpleMessage( + "Select colours above to display only entries with a matching colour."), + "colors": MessageLookupByLibrary.simpleMessage("Colours"), + "colorsExplanation": MessageLookupByLibrary.simpleMessage( + "Colours allow you to categorise your entries in a more simplistic and visual way than Groups or Labels."), + "confirmItsYou": MessageLookupByLibrary.simpleMessage( + "To access your passwords please confirm it\'s you"), + "continueSigningIn": + MessageLookupByLibrary.simpleMessage("Continue signing in"), + "copySecret": MessageLookupByLibrary.simpleMessage("Copy Secret"), + "createNewEntry": + MessageLookupByLibrary.simpleMessage("Create new entry"), + "createNewPasswordApplyExplanation": MessageLookupByLibrary.simpleMessage( + "Replace your old password with the new secure one shown above."), + "createNewPasswordConfigurationExplanation": + MessageLookupByLibrary.simpleMessage( + "Create a different password by choosing a preset and/or adjusting the settings below."), + "createNewPasswordCopyExplanation": MessageLookupByLibrary.simpleMessage( + "Copy the new secure password shown above to your device\'s copy/paste clipboard."), + "createSecurePassword": + MessageLookupByLibrary.simpleMessage("Create secure password"), + "createVault": MessageLookupByLibrary.simpleMessage("Create my Vault"), + "creating": MessageLookupByLibrary.simpleMessage("Creating"), + "currentEmailAddress": + MessageLookupByLibrary.simpleMessage("Current email address"), + "currentPassword": + MessageLookupByLibrary.simpleMessage("Current Password"), + "currentPasswordNotCorrect": MessageLookupByLibrary.simpleMessage( + "Current password is not correct"), + "delete": MessageLookupByLibrary.simpleMessage("Delete"), + "deleteAccount": MessageLookupByLibrary.simpleMessage("Delete Account"), + "deleteAttachment": + MessageLookupByLibrary.simpleMessage("Delete attachment"), + "deleteGroupConfirm": MessageLookupByLibrary.simpleMessage( + "Delete the group and all entries within it?"), + "detCreated": MessageLookupByLibrary.simpleMessage("Created"), + "detDelEntry": MessageLookupByLibrary.simpleMessage("Delete"), + "detDelEntryPerm": + MessageLookupByLibrary.simpleMessage("Delete permanently"), + "detFieldCopied": MessageLookupByLibrary.simpleMessage("Copied"), + "detGroup": MessageLookupByLibrary.simpleMessage("Group"), + "detHistoryRevert": + MessageLookupByLibrary.simpleMessage("Revert to state"), + "detHistoryRevertAlert": MessageLookupByLibrary.simpleMessage( + "Revert to this history state?"), + "detNetField": MessageLookupByLibrary.simpleMessage("New Field"), + "detOtpQrError": + MessageLookupByLibrary.simpleMessage("QR code scan error"), + "detOtpQrErrorBody": MessageLookupByLibrary.simpleMessage( + "Sorry, we could not read the QR code, please try once again or contact the app authors with error details."), + "detOtpQrWrong": MessageLookupByLibrary.simpleMessage("Wrong QR code"), + "detOtpQrWrongBody": MessageLookupByLibrary.simpleMessage( + "Your QR code was successfully scanned but it doesn\'t contain one-time password data."), + "detSetIcon": MessageLookupByLibrary.simpleMessage("Change icon"), + "detSetupOtpManualButton": + MessageLookupByLibrary.simpleMessage("Enter code manually"), + "detUpdated": MessageLookupByLibrary.simpleMessage("Updated"), + "deviceAutoFill": + MessageLookupByLibrary.simpleMessage("Device AutoFill"), + "disabled": MessageLookupByLibrary.simpleMessage("Disabled"), + "discard": MessageLookupByLibrary.simpleMessage("Discard"), + "discardChanges": + MessageLookupByLibrary.simpleMessage("Discard changes"), + "domain": MessageLookupByLibrary.simpleMessage("Domain"), + "done": MessageLookupByLibrary.simpleMessage("Done"), + "downloading": MessageLookupByLibrary.simpleMessage("Downloading"), + "email": MessageLookupByLibrary.simpleMessage("Email"), + "emailChanged": + MessageLookupByLibrary.simpleMessage("Email address changed"), + "emailValidationFail": MessageLookupByLibrary.simpleMessage( + "Not a valid email address. Please try again."), + "emailVerification": + MessageLookupByLibrary.simpleMessage("Email verification"), + "enableAutofill": + MessageLookupByLibrary.simpleMessage("Enable Autofill"), + "enableAutofillIosInstructions": m5, + "enableAutofillRequired": m6, + "enabled": MessageLookupByLibrary.simpleMessage("Enabled"), + "enterNewPresetName": MessageLookupByLibrary.simpleMessage( + "Enter the new name for the preset"), + "enterNumberBetweenXAndY": m7, + "enterOldPassword": MessageLookupByLibrary.simpleMessage( + "First, enter your current password."), + "enter_your_account_password": + MessageLookupByLibrary.simpleMessage("Enter your account password"), + "enter_your_email_address": + MessageLookupByLibrary.simpleMessage("Enter your email address"), + "entryAttachmentSizeError": MessageLookupByLibrary.simpleMessage( + "Large-sized file attachments like this one are not allowed because including them in your Vault will significantly slow down common tasks such as signing-in to your Vault and saving changes. Keep your attachments to a maximum of 250KB"), + "entryAttachmentSizeWarning": MessageLookupByLibrary.simpleMessage( + "Medium-sized file attachments like this one are allowed. However, including more than a small number of them in your Vault will significantly slow down common tasks such as signing-in to your Vault and saving changes. Try to keep your attachments below 20KB"), + "entryHistory": MessageLookupByLibrary.simpleMessage("Entry history"), + "entryHistoryExplainer": MessageLookupByLibrary.simpleMessage( + "Old versions of this entry are listed below. If you need to revert to an older version, we will automatically add your latest saved version to this list."), + "entryIntegrationHintNewId": MessageLookupByLibrary.simpleMessage( + "New ID (e.g. com.example... )"), + "entryIntegrationHintNewUrl": + MessageLookupByLibrary.simpleMessage("New URL (include https://)"), + "errorCorruptField": MessageLookupByLibrary.simpleMessage( + " : A field in this entry is corrupt. Please check the \'Help > Console log\' for details."), + "everyoneElseCanUseForFree": MessageLookupByLibrary.simpleMessage( + "Everyone else is welcome to use the app for free without an account."), + "exact": MessageLookupByLibrary.simpleMessage("Exact"), + "existingUser": MessageLookupByLibrary.simpleMessage("Existing User"), + "existingUsersSignInBelow": MessageLookupByLibrary.simpleMessage( + "If you already have a Kee Vault account on the https://keevault.pm \"Web App\" you can sign-in below."), + "expiredWhileSignedIn": MessageLookupByLibrary.simpleMessage( + "Your subscription has just expired. Please click \"Sign out\" from the main menu below, then sign-in and follow the instructions. Your data is still available at the moment so don\'t panic."), + "export": MessageLookupByLibrary.simpleMessage("Export"), + "exportAnyway": MessageLookupByLibrary.simpleMessage("Export anyway"), + "exportDirtyFileWarning": MessageLookupByLibrary.simpleMessage( + "We export the latest saved version of your Kee Vault. You may want to save your current changes before exporting."), + "exportError": MessageLookupByLibrary.simpleMessage("Export error"), + "exportErrorDetails": MessageLookupByLibrary.simpleMessage( + "Sorry, we were unable to export to this location. Please check that you have enabled the necessary permissions for Kee Vault to access the file. If you still have problems please report it on the community forum along with full details of your device so that we can investigate whether we can add support for your particular device in future."), + "exportUsesCurrentPassword": MessageLookupByLibrary.simpleMessage( + "Exports are encrypted and can be unlocked using the same password you use to open your Kee Vault."), + "exported": MessageLookupByLibrary.simpleMessage("Exported"), + "fieldName": MessageLookupByLibrary.simpleMessage("Field name"), + "filterTooltipClosed": MessageLookupByLibrary.simpleMessage( + "Reveal search options and other filters"), + "filterTooltipOpen": + MessageLookupByLibrary.simpleMessage("Show matching entries"), + "filteredByCriteria": m8, + "footerTitleGen": MessageLookupByLibrary.simpleMessage("Generate"), + "forgotPasswordOrCheckAccount": MessageLookupByLibrary.simpleMessage( + "Forgot your password or unsure if you have a Kee Vault account?"), + "freeUserTermsPopup1": MessageLookupByLibrary.simpleMessage( + "By using this app for free without an associated Kee Vault account, you are bound by the same terms and privacy policy as a user with an Account."), + "freeUserTermsPopup2": MessageLookupByLibrary.simpleMessage( + "However, some terms will obviously not be relevant to you immediately. To save time, you could skip these sections of the Terms of Service: B - Account Terms, E - Payment, F - Free Trial and G - Cancellation and Termination, although you might wish to review them anyway if you think that you may sign up for an Account one day in the future."), + "freeUserTermsPopup3": MessageLookupByLibrary.simpleMessage( + "You can view the documents here:"), + "freeUserTermsPopup4": MessageLookupByLibrary.simpleMessage( + "You will be given a further opportunity to review these documents if you later create a Kee Vault account."), + "genLen": MessageLookupByLibrary.simpleMessage("Length"), + "genPresetHigh": MessageLookupByLibrary.simpleMessage("High security"), + "genPresetMac": MessageLookupByLibrary.simpleMessage("MAC address"), + "genPresetMed": MessageLookupByLibrary.simpleMessage("Medium security"), + "genPresetPin4": MessageLookupByLibrary.simpleMessage("4-digit PIN"), + "genPresetPronounceable": + MessageLookupByLibrary.simpleMessage("Pronounceable"), + "genPresetVeryHigh": + MessageLookupByLibrary.simpleMessage("Very high security"), + "genPsAmbiguous": + MessageLookupByLibrary.simpleMessage("Ambiguous symbols"), + "genPsBrackets": MessageLookupByLibrary.simpleMessage("Brackets"), + "genPsDefault": + MessageLookupByLibrary.simpleMessage("Selected by default"), + "genPsDelete": MessageLookupByLibrary.simpleMessage("Delete preset"), + "genPsDigits": MessageLookupByLibrary.simpleMessage("Digits"), + "genPsHigh": + MessageLookupByLibrary.simpleMessage("High ASCII characters"), + "genPsLower": + MessageLookupByLibrary.simpleMessage("Lowercase latin letters"), + "genPsSpecial": MessageLookupByLibrary.simpleMessage("Special symbols"), + "genPsTitle": MessageLookupByLibrary.simpleMessage("Generator Presets"), + "genPsUpper": + MessageLookupByLibrary.simpleMessage("Uppercase latin letters"), + "generateSinglePassword": + MessageLookupByLibrary.simpleMessage("Generate single password"), + "gotIt": MessageLookupByLibrary.simpleMessage("Got it"), + "group": MessageLookupByLibrary.simpleMessage("group"), + "groupNameNewExplanation": MessageLookupByLibrary.simpleMessage( + "Enter the name for the new group"), + "groupNameRenameExplanation": MessageLookupByLibrary.simpleMessage( + "Enter the new name for the group"), + "help": MessageLookupByLibrary.simpleMessage("Help"), + "hexadecimal": MessageLookupByLibrary.simpleMessage("Hexadecimal"), + "hide": MessageLookupByLibrary.simpleMessage("Hide"), + "hostname": MessageLookupByLibrary.simpleMessage("Hostname"), + "identifying": MessageLookupByLibrary.simpleMessage("Identifying"), + "import": MessageLookupByLibrary.simpleMessage("Import"), + "importComplete": + MessageLookupByLibrary.simpleMessage("Import completed"), + "importError": MessageLookupByLibrary.simpleMessage("Import error"), + "importErrorDetails": MessageLookupByLibrary.simpleMessage( + "Sorry, we were unable to import this file. Please check that it is a valid KDBX file and that you have enabled the necessary permissions for Kee Vault to access the file. If you still have problems please report it on the community forum along with full details of your device so that we can investigate whether we can add support for your particular device in future."), + "importErrorKdbx": MessageLookupByLibrary.simpleMessage( + "Sorry, we were unable to import this KDBX file. You probably need to save it in a different way. More details: "), + "importExport": MessageLookupByLibrary.simpleMessage("Import / Export"), + "importKdbx": MessageLookupByLibrary.simpleMessage( + ".kdbx file (Kee Vault, KeePass, etc.)"), + "importOtherInstructions1": MessageLookupByLibrary.simpleMessage( + "We\'ll add specialised support for some other password manager storage formats in future but won\'t ever be able to directly support every one of the hundreds available."), + "importOtherInstructions4": MessageLookupByLibrary.simpleMessage( + "If you don\'t already have a file in the KDBX format, you could use the desktop computer version of KeePass Password Safe 2 to import from your original source, save the KDBX file and then import that here using the kdbx import option."), + "importUnlockRequired": MessageLookupByLibrary.simpleMessage( + "Enter your other password. This may be the old password you used on this device."), + "importedContinueToVault": + MessageLookupByLibrary.simpleMessage("Continue to your Vault"), + "importedFree1": MessageLookupByLibrary.simpleMessage( + "Thanks for signing in to a Kee Vault account. You already had a locally stored Vault on this device."), + "importedFree2": MessageLookupByLibrary.simpleMessage( + "We have automatically imported your local passwords to a new Group in your Kee Vault account. You may wish to rename the group or manually remove/edit the entries to resolve any duplication. You can read more about this and find more detailed instructions in "), + "importedManual": MessageLookupByLibrary.simpleMessage( + "We have imported your passwords to a new Group in your Kee Vault. You may wish to rename the group or manually remove/edit the entries to resolve any duplication. You can read more about this and find more detailed instructions in "), + "incorrectFile": MessageLookupByLibrary.simpleMessage("Incorrect file"), + "integrationSettings": + MessageLookupByLibrary.simpleMessage("Integration settings"), + "integrationSettingsExplainer": MessageLookupByLibrary.simpleMessage( + "These settings help you to refine when this entry is autofilled into other apps and websites. Some settings apply only to when you use Kee on a desktop computer and others only to specific mobile platforms (such as Android)."), + "introFilter": MessageLookupByLibrary.simpleMessage( + "\nFilter by group, label, colour and text"), + "introSortYourEntries": + MessageLookupByLibrary.simpleMessage("\nSort your entries"), + "keeVaultFormatExplainer": MessageLookupByLibrary.simpleMessage( + "Kee Vault uses a standard format to securely store your passwords. You are free to export your passwords in this format to create a backup of your data. You can also import additional passwords to your vault from this screen."), + "keep": MessageLookupByLibrary.simpleMessage("Keep"), + "keep_your_changes_question": MessageLookupByLibrary.simpleMessage( + "Do you want to keep your changes?"), + "label": MessageLookupByLibrary.simpleMessage("Label"), + "labelAssignmentExplanation": MessageLookupByLibrary.simpleMessage( + "Add new or existing labels to entries by editing the entry."), + "labelFilteringHint": MessageLookupByLibrary.simpleMessage( + "Select labels above to display only entries with a matching label."), + "labels": MessageLookupByLibrary.simpleMessage("Labels"), + "labelsExplanation": MessageLookupByLibrary.simpleMessage( + "Labels allow you to categorise your entries."), + "labelsExplanation2": MessageLookupByLibrary.simpleMessage( + "Unlike Groups, each entry can be assigned more than one label."), + "loading": MessageLookupByLibrary.simpleMessage("Loading"), + "localOnlyAgree1": + MessageLookupByLibrary.simpleMessage("You need to agree to the "), + "localOnlyAgree2": MessageLookupByLibrary.simpleMessage( + "Terms of Service and Privacy Statement"), + "localOnlyAgree3": MessageLookupByLibrary.simpleMessage( + ". We\'ll remember this until you uninstall the app or clear the app data. You MUST avoid clearing stored App data or you will also delete the passwords, usernames and other data you store in the app!"), + "localOnlyAgree4": MessageLookupByLibrary.simpleMessage( + "I understand and agree to the above"), + "localOnlyIntro": MessageLookupByLibrary.simpleMessage( + "Kee Vault supports one free user on your device. The passwords you store into your Vault will be held securely on only this device so you should ensure that you do not delete the App\'s Data and that you take regular backups."), + "lock": MessageLookupByLibrary.simpleMessage("Lock"), + "longPressGroupExplanation": MessageLookupByLibrary.simpleMessage( + "Long-press on a group to rename, move or delete it, or to create a new subgroup."), + "makeMoreChangesOrSave1": MessageLookupByLibrary.simpleMessage( + "Entry updated. Don\'t forget to Save your Vault when you have finished creating and changing entries."), + "makeMoreChangesOrSave2": MessageLookupByLibrary.simpleMessage( + "You don\'t need to save after every change you make but make sure you save before closing the app or locking your Vault."), + "makeMoreChangesOrSave3": MessageLookupByLibrary.simpleMessage( + "Beware that some devices will randomly delete unsaved data if you switch to using a different app for a little while."), + "manageAccount": MessageLookupByLibrary.simpleMessage("Manage account"), + "manageAccountDetail": MessageLookupByLibrary.simpleMessage( + "Manage your Kee Vault account"), + "manageAccountSettingsDetail": MessageLookupByLibrary.simpleMessage( + "Edit your subscription, payment details or email contact preferences from the Kee Vault Account website."), + "managePasswordPresets": + MessageLookupByLibrary.simpleMessage("Manage password presets"), + "managePresets": MessageLookupByLibrary.simpleMessage("Manage presets"), + "menuEmptyTrash": MessageLookupByLibrary.simpleMessage("Empty Bin"), + "menuEmptyTrashAlert": + MessageLookupByLibrary.simpleMessage("Empty Bin?"), + "menuEmptyTrashAlertBody": MessageLookupByLibrary.simpleMessage( + "You will not be able to get the entries back"), + "menuSetGeneral": MessageLookupByLibrary.simpleMessage("General"), + "menuTrash": MessageLookupByLibrary.simpleMessage("Bin"), + "merging": MessageLookupByLibrary.simpleMessage("Merging"), + "minURLMatchAccuracy": MessageLookupByLibrary.simpleMessage( + "Minimum accuracy for a URL match"), + "minURLMatchAccuracyExactWarning": MessageLookupByLibrary.simpleMessage( + "If you select Exact (for use on desktop web browsers) we\'ll use Hostname matching on mobile instead because Android and iOS do not permit Exact matching."), + "minimumMatchAccuracyDomainExplainer": + MessageLookupByLibrary.simpleMessage( + "The URL only needs to be part of the same domain to match."), + "minimumMatchAccuracyExactExplainer": MessageLookupByLibrary.simpleMessage( + "The URL must match exactly including full path and query string."), + "minimumMatchAccuracyHostnameExplainer": + MessageLookupByLibrary.simpleMessage( + "The URL must match the hostname (domain and subdomains) and port."), + "move": MessageLookupByLibrary.simpleMessage("Move"), + "name": MessageLookupByLibrary.simpleMessage("name"), + "newEmailAddress": + MessageLookupByLibrary.simpleMessage("New email address"), + "newGroup": MessageLookupByLibrary.simpleMessage("New Group"), + "newPassword": MessageLookupByLibrary.simpleMessage("New password"), + "newPasswordRepeat": MessageLookupByLibrary.simpleMessage( + "New password (please repeat)"), + "newProfile": MessageLookupByLibrary.simpleMessage("New profile"), + "newUser": MessageLookupByLibrary.simpleMessage("New User"), + "noEntriesCreateNewInstruction": MessageLookupByLibrary.simpleMessage( + "You have no password entries yet. Create one using the + button below. If you have passwords already stored in the standard KDBX (KeePass) format you can import them."), + "noLongerHaveAccessToUnverifiedEmail": + MessageLookupByLibrary.simpleMessage( + "No longer have access to your email address?"), + "notSignedIn": MessageLookupByLibrary.simpleMessage("Not signed in"), + "notes": MessageLookupByLibrary.simpleMessage("Notes"), + "occasionalNotifications": MessageLookupByLibrary.simpleMessage( + "Please send me occasional emails including new feature announcements and tips/advice on how to stay secure and get the most out of your Kee Vault account."), + "offerToSave": + MessageLookupByLibrary.simpleMessage("Offer to save passwords"), + "openError": MessageLookupByLibrary.simpleMessage("Error"), + "openInBrowser": + MessageLookupByLibrary.simpleMessage("Open in browser"), + "openLogConsole": + MessageLookupByLibrary.simpleMessage("Share/view logs"), + "openSettings": MessageLookupByLibrary.simpleMessage("Open settings"), + "openUrl": MessageLookupByLibrary.simpleMessage("URL"), + "openWebApp": MessageLookupByLibrary.simpleMessage( + "Open Kee Vault in your browser"), + "opening": MessageLookupByLibrary.simpleMessage("Opening"), + "otp": MessageLookupByLibrary.simpleMessage("OTP"), + "otpCodeLabel": + MessageLookupByLibrary.simpleMessage("TOTP code (base32 format)"), + "otpExplainer1": MessageLookupByLibrary.simpleMessage( + "\"One Time Passwords\" (OTP) are a feature some websites offer to improve security. It is a type of Two/Multi Factor Authentication (2FA/MFA)."), + "otpManualError": + MessageLookupByLibrary.simpleMessage("Invalid TOTP code"), + "otpManualErrorBody": MessageLookupByLibrary.simpleMessage( + "You did not enter a valid TOTP base32 code. Please try again."), + "otpManualTitle": MessageLookupByLibrary.simpleMessage( + "Time-based One Time Password"), + "password": MessageLookupByLibrary.simpleMessage("Password"), + "passwordChanged": MessageLookupByLibrary.simpleMessage( + "Password changed. Use it when you next unlock Kee Vault."), + "passwordRepeat": + MessageLookupByLibrary.simpleMessage("Password (please repeat)"), + "passwordStrength": + MessageLookupByLibrary.simpleMessage("Password strength"), + "permanentlyDeleteGroupConfirm": MessageLookupByLibrary.simpleMessage( + "Permanently delete the group and all entries within it?"), + "permissionDeniedError": m9, + "permissionDeniedPermanentlyError": m10, + "permissionError": + MessageLookupByLibrary.simpleMessage("Permission error"), + "permissionReasonAttachFile": + MessageLookupByLibrary.simpleMessage("attach a file"), + "permissionReasonScanBarcodes": MessageLookupByLibrary.simpleMessage( + "quickly scan QR codes (barcodes)"), + "permissionSettingsOpenError": MessageLookupByLibrary.simpleMessage( + "Sorry, your device did not allow us to open the settings for this app. Please use your device settings app to find and change the permissions settings for Kee Vault and then return here to try again."), + "prcRegistrationError": MessageLookupByLibrary.simpleMessage( + "Sorry, we weren\'t able to register your email address now. Please check that you have a good network connection and try again or ask for help on the community forum if the problem continues."), + "prcRegistrationPrivacy1": MessageLookupByLibrary.simpleMessage( + "The same privacy policy applies as when you started using the app. In brief, we\'ll protect (encrypt) your email address when we store it and will never share it or use it for anything you haven\'t agreed to. You can unsubscribe easily from each email we send to you."), + "prcRegistrationPrivacy2": MessageLookupByLibrary.simpleMessage( + "You can review the full policy here:"), + "prcRegistrationSignUpButton": + MessageLookupByLibrary.simpleMessage("Sign up to receive emails"), + "prcRegistrationSuccess": MessageLookupByLibrary.simpleMessage( + "Success! Please check your emails soon to confirm that you want to receive updates from us."), + "prcSignupOrAccountStatusCheck": m11, + "preset": MessageLookupByLibrary.simpleMessage("Preset"), + "privacyStatement": + MessageLookupByLibrary.simpleMessage("Privacy Statement"), + "privacySummaryExplainer": MessageLookupByLibrary.simpleMessage( + "We take pride in how we protect your privacy and security, particularly in comparison to other password management services, so we highlight the most important information right here."), + "protectField": MessageLookupByLibrary.simpleMessage("Protect field"), + "protectedClickToReveal": MessageLookupByLibrary.simpleMessage( + "Protected field. Click to reveal."), + "quickSignIn": MessageLookupByLibrary.simpleMessage("Quick sign-in"), + "quickSignInExplainer": m12, + "reenterYourPassword": MessageLookupByLibrary.simpleMessage( + "Please re-enter your password"), + "register": MessageLookupByLibrary.simpleMessage("Register"), + "registrationBlurb1": MessageLookupByLibrary.simpleMessage( + "Choose a secure password to protect your Kee Vault. There are no \"requirements\" so just make it as strong as you can. Only you will know this password - it never leaves your device. It can not be reset so you must not forget it, but you can change it when you\'re signed in to Kee Vault."), + "registrationBlurb2": MessageLookupByLibrary.simpleMessage( + "Your email address is securely sent to a Kee Vault server (a computer on the internet) and immediately encrypted so that no-one can view it, even if the Kee Vault account database is illegally accessed. Our advanced personal data protection solution means that even when you next sign in to Kee Vault, your email address is not transmitted."), + "registrationBlurb3": MessageLookupByLibrary.simpleMessage( + "We will share your email address only with 3rd parties that are essential to the operation of the Kee Vault service. For example, for payment processing. We demand the highest level of security and privacy from these recipients of your personal data."), + "registrationBlurb4": MessageLookupByLibrary.simpleMessage( + "Potentially personally identifiable information is only kept for as long as is needed for us to deliver the service to you and meet our legal obligations. For example, the server logs IP addresses as part of protecting your account from unauthorised access attempts."), + "registrationBlurb4old": MessageLookupByLibrary.simpleMessage( + "The Kee Vault servers are connected to the internet so various internet infrastructure companies may be in a position to view your email address. As explained above, we will encrypt it during transfer and storage, and follow all other best practice to minimise this risk."), + "registrationBlurb5": MessageLookupByLibrary.simpleMessage( + "To improve Kee Vault for you, we may record anonymous usage data across our apps, keevault.pm and our associated websites. This never includes personally identifiable information (or passwords!) and is never shared."), + "registrationBlurb7": MessageLookupByLibrary.simpleMessage( + "The security of your information depends upon the security of the devices that you use to access Kee Vault. This is no different to every other online or offline app but we want to re-iterate that point here: any software or service that claims to protect you from a security breach on a local device is misleading you - it is your responsibility to keep your local device secure."), + "registrationEmailUsage1": MessageLookupByLibrary.simpleMessage( + "We and/or our essential 3rd party partners will send you emails that relate to critical service or security issues as necessary. We\'ll send a handful of introductory emails with usage instructions and tips which are legitimately in your interest but you can unsubscribe any time from the emails themselves. Receiving marketing emails is optional. We recommend opting in to evaluate whether the frequency and content of emails is suitable for you because it\'s easy to unsubscribe at any time."), + "registrationPrivacyOverview1": MessageLookupByLibrary.simpleMessage( + "The information above is intended as simple guide to what we think are the most critical privacy and security concerns relating to your use of the Kee Vault service but they are not a substitute for our full Terms of Service and Privacy Statement. Also note that your Subscription (payment) agreement may be with a 3rd party and they will show you those additional terms and conditions at the appropriate point of your subscription sign-up."), + "rememberExportsDoNotUpdate": MessageLookupByLibrary.simpleMessage( + "Remember that Exports do not automatically update. The information stored within and the password required to unlock it does not change after you create the export."), + "rememberFilterGroup": MessageLookupByLibrary.simpleMessage( + "Remember chosen filter group"), + "rememberVaultPassword": MessageLookupByLibrary.simpleMessage( + "Remember your Vault password?"), + "renameFieldEnterNewName": MessageLookupByLibrary.simpleMessage( + "Enter the new name for the field"), + "renamingField": MessageLookupByLibrary.simpleMessage("Renaming field"), + "renamingPreset": + MessageLookupByLibrary.simpleMessage("Renaming preset"), + "requireFullPasswordEvery": MessageLookupByLibrary.simpleMessage( + "Require full password every (days)"), + "resendVerification": MessageLookupByLibrary.simpleMessage( + "Resend the verification link"), + "resetEntryToThis": + MessageLookupByLibrary.simpleMessage("Reset entry to this state"), + "resetPasswordInstructions": MessageLookupByLibrary.simpleMessage( + "You can reset your password using the Kee Vault \"Web App\" (version 1)."), + "restartSubscription": + MessageLookupByLibrary.simpleMessage("Restart subscription"), + "restore": MessageLookupByLibrary.simpleMessage("Restore"), + "revertUnsavedWarning": MessageLookupByLibrary.simpleMessage( + "Your unsaved changes will be permanently lost if you change to this older version now. Do you want to discard your changes?"), + "save": MessageLookupByLibrary.simpleMessage("Save"), + "saveChanges": MessageLookupByLibrary.simpleMessage("Confirm changes"), + "saveExplainerAlertTitle": + MessageLookupByLibrary.simpleMessage("Saving..."), + "saveVault": MessageLookupByLibrary.simpleMessage("Save Vault"), + "search": MessageLookupByLibrary.simpleMessage("Search"), + "searchCase": MessageLookupByLibrary.simpleMessage("Match case"), + "searchHistory": + MessageLookupByLibrary.simpleMessage("Include entry history"), + "searchOtherSecure": + MessageLookupByLibrary.simpleMessage("Other protected fields"), + "searchOtherStandard": + MessageLookupByLibrary.simpleMessage("Other standard fields"), + "searchRegex": MessageLookupByLibrary.simpleMessage("RegEx"), + "searchSearchIn": MessageLookupByLibrary.simpleMessage( + "Search in these entry fields:"), + "selectKdbxFile": + MessageLookupByLibrary.simpleMessage("Please select a KDBX file."), + "serverMITMWarning": MessageLookupByLibrary.simpleMessage( + "Sign in failed because the response we received from the server indicates that it may be compromised. The most likely explanation is that someone near you or at your internet service provider is attempting to interfere with the secure connection and connect you to a malicious server (A Miscreant In The Middle attack). Find a different internet connection immediately, shut down the Kee Vault app and try again. If it keeps happening, your local device may be compromised. The security of your Kee Vault remains intact so you need not panic. More information about the error is available at https://forum.kee.pm/"), + "setDefault": MessageLookupByLibrary.simpleMessage("Set as default"), + "setFilePassNotMatch": MessageLookupByLibrary.simpleMessage( + "Passwords don\'t match, please type them again"), + "setGenShowSubgroups": MessageLookupByLibrary.simpleMessage( + "Show entries from all subgroups"), + "setGenTheme": MessageLookupByLibrary.simpleMessage("Theme"), + "setGenThemeDk": MessageLookupByLibrary.simpleMessage("Dark"), + "setGenThemeLt": MessageLookupByLibrary.simpleMessage("Light"), + "setGenTitlebarStyleDefault": + MessageLookupByLibrary.simpleMessage("Default"), + "settings": MessageLookupByLibrary.simpleMessage("Settings"), + "settingsNotSignedInError": MessageLookupByLibrary.simpleMessage( + "You are not signed in so we cannot proceed. Try returning to the app home page or kill and re-open the app if you are having trouble reaching the sign-in screen again."), + "share": MessageLookupByLibrary.simpleMessage("Share"), + "show": MessageLookupByLibrary.simpleMessage("Show"), + "showEntryInBrowsersAndApps": MessageLookupByLibrary.simpleMessage( + "Show this entry in Kee browser extension (desktop), mobile apps and browsers"), + "showProtectedField": + MessageLookupByLibrary.simpleMessage("Show protected field"), + "showing_all_entries": + MessageLookupByLibrary.simpleMessage("Showing all entries"), + "signInAgainWhenVerified": MessageLookupByLibrary.simpleMessage( + "When your email address is successfully verified you can click the button below to continue your sign-in."), + "signin": MessageLookupByLibrary.simpleMessage("Sign in"), + "signout": MessageLookupByLibrary.simpleMessage("Sign out"), + "sizeBytes": m13, + "sortCreated": MessageLookupByLibrary.simpleMessage("Newest"), + "sortCreatedReversed": MessageLookupByLibrary.simpleMessage("Oldest"), + "sortModified": + MessageLookupByLibrary.simpleMessage("Recently updated"), + "sortModifiedReversed": + MessageLookupByLibrary.simpleMessage("Least recently updated"), + "sortTitle": MessageLookupByLibrary.simpleMessage("Title"), + "sortTitleReversed": + MessageLookupByLibrary.simpleMessage("Title - reversed"), + "startAccountReset": + MessageLookupByLibrary.simpleMessage("Start account reset"), + "startFreeTrial": + MessageLookupByLibrary.simpleMessage("Start free trial"), + "startNewTrialError": MessageLookupByLibrary.simpleMessage( + "Sorry, we weren\'t able to restart your trial now. Please try again later and ask for help on the community forum if the problem continues."), + "startNewTrialSuccess": + MessageLookupByLibrary.simpleMessage("All done!"), + "subscriptionAssociatingDescription": MessageLookupByLibrary.simpleMessage( + "Nearly there. Your subscription is being processed and we are setting up your account. This usually takes a few seconds but can take longer at busy times. We\'ll keep trying for a minute so don\'t close the app or lock your phone before then."), + "subscriptionCancellationNotes": MessageLookupByLibrary.simpleMessage( + "Cancellation notes: If you cancel your subscription, once your current subscription term ends, we will delete your account in a way that protects your data at all times. After some time, your Kee Vault data will be permanently deleted so you must make sure that you have exported the latest copy of your data before you cancel your subscription. To continue using the app as a free user, you must first export your data to a KDBX file, then uninstall and reinstall the app. You can then import the exported KDBX file once you start using the app again as a free user. We recommend you plan carefully to minimise your risk of data loss."), + "subscriptionExpired": + MessageLookupByLibrary.simpleMessage("Subscription expired"), + "subscriptionExpiredDetails": MessageLookupByLibrary.simpleMessage( + "Your subscription or trial period has ended. Provide up to date payment details and re-enable your subscription on the Kee Vault Account Management web site."), + "subscriptionExpiredIapDetails": MessageLookupByLibrary.simpleMessage( + "Your subscription or trial period has ended. Please restart your subscription to continue."), + "subscriptionExpiredNoAction": MessageLookupByLibrary.simpleMessage( + "Your subscription or trial period has ended. Please contact us to discuss options for renewal."), + "subscriptionExpiredTrialAvailable": MessageLookupByLibrary.simpleMessage( + "Welcome back to Kee Vault. You can enable a new 30 day free trial to see what has improved since you first created your Kee Vault account."), + "tagRename": MessageLookupByLibrary.simpleMessage("Rename"), + "text": MessageLookupByLibrary.simpleMessage("Text"), + "textFilteringHint": MessageLookupByLibrary.simpleMessage( + "These options change how Search uses your text input to find entries."), + "thisCommunityForumTopic": + MessageLookupByLibrary.simpleMessage("this community forum topic"), + "this_field_required": + MessageLookupByLibrary.simpleMessage("This field is required"), + "title": MessageLookupByLibrary.simpleMessage("title"), + "tryAgain": MessageLookupByLibrary.simpleMessage("Try again"), + "unexpected_error": m14, + "unlock": MessageLookupByLibrary.simpleMessage("Unlock"), + "unlockRequired": + MessageLookupByLibrary.simpleMessage("Unlock your Vault"), + "unlock_with_biometrics": + MessageLookupByLibrary.simpleMessage("Use biometrics"), + "unprotectField": + MessageLookupByLibrary.simpleMessage("Unprotect field"), + "urlOpenFailed": MessageLookupByLibrary.simpleMessage( + "Your device stopped us opening that resource"), + "useWebAppForOtherSettings": MessageLookupByLibrary.simpleMessage( + "You can change some additional settings from the Kee Vault web app by using your web browser to sign in to Kee Vault."), + "user": MessageLookupByLibrary.simpleMessage("user"), + "userEmail": MessageLookupByLibrary.simpleMessage("User/Email"), + "vaultStatusActionNeeded": + MessageLookupByLibrary.simpleMessage("Action needed"), + "vaultStatusDescLoaded": MessageLookupByLibrary.simpleMessage( + "Your Vault is loaded and ready for use."), + "vaultStatusDescMerging": MessageLookupByLibrary.simpleMessage( + "Merging your changes from your other devices"), + "vaultStatusDescPasswordChanged": + MessageLookupByLibrary.simpleMessage("Your password has changed"), + "vaultStatusDescRefreshing": MessageLookupByLibrary.simpleMessage( + "Checking for changes from your other devices"), + "vaultStatusDescSaveNeeded": MessageLookupByLibrary.simpleMessage( + "There are changes from other devices which will be merged with this device when you next save."), + "vaultStatusDescSaving": + MessageLookupByLibrary.simpleMessage("Saving your changes"), + "vaultStatusDescUnknown": MessageLookupByLibrary.simpleMessage( + "If this situation does not automatically resolve itself within a minute, please check the Console Log in the Help section, report the problem and restart the app."), + "vaultStatusDescUploading": + MessageLookupByLibrary.simpleMessage("Uploading your changes"), + "vaultStatusError": MessageLookupByLibrary.simpleMessage("Error"), + "vaultStatusLoaded": MessageLookupByLibrary.simpleMessage("Loaded"), + "vaultStatusRefreshing": + MessageLookupByLibrary.simpleMessage("Refreshing"), + "vaultStatusSaveNeeded": + MessageLookupByLibrary.simpleMessage("Save needed"), + "vaultStatusSaving": MessageLookupByLibrary.simpleMessage("Saving"), + "vaultStatusUnknownState": + MessageLookupByLibrary.simpleMessage("Unknown state"), + "vaultStatusUploading": + MessageLookupByLibrary.simpleMessage("Uploading"), + "vaultTooLarge": MessageLookupByLibrary.simpleMessage( + "Your Kee Vault is too large to save and sync to other devices. Delete some large file attachments, empty the bin, etc. and then try again."), + "verificationRequest": m15, + "viewDocumentation": + MessageLookupByLibrary.simpleMessage("View documentation"), + "viewEntries": MessageLookupByLibrary.simpleMessage("View Entries"), + "visitTheForum": + MessageLookupByLibrary.simpleMessage("Visit the forum"), + "website": MessageLookupByLibrary.simpleMessage("Website"), + "welcomeToKeeVault": + MessageLookupByLibrary.simpleMessage("Welcome to Kee Vault"), + "welcome_message": m16, + "willTrySamePasswordFirst": MessageLookupByLibrary.simpleMessage( + "We\'ll try using the same password you have used to open your current Kee Vault. If that doesn\'t work, you can type in the correct password in a moment."), + "yourPasswordEntries": + MessageLookupByLibrary.simpleMessage("Your password entries"), + "yourSubscription": + MessageLookupByLibrary.simpleMessage("Your Subscription") + }; } diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 6ced32f..eed1a8a 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -18,20 +18,17 @@ class S { static S? _current; static S get current { - assert( - _current != null, - 'No instance of S was loaded. Try to initialize the S delegate before accessing S.current.', - ); + assert(_current != null, + 'No instance of S was loaded. Try to initialize the S delegate before accessing S.current.'); return _current!; } static const AppLocalizationDelegate delegate = AppLocalizationDelegate(); static Future load(Locale locale) { - final name = - (locale.countryCode?.isEmpty ?? false) - ? locale.languageCode - : locale.toString(); + final name = (locale.countryCode?.isEmpty ?? false) + ? locale.languageCode + : locale.toString(); final localeName = Intl.canonicalizedLocale(name); return initializeMessages(localeName).then((_) { Intl.defaultLocale = localeName; @@ -44,10 +41,8 @@ class S { static S of(BuildContext context) { final instance = S.maybeOf(context); - assert( - instance != null, - 'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?', - ); + assert(instance != null, + 'No instance of S present in the widget tree. Did you add S.delegate in localizationsDelegates?'); return instance!; } @@ -57,27 +52,52 @@ class S { /// `Loading` String get loading { - return Intl.message('Loading', name: 'loading', desc: '', args: []); + return Intl.message( + 'Loading', + name: 'loading', + desc: '', + args: [], + ); } /// `Downloading` String get downloading { - return Intl.message('Downloading', name: 'downloading', desc: '', args: []); + return Intl.message( + 'Downloading', + name: 'downloading', + desc: '', + args: [], + ); } /// `Opening` String get opening { - return Intl.message('Opening', name: 'opening', desc: '', args: []); + return Intl.message( + 'Opening', + name: 'opening', + desc: '', + args: [], + ); } /// `Merging` String get merging { - return Intl.message('Merging', name: 'merging', desc: '', args: []); + return Intl.message( + 'Merging', + name: 'merging', + desc: '', + args: [], + ); } /// `Identifying` String get identifying { - return Intl.message('Identifying', name: 'identifying', desc: '', args: []); + return Intl.message( + 'Identifying', + name: 'identifying', + desc: '', + args: [], + ); } /// `Authenticating` @@ -122,12 +142,22 @@ class S { /// `Email` String get email { - return Intl.message('Email', name: 'email', desc: '', args: []); + return Intl.message( + 'Email', + name: 'email', + desc: '', + args: [], + ); } /// `Password` String get password { - return Intl.message('Password', name: 'password', desc: '', args: []); + return Intl.message( + 'Password', + name: 'password', + desc: '', + args: [], + ); } /// `This field is required` @@ -142,27 +172,52 @@ class S { /// `Unlock` String get unlock { - return Intl.message('Unlock', name: 'unlock', desc: '', args: []); + return Intl.message( + 'Unlock', + name: 'unlock', + desc: '', + args: [], + ); } /// `Save` String get save { - return Intl.message('Save', name: 'save', desc: '', args: []); + return Intl.message( + 'Save', + name: 'save', + desc: '', + args: [], + ); } /// `Save Vault` String get saveVault { - return Intl.message('Save Vault', name: 'saveVault', desc: '', args: []); + return Intl.message( + 'Save Vault', + name: 'saveVault', + desc: '', + args: [], + ); } /// `Lock` String get lock { - return Intl.message('Lock', name: 'lock', desc: '', args: []); + return Intl.message( + 'Lock', + name: 'lock', + desc: '', + args: [], + ); } /// `OTP` String get otp { - return Intl.message('OTP', name: 'otp', desc: '', args: []); + return Intl.message( + 'OTP', + name: 'otp', + desc: '', + args: [], + ); } /// `Showing all entries` @@ -207,22 +262,42 @@ class S { /// `Discard` String get discard { - return Intl.message('Discard', name: 'discard', desc: '', args: []); + return Intl.message( + 'Discard', + name: 'discard', + desc: '', + args: [], + ); } /// `Keep` String get keep { - return Intl.message('Keep', name: 'keep', desc: '', args: []); + return Intl.message( + 'Keep', + name: 'keep', + desc: '', + args: [], + ); } /// `Colour` String get color { - return Intl.message('Colour', name: 'color', desc: '', args: []); + return Intl.message( + 'Colour', + name: 'color', + desc: '', + args: [], + ); } /// `Title` String get sortTitle { - return Intl.message('Title', name: 'sortTitle', desc: '', args: []); + return Intl.message( + 'Title', + name: 'sortTitle', + desc: '', + args: [], + ); } /// `Title - reversed` @@ -257,7 +332,12 @@ class S { /// `Newest` String get sortCreated { - return Intl.message('Newest', name: 'sortCreated', desc: '', args: []); + return Intl.message( + 'Newest', + name: 'sortCreated', + desc: '', + args: [], + ); } /// `Oldest` @@ -482,7 +562,12 @@ class S { /// `Add` String get add { - return Intl.message('Add', name: 'add', desc: '', args: []); + return Intl.message( + 'Add', + name: 'add', + desc: '', + args: [], + ); } /// `The URL only needs to be part of the same domain to match.` @@ -537,7 +622,12 @@ class S { /// `Preset` String get preset { - return Intl.message('Preset', name: 'preset', desc: '', args: []); + return Intl.message( + 'Preset', + name: 'preset', + desc: '', + args: [], + ); } /// `Manage presets` @@ -562,12 +652,22 @@ class S { /// `Move` String get move { - return Intl.message('Move', name: 'move', desc: '', args: []); + return Intl.message( + 'Move', + name: 'move', + desc: '', + args: [], + ); } /// `New Group` String get newGroup { - return Intl.message('New Group', name: 'newGroup', desc: '', args: []); + return Intl.message( + 'New Group', + name: 'newGroup', + desc: '', + args: [], + ); } /// `Long-press on a group to rename, move or delete it, or to create a new subgroup.` @@ -582,7 +682,12 @@ class S { /// `Restore` String get restore { - return Intl.message('Restore', name: 'restore', desc: '', args: []); + return Intl.message( + 'Restore', + name: 'restore', + desc: '', + args: [], + ); } /// `Enter the new name for the group` @@ -697,12 +802,22 @@ class S { /// `Label` String get label { - return Intl.message('Label', name: 'label', desc: '', args: []); + return Intl.message( + 'Label', + name: 'label', + desc: '', + args: [], + ); } /// `Labels` String get labels { - return Intl.message('Labels', name: 'labels', desc: '', args: []); + return Intl.message( + 'Labels', + name: 'labels', + desc: '', + args: [], + ); } /// `Colours allow you to categorise your entries in a more simplistic and visual way than Groups or Labels.` @@ -767,12 +882,22 @@ class S { /// `Notes` String get notes { - return Intl.message('Notes', name: 'notes', desc: '', args: []); + return Intl.message( + 'Notes', + name: 'notes', + desc: '', + args: [], + ); } /// `Website` String get website { - return Intl.message('Website', name: 'website', desc: '', args: []); + return Intl.message( + 'Website', + name: 'website', + desc: '', + args: [], + ); } /// `Include entry history` @@ -787,7 +912,12 @@ class S { /// `Colours` String get colors { - return Intl.message('Colours', name: 'colors', desc: '', args: []); + return Intl.message( + 'Colours', + name: 'colors', + desc: '', + args: [], + ); } /// `Filtered by {criteria}` @@ -862,7 +992,12 @@ class S { /// `Error` String get vaultStatusError { - return Intl.message('Error', name: 'vaultStatusError', desc: '', args: []); + return Intl.message( + 'Error', + name: 'vaultStatusError', + desc: '', + args: [], + ); } /// `Save needed` @@ -987,7 +1122,12 @@ class S { /// `Try again` String get tryAgain { - return Intl.message('Try again', name: 'tryAgain', desc: '', args: []); + return Intl.message( + 'Try again', + name: 'tryAgain', + desc: '', + args: [], + ); } /// `Not signed in` @@ -1032,7 +1172,12 @@ class S { /// `New profile` String get newProfile { - return Intl.message('New profile', name: 'newProfile', desc: '', args: []); + return Intl.message( + 'New profile', + name: 'newProfile', + desc: '', + args: [], + ); } /// `You need to agree to the ` @@ -1077,7 +1222,12 @@ class S { /// `Creating` String get creating { - return Intl.message('Creating', name: 'creating', desc: '', args: []); + return Intl.message( + 'Creating', + name: 'creating', + desc: '', + args: [], + ); } /// `By using this app for free without an associated Kee Vault account, you are bound by the same terms and privacy policy as a user with an Account.` @@ -1222,7 +1372,12 @@ class S { /// `Export` String get export { - return Intl.message('Export', name: 'export', desc: '', args: []); + return Intl.message( + 'Export', + name: 'export', + desc: '', + args: [], + ); } /// `Import / Export` @@ -1297,12 +1452,22 @@ class S { /// `Show` String get show { - return Intl.message('Show', name: 'show', desc: '', args: []); + return Intl.message( + 'Show', + name: 'show', + desc: '', + args: [], + ); } /// `Hide` String get hide { - return Intl.message('Hide', name: 'hide', desc: '', args: []); + return Intl.message( + 'Hide', + name: 'hide', + desc: '', + args: [], + ); } /// `Reset entry to this state` @@ -1397,7 +1562,12 @@ class S { /// `Share` String get share { - return Intl.message('Share', name: 'share', desc: '', args: []); + return Intl.message( + 'Share', + name: 'share', + desc: '', + args: [], + ); } /// `Are you sure you want to delete {name}` @@ -1412,7 +1582,12 @@ class S { /// `Delete` String get delete { - return Intl.message('Delete', name: 'delete', desc: '', args: []); + return Intl.message( + 'Delete', + name: 'delete', + desc: '', + args: [], + ); } /// `Permission error` @@ -1607,7 +1782,12 @@ class S { /// `Add field` String get addField { - return Intl.message('Add field', name: 'addField', desc: '', args: []); + return Intl.message( + 'Add field', + name: 'addField', + desc: '', + args: [], + ); } /// `Add TOTP / 2FA secret` @@ -1622,7 +1802,12 @@ class S { /// `Exported` String get exported { - return Intl.message('Exported', name: 'exported', desc: '', args: []); + return Intl.message( + 'Exported', + name: 'exported', + desc: '', + args: [], + ); } /// `Visit the forum` @@ -1697,7 +1882,12 @@ class S { /// `Hexadecimal` String get hexadecimal { - return Intl.message('Hexadecimal', name: 'hexadecimal', desc: '', args: []); + return Intl.message( + 'Hexadecimal', + name: 'hexadecimal', + desc: '', + args: [], + ); } /// `Share/view logs` @@ -1712,7 +1902,12 @@ class S { /// `Autofilling` String get autofilling { - return Intl.message('Autofilling', name: 'autofilling', desc: '', args: []); + return Intl.message( + 'Autofilling', + name: 'autofilling', + desc: '', + args: [], + ); } /// `attach a file` @@ -1767,7 +1962,12 @@ class S { /// `Got it` String get gotIt { - return Intl.message('Got it', name: 'gotIt', desc: '', args: []); + return Intl.message( + 'Got it', + name: 'gotIt', + desc: '', + args: [], + ); } /// `Your password entries` @@ -1842,7 +2042,12 @@ class S { /// `Copy Secret` String get copySecret { - return Intl.message('Copy Secret', name: 'copySecret', desc: '', args: []); + return Intl.message( + 'Copy Secret', + name: 'copySecret', + desc: '', + args: [], + ); } /// `New URL (include https://)` @@ -1907,32 +2112,62 @@ class S { /// `Search` String get search { - return Intl.message('Search', name: 'search', desc: '', args: []); + return Intl.message( + 'Search', + name: 'search', + desc: '', + args: [], + ); } /// `name` String get name { - return Intl.message('name', name: 'name', desc: '', args: []); + return Intl.message( + 'name', + name: 'name', + desc: '', + args: [], + ); } /// `title` String get title { - return Intl.message('title', name: 'title', desc: '', args: []); + return Intl.message( + 'title', + name: 'title', + desc: '', + args: [], + ); } /// `user` String get user { - return Intl.message('user', name: 'user', desc: '', args: []); + return Intl.message( + 'user', + name: 'user', + desc: '', + args: [], + ); } /// `User/Email` String get userEmail { - return Intl.message('User/Email', name: 'userEmail', desc: '', args: []); + return Intl.message( + 'User/Email', + name: 'userEmail', + desc: '', + args: [], + ); } /// `group` String get group { - return Intl.message('group', name: 'group', desc: '', args: []); + return Intl.message( + 'group', + name: 'group', + desc: '', + args: [], + ); } /// `Confirm changes` @@ -1957,22 +2192,42 @@ class S { /// `Help` String get help { - return Intl.message('Help', name: 'help', desc: '', args: []); + return Intl.message( + 'Help', + name: 'help', + desc: '', + args: [], + ); } /// `Settings` String get settings { - return Intl.message('Settings', name: 'settings', desc: '', args: []); + return Intl.message( + 'Settings', + name: 'settings', + desc: '', + args: [], + ); } /// `Bin` String get menuTrash { - return Intl.message('Bin', name: 'menuTrash', desc: '', args: []); + return Intl.message( + 'Bin', + name: 'menuTrash', + desc: '', + args: [], + ); } /// `General` String get menuSetGeneral { - return Intl.message('General', name: 'menuSetGeneral', desc: '', args: []); + return Intl.message( + 'General', + name: 'menuSetGeneral', + desc: '', + args: [], + ); } /// `Empty Bin` @@ -2007,42 +2262,82 @@ class S { /// `Yes` String get alertYes { - return Intl.message('Yes', name: 'alertYes', desc: '', args: []); + return Intl.message( + 'Yes', + name: 'alertYes', + desc: '', + args: [], + ); } /// `No` String get alertNo { - return Intl.message('No', name: 'alertNo', desc: '', args: []); + return Intl.message( + 'No', + name: 'alertNo', + desc: '', + args: [], + ); } /// `OK` String get alertOk { - return Intl.message('OK', name: 'alertOk', desc: '', args: []); + return Intl.message( + 'OK', + name: 'alertOk', + desc: '', + args: [], + ); } /// `Cancel` String get alertCancel { - return Intl.message('Cancel', name: 'alertCancel', desc: '', args: []); + return Intl.message( + 'Cancel', + name: 'alertCancel', + desc: '', + args: [], + ); } /// `Copy` String get alertCopy { - return Intl.message('Copy', name: 'alertCopy', desc: '', args: []); + return Intl.message( + 'Copy', + name: 'alertCopy', + desc: '', + args: [], + ); } /// `Close` String get alertClose { - return Intl.message('Close', name: 'alertClose', desc: '', args: []); + return Intl.message( + 'Close', + name: 'alertClose', + desc: '', + args: [], + ); } /// `Generate` String get footerTitleGen { - return Intl.message('Generate', name: 'footerTitleGen', desc: '', args: []); + return Intl.message( + 'Generate', + name: 'footerTitleGen', + desc: '', + args: [], + ); } /// `Length` String get genLen { - return Intl.message('Length', name: 'genLen', desc: '', args: []); + return Intl.message( + 'Length', + name: 'genLen', + desc: '', + args: [], + ); } /// `Pronounceable` @@ -2107,7 +2402,12 @@ class S { /// `Rename` String get tagRename { - return Intl.message('Rename', name: 'tagRename', desc: '', args: []); + return Intl.message( + 'Rename', + name: 'tagRename', + desc: '', + args: [], + ); } /// `Generator Presets` @@ -2162,7 +2462,12 @@ class S { /// `Digits` String get genPsDigits { - return Intl.message('Digits', name: 'genPsDigits', desc: '', args: []); + return Intl.message( + 'Digits', + name: 'genPsDigits', + desc: '', + args: [], + ); } /// `Special symbols` @@ -2177,7 +2482,12 @@ class S { /// `Brackets` String get genPsBrackets { - return Intl.message('Brackets', name: 'genPsBrackets', desc: '', args: []); + return Intl.message( + 'Brackets', + name: 'genPsBrackets', + desc: '', + args: [], + ); } /// `High ASCII characters` @@ -2202,22 +2512,42 @@ class S { /// `Match case` String get searchCase { - return Intl.message('Match case', name: 'searchCase', desc: '', args: []); + return Intl.message( + 'Match case', + name: 'searchCase', + desc: '', + args: [], + ); } /// `RegEx` String get searchRegex { - return Intl.message('RegEx', name: 'searchRegex', desc: '', args: []); + return Intl.message( + 'RegEx', + name: 'searchRegex', + desc: '', + args: [], + ); } /// `URL` String get openUrl { - return Intl.message('URL', name: 'openUrl', desc: '', args: []); + return Intl.message( + 'URL', + name: 'openUrl', + desc: '', + args: [], + ); } /// `Error` String get openError { - return Intl.message('Error', name: 'openError', desc: '', args: []); + return Intl.message( + 'Error', + name: 'openError', + desc: '', + args: [], + ); } /// `Revert to state` @@ -2242,12 +2572,22 @@ class S { /// `Change icon` String get detSetIcon { - return Intl.message('Change icon', name: 'detSetIcon', desc: '', args: []); + return Intl.message( + 'Change icon', + name: 'detSetIcon', + desc: '', + args: [], + ); } /// `Delete` String get detDelEntry { - return Intl.message('Delete', name: 'detDelEntry', desc: '', args: []); + return Intl.message( + 'Delete', + name: 'detDelEntry', + desc: '', + args: [], + ); } /// `Delete permanently` @@ -2262,27 +2602,52 @@ class S { /// `Group` String get detGroup { - return Intl.message('Group', name: 'detGroup', desc: '', args: []); + return Intl.message( + 'Group', + name: 'detGroup', + desc: '', + args: [], + ); } /// `Created` String get detCreated { - return Intl.message('Created', name: 'detCreated', desc: '', args: []); + return Intl.message( + 'Created', + name: 'detCreated', + desc: '', + args: [], + ); } /// `Updated` String get detUpdated { - return Intl.message('Updated', name: 'detUpdated', desc: '', args: []); + return Intl.message( + 'Updated', + name: 'detUpdated', + desc: '', + args: [], + ); } /// `New Field` String get detNetField { - return Intl.message('New Field', name: 'detNetField', desc: '', args: []); + return Intl.message( + 'New Field', + name: 'detNetField', + desc: '', + args: [], + ); } /// `Copied` String get detFieldCopied { - return Intl.message('Copied', name: 'detFieldCopied', desc: '', args: []); + return Intl.message( + 'Copied', + name: 'detFieldCopied', + desc: '', + args: [], + ); } /// `"One Time Passwords" (OTP) are a feature some websites offer to improve security. It is a type of Two/Multi Factor Authentication (2FA/MFA).` @@ -2357,17 +2722,32 @@ class S { /// `Theme` String get setGenTheme { - return Intl.message('Theme', name: 'setGenTheme', desc: '', args: []); + return Intl.message( + 'Theme', + name: 'setGenTheme', + desc: '', + args: [], + ); } /// `Light` String get setGenThemeLt { - return Intl.message('Light', name: 'setGenThemeLt', desc: '', args: []); + return Intl.message( + 'Light', + name: 'setGenThemeLt', + desc: '', + args: [], + ); } /// `Dark` String get setGenThemeDk { - return Intl.message('Dark', name: 'setGenThemeDk', desc: '', args: []); + return Intl.message( + 'Dark', + name: 'setGenThemeDk', + desc: '', + args: [], + ); } /// `Default` @@ -2402,17 +2782,32 @@ class S { /// `Sign in` String get signin { - return Intl.message('Sign in', name: 'signin', desc: '', args: []); + return Intl.message( + 'Sign in', + name: 'signin', + desc: '', + args: [], + ); } /// `Sign out` String get signout { - return Intl.message('Sign out', name: 'signout', desc: '', args: []); + return Intl.message( + 'Sign out', + name: 'signout', + desc: '', + args: [], + ); } /// `New User` String get newUser { - return Intl.message('New User', name: 'newUser', desc: '', args: []); + return Intl.message( + 'New User', + name: 'newUser', + desc: '', + args: [], + ); } /// `Existing User` @@ -2427,7 +2822,12 @@ class S { /// `Register` String get register { - return Intl.message('Register', name: 'register', desc: '', args: []); + return Intl.message( + 'Register', + name: 'register', + desc: '', + args: [], + ); } /// `Create my Vault` @@ -2562,7 +2962,12 @@ class S { /// `Import` String get import { - return Intl.message('Import', name: 'import', desc: '', args: []); + return Intl.message( + 'Import', + name: 'import', + desc: '', + args: [], + ); } /// `We'll add specialised support for some other password manager storage formats in future but won't ever be able to directly support every one of the hundreds available.` @@ -2587,17 +2992,32 @@ class S { /// `Domain` String get domain { - return Intl.message('Domain', name: 'domain', desc: '', args: []); + return Intl.message( + 'Domain', + name: 'domain', + desc: '', + args: [], + ); } /// `Exact` String get exact { - return Intl.message('Exact', name: 'exact', desc: '', args: []); + return Intl.message( + 'Exact', + name: 'exact', + desc: '', + args: [], + ); } /// `Hostname` String get hostname { - return Intl.message('Hostname', name: 'hostname', desc: '', args: []); + return Intl.message( + 'Hostname', + name: 'hostname', + desc: '', + args: [], + ); } /// `Minimum accuracy for a URL match` @@ -2612,22 +3032,42 @@ class S { /// `Text` String get text { - return Intl.message('Text', name: 'text', desc: '', args: []); + return Intl.message( + 'Text', + name: 'text', + desc: '', + args: [], + ); } /// `Field name` String get fieldName { - return Intl.message('Field name', name: 'fieldName', desc: '', args: []); + return Intl.message( + 'Field name', + name: 'fieldName', + desc: '', + args: [], + ); } /// `Enabled` String get enabled { - return Intl.message('Enabled', name: 'enabled', desc: '', args: []); + return Intl.message( + 'Enabled', + name: 'enabled', + desc: '', + args: [], + ); } /// `Disabled` String get disabled { - return Intl.message('Disabled', name: 'disabled', desc: '', args: []); + return Intl.message( + 'Disabled', + name: 'disabled', + desc: '', + args: [], + ); } /// `Protect field` @@ -2652,7 +3092,12 @@ class S { /// `Apply` String get apply { - return Intl.message('Apply', name: 'apply', desc: '', args: []); + return Intl.message( + 'Apply', + name: 'apply', + desc: '', + args: [], + ); } /// `Saving...` @@ -2687,7 +3132,12 @@ class S { /// `Done` String get done { - return Intl.message('Done', name: 'done', desc: '', args: []); + return Intl.message( + 'Done', + name: 'done', + desc: '', + args: [], + ); } /// `Offer to save passwords` @@ -3585,7 +4035,9 @@ class AppLocalizationDelegate extends LocalizationsDelegate { const AppLocalizationDelegate(); List get supportedLocales { - return const [Locale.fromSubtags(languageCode: 'en')]; + return const [ + Locale.fromSubtags(languageCode: 'en'), + ]; } @override diff --git a/lib/local_vault_repository.dart b/lib/local_vault_repository.dart index 70b725e..88534c1 100644 --- a/lib/local_vault_repository.dart +++ b/lib/local_vault_repository.dart @@ -33,7 +33,7 @@ class LocalVaultRepository { return KdbxFormat(KeeVaultKdfCache(), FlutterArgon2()); } - getStorageDirectory() async { + Future getStorageDirectory() async { if (KeeVaultPlatform.isIOS) { final path = await _autoFillMethodChannel.invokeMethod('getAppGroupDirectory'); return Directory(path); @@ -257,7 +257,7 @@ class LocalVaultRepository { return false; } - remove(User user) async { + Future remove(User user) async { final directory = await getStorageDirectory(); final file = File('${directory.path}/${user.idB64url}/current.kdbx'); final stagedFile = File('${directory.path}/${user.idB64url}/staged.kdbx'); diff --git a/lib/logging/log_console.dart b/lib/logging/log_console.dart index 905fceb..9f12ba9 100644 --- a/lib/logging/log_console.dart +++ b/lib/logging/log_console.dart @@ -424,7 +424,7 @@ class LogConsoleState extends State { } //TODO:f: deduplicate - getStorageDirectory() async { + Future getStorageDirectory() async { const autoFillMethodChannel = MethodChannel('com.keevault.keevault/autofill'); if (KeeVaultPlatform.isIOS) { final path = await autoFillMethodChannel.invokeMethod('getAppGroupDirectory'); @@ -516,7 +516,7 @@ class LogConsoleState extends State { ); } - colorForLevel(Level level) { + Color? colorForLevel(Level level) { final dark = Theme.of(context).brightness == Brightness.dark; switch (level) { case Level.fatal: diff --git a/lib/model/entry.dart b/lib/model/entry.dart index f62b581..5dc8b5c 100644 --- a/lib/model/entry.dart +++ b/lib/model/entry.dart @@ -31,8 +31,8 @@ class EntryListItemViewModel { final EntryColor? color; //TODO:f Look for KeeFormField text items if no username exists - get usernameCustom => entry.getString(KdbxKeyCommon.USER_NAME)?.getText().trim() ?? ''; - get username => usernameCustom; + String get usernameCustom => entry.getString(KdbxKeyCommon.USER_NAME)?.getText().trim() ?? ''; + dynamic get username => usernameCustom; static List _createGroupNames(KdbxGroup group) => group.breadcrumbs.map((e) => e.name.get()).whereNotNull().toList(); @@ -443,7 +443,7 @@ class EditEntryViewModel extends EntryViewModel { static List _createGroupNames(KdbxGroup group) => group.breadcrumbs.map((g) => g.name.get()).whereNotNull().toList(); - commit(KdbxEntry entry) { + void commit(KdbxEntry entry) { final Map newFields = {}; final List jsonFields = []; diff --git a/lib/model/field.dart b/lib/model/field.dart index f91b40a..bcde6ff 100644 --- a/lib/model/field.dart +++ b/lib/model/field.dart @@ -181,7 +181,7 @@ class FieldViewModel { //TODO:f If necessary, call this as part of creating a new browserModel when user first enables browser integration on the field (or creates a new field full stop if we will always default to enabling browser integration) // ignore: unused_element - _getBrowserFieldDisplayName() { + String? _getBrowserFieldDisplayName() { if (key == KdbxKeyCommon.PASSWORD) { return 'KeePass password'; } else if (key == KdbxKeyCommon.USER_NAME) { diff --git a/lib/payment_service.dart b/lib/payment_service.dart index d37c2dd..48d5efc 100644 --- a/lib/payment_service.dart +++ b/lib/payment_service.dart @@ -46,22 +46,22 @@ class PaymentService { } /// view can subscribe to _errorListeners using this method - addToErrorListeners(Function(String) callback) { + void addToErrorListeners(Function(String) callback) { _errorListeners.add(callback); } /// view can cancel to _errorListeners using this method - removeFromErrorListeners(Function(String) callback) { + void removeFromErrorListeners(Function(String) callback) { _errorListeners.remove(callback); } /// view can subscribe to _purchasedListeners using this method - addToPurchasedListeners(Function(PurchasedItem) callback) { + void addToPurchasedListeners(Function(PurchasedItem) callback) { _purchasedListeners.add(callback); } /// view can cancel to _purchasedListeners using this method - removeFromPurchasedListeners(Function(PurchasedItem) callback) { + void removeFromPurchasedListeners(Function(PurchasedItem) callback) { _purchasedListeners.remove(callback); } diff --git a/lib/vault_backend/remote_service.dart b/lib/vault_backend/remote_service.dart index 5b90652..9952949 100644 --- a/lib/vault_backend/remote_service.dart +++ b/lib/vault_backend/remote_service.dart @@ -44,7 +44,7 @@ class RemoteService { RemoteService._(this._name, this._dio); - factory RemoteService(stage, name) { + factory RemoteService(Stage? stage, String name) { var endpoint = endpoints[stage]![name]!; var options = BaseOptions( baseUrl: endpoint, diff --git a/lib/widgets/account_create.dart b/lib/widgets/account_create.dart index 74bc502..0355c8f 100644 --- a/lib/widgets/account_create.dart +++ b/lib/widgets/account_create.dart @@ -156,7 +156,7 @@ class _AccountCreateWidgetState extends State { blockingOverlay.hide(); } - initialiseIAP() async { + Future initialiseIAP() async { final accountCubit = BlocProvider.of(context); final vaultCubit = BlocProvider.of(context); final blockingOverlay = BlockingOverlay.of(context); @@ -690,7 +690,7 @@ class _AccountCreateWidgetState extends State { return false; } - subscribeUser(User user) async { + Future subscribeUser(User user) async { final accountCubit = BlocProvider.of(context); final vaultCubit = BlocProvider.of(context); final str = S.of(context); @@ -733,7 +733,7 @@ class _AccountCreateWidgetState extends State { } } - registerAccount(String email, String password, bool marketingEmails) async { + Future registerAccount(String email, String password, bool marketingEmails) async { final blockingOverlay = BlockingOverlay.of(context); blockingOverlay.show(null, Duration(seconds: 1)); final accountCubit = BlocProvider.of(context); @@ -758,7 +758,7 @@ class _AccountCreateWidgetState extends State { await subscribeUser(user); } - resubscriptionNeededReason(AccountAuthenticated state) { + String resubscriptionNeededReason(AccountAuthenticated state) { if (state is AccountSubscribeError) { return 'Could not subscribe you this time. Please try again. Reason: ${(state).message}'; } @@ -771,7 +771,7 @@ class _AccountCreateWidgetState extends State { return 'Your account is enabled but you have no active subscription. That could happen for a variety of reasons but is easy to fix - just hit the button below and follow any steps your Subscription Provider presents.'; } - isRenewalMode(AccountAuthenticated state) { + bool isRenewalMode(AccountAuthenticated state) { if (state is AccountSubscribeError) { return false; } diff --git a/lib/widgets/account_expired.dart b/lib/widgets/account_expired.dart index 22eb496..862df80 100644 --- a/lib/widgets/account_expired.dart +++ b/lib/widgets/account_expired.dart @@ -127,7 +127,7 @@ class _AccountExpiredWidgetState extends State { final accountCubit = BlocProvider.of(context); final vaultCubit = BlocProvider.of(context); await DialogUtils.openUrl( - EnvironmentConfig.webUrl + '/#pfEmail=$userEmail,dest=manageAccount', + '${EnvironmentConfig.webUrl}/#pfEmail=$userEmail,dest=manageAccount', ); vaultCubit.signout(); await accountCubit.signout(); @@ -183,7 +183,7 @@ class _AccountExpiredWidgetState extends State { ); } - expiryMessageForSubscriptionSource(AccountSubscriptionSource subscriptionSource, S str) { + String expiryMessageForSubscriptionSource(AccountSubscriptionSource subscriptionSource, S str) { if (subscriptionSource == AccountSubscriptionSource.chargeBee) { return str.subscriptionExpiredDetails; } diff --git a/lib/widgets/autofill_save.dart b/lib/widgets/autofill_save.dart index 722a05e..2c596e9 100644 --- a/lib/widgets/autofill_save.dart +++ b/lib/widgets/autofill_save.dart @@ -73,7 +73,7 @@ class _AutofillSaveWidgetState extends State with TraceableC BlocProvider.of(context).startEditing(newEntry!, startDirty: false); } - onEndEditing(bool keepChanges, VaultCubit vaultCubit, List tags) async { + Future onEndEditing(bool keepChanges, VaultCubit vaultCubit, List tags) async { final entryCubit = BlocProvider.of(context); final autofillCubit = BlocProvider.of(context); if (keepChanges && (entryCubit.state as EntryLoaded).entry.isDirty) { diff --git a/lib/widgets/bottom.dart b/lib/widgets/bottom.dart index 8cbbec7..ce924a3 100644 --- a/lib/widgets/bottom.dart +++ b/lib/widgets/bottom.dart @@ -421,6 +421,6 @@ void toggleBottomDrawerVisibility(BuildContext context) { ); } -_removeKeyboardFocus(BuildContext context) { +void _removeKeyboardFocus(BuildContext context) { FocusScope.of(context).unfocus(); } diff --git a/lib/widgets/change_email_prefs.dart b/lib/widgets/change_email_prefs.dart index fa12b1e..5e58b58 100644 --- a/lib/widgets/change_email_prefs.dart +++ b/lib/widgets/change_email_prefs.dart @@ -43,7 +43,7 @@ class _ChangeEmailPrefsWidgetState extends State { label: Icon(Icons.open_in_new), onPressed: () async { await DialogUtils.openUrl( - EnvironmentConfig.webUrl + '/#pfEmail=${accountState.user.email},dest=manageAccount', + '${EnvironmentConfig.webUrl}/#pfEmail=${accountState.user.email},dest=manageAccount', ); }, ), diff --git a/lib/widgets/change_subscription.dart b/lib/widgets/change_subscription.dart index 1e18089..2ae9544 100644 --- a/lib/widgets/change_subscription.dart +++ b/lib/widgets/change_subscription.dart @@ -54,7 +54,7 @@ class _ChangeSubscriptionWidgetState extends State { label: Icon(Icons.open_in_new), onPressed: () async { await DialogUtils.openUrl( - EnvironmentConfig.webUrl + '/#pfEmail=${accountState.user.email},dest=manageAccount', + '${EnvironmentConfig.webUrl}/#pfEmail=${accountState.user.email},dest=manageAccount', ); }, ), diff --git a/lib/widgets/entry_field.dart b/lib/widgets/entry_field.dart index c8194f2..c159947 100644 --- a/lib/widgets/entry_field.dart +++ b/lib/widgets/entry_field.dart @@ -280,7 +280,7 @@ class _EntryTextFieldState extends _EntryFieldState implements FieldDelegate { } } - _onUsernameChanged(value) { + void _onUsernameChanged(String? value) { _updateAutocompleteSuggestions(context); final StringValue? newValue = value == null ? null diff --git a/lib/widgets/import_credentials.dart b/lib/widgets/import_credentials.dart index d9dd029..cef8053 100644 --- a/lib/widgets/import_credentials.dart +++ b/lib/widgets/import_credentials.dart @@ -81,11 +81,11 @@ class ImportCredentialsWidget extends StatelessWidget { ); } - _skipImport(BuildContext context, LocalVaultFile destination) async { + Future _skipImport(BuildContext context, LocalVaultFile destination) async { await BlocProvider.of(context).skipLocalFreeKdbxImport(destination); } - _cancelImport(BuildContext context, LocalVaultFile destination) async { + Future _cancelImport(BuildContext context, LocalVaultFile destination) async { await BlocProvider.of(context).emitVaultLoaded(destination, null, safe: false); } } diff --git a/lib/widgets/import_export.dart b/lib/widgets/import_export.dart index b9bc19e..e4cf654 100644 --- a/lib/widgets/import_export.dart +++ b/lib/widgets/import_export.dart @@ -212,7 +212,7 @@ class _ImportExportWidgetState extends State { ); } - _import(BuildContext context, VaultLoaded vaultState) async { + Future _import(BuildContext context, VaultLoaded vaultState) async { final str = S.of(context); final vaultCubit = BlocProvider.of(context); @@ -279,7 +279,7 @@ class _ImportExportWidgetState extends State { } } - _export(BuildContext context, VaultLoaded state) async { + Future _export(BuildContext context, VaultLoaded state) async { final str = S.of(context); final sm = ScaffoldMessenger.of(context); @@ -336,7 +336,7 @@ class _ImportExportWidgetState extends State { } } - _exportFreeKdbx(BuildContext context) async { + Future _exportFreeKdbx(BuildContext context) async { final str = S.of(context); final sm = ScaffoldMessenger.of(context); final vaultCubit = BlocProvider.of(context); @@ -386,7 +386,7 @@ class _ImportExportWidgetState extends State { } } - _deleteFreeKdbx(BuildContext context) async { + Future _deleteFreeKdbx(BuildContext context) async { final str = S.of(context); final sm = ScaffoldMessenger.of(context); final vaultCubit = BlocProvider.of(context); diff --git a/lib/widgets/kee_vault_app.dart b/lib/widgets/kee_vault_app.dart index a325bc8..5ce252c 100644 --- a/lib/widgets/kee_vault_app.dart +++ b/lib/widgets/kee_vault_app.dart @@ -60,7 +60,7 @@ class KeeVaultAppState extends State with WidgetsBindingObserver, T late UserRepository userRepo; late AccountCubit accountCubit; - onTokensChange(User user) { + void onTokensChange(User user) { // A lot of background operations can result in updated information about the // user's authentication status or subscription status being changed (via requests // like refresh which end up changing the authentication tokens and features @@ -128,7 +128,7 @@ class KeeVaultAppState extends State with WidgetsBindingObserver, T } final mode = intent?.extra?['autofill_mode']; if (mode?.startsWith('/autofill') ?? false) { - BlocProvider.of(navContext).refresh(); + unawaited(BlocProvider.of(navContext).refresh()); } }, onError: (err) { diff --git a/lib/widgets/reset_account_prompt_dialog.dart b/lib/widgets/reset_account_prompt_dialog.dart index c899bb4..139ecab 100644 --- a/lib/widgets/reset_account_prompt_dialog.dart +++ b/lib/widgets/reset_account_prompt_dialog.dart @@ -102,7 +102,7 @@ class _ResetAccountPromptDialogState extends State wit label: Icon(Icons.open_in_new), onPressed: () async { final navigator = Navigator.of(context); - await DialogUtils.openUrl(EnvironmentConfig.webUrl + '/#dest=resetPassword'); + await DialogUtils.openUrl('${EnvironmentConfig.webUrl}/#dest=resetPassword'); navigator.pop(true); }, ), diff --git a/lib/widgets/settings.dart b/lib/widgets/settings.dart index 3e27eee..5e491dc 100644 --- a/lib/widgets/settings.dart +++ b/lib/widgets/settings.dart @@ -98,7 +98,7 @@ class _SettingsWidgetState extends State with TraceableClientMix label: Icon(Icons.open_in_new), onPressed: () async { await DialogUtils.openUrl( - EnvironmentConfig.webUrl + '/#pfEmail=$userEmail,dest=manageAccount', + '${EnvironmentConfig.webUrl}/#pfEmail=$userEmail,dest=manageAccount', ); }, ), @@ -131,7 +131,7 @@ class _SettingsWidgetState extends State with TraceableClientMix label: Icon(Icons.open_in_new), onPressed: () async { await DialogUtils.openUrl( - EnvironmentConfig.webUrl + '/#pfEmail=$userEmail,dest=signin', + '${EnvironmentConfig.webUrl}/#pfEmail=$userEmail,dest=signin', ); }, ), diff --git a/lib/widgets/vault_imported.dart b/lib/widgets/vault_imported.dart index f15426d..1de1b9f 100644 --- a/lib/widgets/vault_imported.dart +++ b/lib/widgets/vault_imported.dart @@ -10,7 +10,7 @@ import '../generated/l10n.dart'; class VaultImportedWidget extends StatelessWidget { const VaultImportedWidget({super.key}); - _loadVault(LocalVaultFile vault, BuildContext context) async { + Future _loadVault(LocalVaultFile vault, BuildContext context) async { final accountCubit = BlocProvider.of(context); final vaultCubit = BlocProvider.of(context); await vaultCubit.emitVaultLoaded( diff --git a/lib/widgets/vault_password_credentials.dart b/lib/widgets/vault_password_credentials.dart index b5412a0..46b1d7a 100644 --- a/lib/widgets/vault_password_credentials.dart +++ b/lib/widgets/vault_password_credentials.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_settings_screens/flutter_settings_screens.dart'; import 'package:keevault/credentials/quick_unlocker.dart'; @@ -37,10 +39,10 @@ class _VaultPasswordCredentialsWidgetState extends State _detectBiometrics() async { final hide = widget.forceBiometric == null || widget.quStatus == QUStatus.mapAvailable || diff --git a/pubspec.lock b/pubspec.lock index 5dac82a..ea6c559 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -94,10 +94,10 @@ packages: dependency: "direct main" description: name: base32 - sha256: ddad4ebfedf93d4500818ed8e61443b734ffe7cf8a45c668c9b34ef6adde02e2 + sha256: "37548444aaee8bd5e91db442ce69ee3a79d3652ed47c1fa7568aa3bb9af0aea5" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.2.0" biometric_storage: dependency: "direct main" description: @@ -111,10 +111,10 @@ packages: dependency: "direct main" description: name: bloc - sha256: "52c10575f4445c61dd9e0cafcc6356fdd827c4c64dd7945ef3c4105f6b6ac189" + sha256: a2cebb899f91d36eeeaa55c7b20b5915db5a9df1b8fd4a3c9c825e22e474537d url: "https://pub.dev" source: hosted - version: "9.0.0" + version: "9.1.0" boolean_selector: dependency: transitive description: @@ -215,18 +215,26 @@ packages: dependency: "direct main" description: name: dart_jsonwebtoken - sha256: "21ce9f8a8712f741e8d6876a9c82c0f8a257fe928c4378a91d8527b92a3fd413" + sha256: "0de65691c1d736e9459f22f654ddd6fd8368a271d4e41aa07e53e6301eff5075" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.3.1" + dbus: + dependency: transitive + description: + name: dbus + sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + url: "https://pub.dev" + source: hosted + version: "0.7.11" dependency_validator: dependency: "direct dev" description: name: dependency_validator - sha256: "3a243f5b9def5f902887a66fbea7e72e612eee956af6c8c34d382fe6d5484145" + sha256: a5928c0e3773808027bdafeb13fb4be0e4fdd79819773ad3df34d0fcf42636f2 url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.0.3" device_info_plus: dependency: "direct main" description: @@ -247,10 +255,10 @@ packages: dependency: "direct main" description: name: dio - sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9" + sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9 url: "https://pub.dev" source: hosted - version: "5.8.0+1" + version: "5.9.0" dio_web_adapter: dependency: transitive description: @@ -303,10 +311,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: ef9908739bdd9c476353d6adff72e88fd00c625f5b959ae23f7567bd5137db0a + sha256: f2d9f173c2c14635cc0e9b14c143c49ef30b4934e8d1d274d6206fcb0086a06f url: "https://pub.dev" source: hosted - version: "10.2.0" + version: "10.3.3" fixnum: dependency: transitive description: @@ -319,10 +327,10 @@ packages: dependency: "direct main" description: name: flex_color_scheme - sha256: "3344f8f6536c6ce0473b98e9f084ef80ca89024ad3b454f9c32cf840206f4387" + sha256: "6e713c27a2ebe63393a44d4bf9cdd2ac81e112724a4c69905fc41cbf231af11d" url: "https://pub.dev" source: hosted - version: "8.2.0" + version: "8.3.1" flex_seed_scheme: dependency: transitive description: @@ -397,10 +405,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "6.0.0" flutter_localizations: dependency: "direct main" description: flutter @@ -410,10 +418,10 @@ packages: dependency: "direct dev" description: name: flutter_native_splash - sha256: "8321a6d11a8d13977fa780c89de8d257cce3d841eecfb7a4cadffcc4f12d82dc" + sha256: "4fb9f4113350d3a80841ce05ebf1976a36de622af7d19aca0ca9a9911c7ff002" url: "https://pub.dev" source: hosted - version: "2.4.6" + version: "2.4.7" flutter_persistent_queue: dependency: "direct main" description: @@ -568,34 +576,34 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.1" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: name: lints - sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 + sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "6.0.0" localstorage: dependency: transitive description: @@ -609,10 +617,10 @@ packages: dependency: "direct main" description: name: logger - sha256: "2621da01aabaf223f8f961e751f2c943dbb374dc3559b982f200ccedadaa6999" + sha256: a7967e31b703831a893bbc3c3dd11db08126fe5f369b5c648a36f821979f5be3 url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.6.2" logging: dependency: "direct main" description: @@ -649,10 +657,10 @@ packages: dependency: "direct main" description: name: matomo_tracker - sha256: e5f179b3660193d62b7494abd2179c8dfcab8e66ffa76eeefe3b6f88fb3d8291 + sha256: cdf3bd31f50c89a313181a8f671074870f8ecc129ab4590cf016a2cb0e3c511a url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "6.1.0" meta: dependency: "direct main" description: @@ -681,10 +689,10 @@ packages: dependency: "direct main" description: name: otp - sha256: fcb7f21e30c4cd80a0a982c27a9b75151cc1fe3d8f7ee680673c090171b1ad55 + sha256: "998e73b5cd831a13fa654cf2cbb169d027f74b4928853ff26aa9311ead66ed7c" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.2.0" package_config: dependency: transitive description: @@ -697,18 +705,18 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191" + sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" url: "https://pub.dev" source: hosted - version: "8.3.0" + version: "8.3.1" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c" + sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" path: dependency: "direct main" description: @@ -769,10 +777,10 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "2d070d8684b68efb580a5997eb62f675e8a885ef0be6e754fb9ef489c177470f" + sha256: bc917da36261b00137bbc8896bf1482169cd76f866282368948f032c8c1caae1 url: "https://pub.dev" source: hosted - version: "12.0.0+1" + version: "12.0.1" permission_handler_android: dependency: transitive description: @@ -817,10 +825,10 @@ packages: dependency: transitive description: name: petitparser - sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" + sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "7.0.1" platform: dependency: "direct main" description: @@ -940,18 +948,18 @@ packages: dependency: "direct main" description: name: share_plus - sha256: b2961506569e28948d75ec346c28775bb111986bb69dc6a20754a457e3d97fa0 + sha256: d7dc0630a923883c6328ca31b89aa682bacbf2f8304162d29f7c6aaff03a27a1 url: "https://pub.dev" source: hosted - version: "11.0.0" + version: "11.1.0" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - sha256: "1032d392bc5d2095a77447a805aa3f804d2ae6a4d5eef5e6ebb3bd94c1bc19ef" + sha256: "88023e53a13429bd65d8e85e11a9b484f49d4c190abbd96c7932b74d6927cc9a" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "6.1.0" shared_preferences: dependency: "direct main" description: @@ -1021,14 +1029,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.1" - sprintf: - dependency: transitive - description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.dev" - source: hosted - version: "7.0.0" srp: dependency: "direct main" description: @@ -1082,18 +1082,18 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" timezone: dependency: transitive description: name: timezone - sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d" + sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1 url: "https://pub.dev" source: hosted - version: "0.9.4" + version: "0.10.1" tuple: dependency: "direct main" description: @@ -1130,10 +1130,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.2" url_launcher_android: dependency: transitive description: @@ -1194,18 +1194,18 @@ packages: dependency: "direct main" description: name: uuid - sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + sha256: a11b666489b1954e01d992f3d601b1804a33937b5a8fe677bd26b8a9f96f96e8 url: "https://pub.dev" source: hosted - version: "4.5.1" + version: "4.5.2" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -1258,10 +1258,10 @@ packages: dependency: transitive description: name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" url: "https://pub.dev" source: hosted - version: "6.5.0" + version: "6.6.1" yaml: dependency: transitive description: @@ -1280,4 +1280,4 @@ packages: version: "1.0.0" sdks: dart: ">=3.8.0 <4.0.0" - flutter: ">=3.29.0" + flutter: ">=3.35.0" diff --git a/pubspec.yaml b/pubspec.yaml index 5939ec1..e6d6568 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,13 +18,13 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 2.5.0+58 environment: - sdk: '>=3.8.0 <4.0.0' + sdk: '>=3.9.0 <4.0.0' dependencies: flutter: sdk: flutter - logger: ^2.5.0 - logging: ^1.2.0 + logger: ^2.6.2 + logging: ^1.3.0 kdbx: git: url: https://github.com/kee-org/kdbx.dart.git @@ -35,8 +35,8 @@ dependencies: url: https://github.com/kee-org/biometric_storage.git ref: keevault - package_info_plus: ^8.0.0 - shared_preferences: ^2.5.1 # at least 2.3.4 for security patch + package_info_plus: ^8.3.1 + shared_preferences: ^2.5.3 # at least 2.3.4 for security patch flutter_settings_screens: git: url: https://github.com/Juggler98/flutter_settings_screens.git @@ -49,11 +49,11 @@ dependencies: # git: # url: https://github.com/kee-org/flutter_autofill_service.git # ref: master - bloc: ^9.0.0 - flutter_bloc: ^9.0.0 + bloc: ^9.1.0 + flutter_bloc: ^9.1.1 fluro: ^2.0.5 - dio: ^5.8.0+1 - dart_jsonwebtoken: ^3.2.0 + dio: ^5.9.0 + dart_jsonwebtoken: ^3.3.1 pointycastle: ^4.0.0 srp: git: @@ -62,11 +62,11 @@ dependencies: animations: ^2.0.11 font_awesome_flutter: ^10.8.0 public_suffix: ^3.0.0 - url_launcher: ^6.3.1 - otp: ^3.1.4 + url_launcher: ^6.3.2 + otp: ^3.2.0 tuple: ^2.0.2 - collection: ^1.18.0 - jiffy: ^6.3.2 + collection: ^1.19.1 + jiffy: ^6.4.3 # characters: ^1.2.0 flutter_treeview: git: @@ -80,7 +80,6 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 - app_links: ^6.4.0 flutter_persistent_queue: git: url: https://github.com/kee-org/flutter_persistent_queue @@ -88,29 +87,29 @@ dependencies: flutter_localizations: sdk: flutter - matomo_tracker: ^6.0.0 + matomo_tracker: ^6.1.0 - file_picker: ^10.1.9 + file_picker: ^10.3.3 zxcvbn: ^1.0.0 flutter_rating_bar: ^4.0.1 mime: ^2.0.0 - share_plus: ^11.0.0 + share_plus: ^11.1.0 path: ^1.9.0 #flutter sdk always lags behind so upgrade this only when needed - permission_handler: ^12.0.0+1 + permission_handler: ^12.0.1 flutter_file_dialog: ^3.0.2 - base32: ^2.1.3 + base32: ^2.2.0 flutter_speed_dial: ^7.0.0 receive_intent: #^0.2.7 git: url: https://github.com/daadu/receive_intent ref: master - platform: ^3.1.5 + platform: ^3.1.6 email_validator: ^3.0.0 - convert: ^3.1.1 + convert: ^3.1.2 meta: ^1.16.0 argon2_ffi_base: ^1.1.1 - uuid: ^4.5.1 - clock: ^1.1.1 + uuid: ^4.5.2 + clock: ^1.1.2 flutter_inapp_purchase: ^5.6.2 # git: # url: https://github.com/kee-org/flutter_inapp_purchase @@ -124,10 +123,10 @@ dependencies: git: url: https://github.com/kee-org/RateMyApp ref: api34 - archive: ^4.0.2 - device_info_plus: ^11.2.2 + archive: ^4.0.7 + device_info_plus: ^11.5.0 barcode_scan2: ^4.5.1 - flex_color_scheme: ^8.2.0 + flex_color_scheme: ^8.3.1 # barcode_scan2: # git: # url: https://github.com/kee-org/barcode_scan2 @@ -136,10 +135,10 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_launcher_icons: "^0.14.3" - flutter_lints: ^5.0.0 - dependency_validator: ^5.0.2 - flutter_native_splash: ^2.4.4 + flutter_launcher_icons: "^0.14.4" + flutter_lints: ^6.0.0 + dependency_validator: ^5.0.3 + flutter_native_splash: ^2.4.7 #patrol: ^2.2.3 dependency_overrides: From ed408906cfafbca33407cbd267ed462777ebd25c Mon Sep 17 00:00:00 2001 From: Chris Tomlinson Date: Fri, 7 Nov 2025 18:14:26 +0000 Subject: [PATCH 02/10] Android 36, Gradle and IAP library update --- android/app/build.gradle | 7 +- android/app/proguard-rules.pro | 8 +- android/build.gradle | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/settings.gradle | 4 +- ios/Podfile.lock | 56 +++-- lib/cubit/account_cubit.dart | 33 +-- lib/extension_methods.dart | 7 +- lib/payment_service.dart | 232 ++++++++++-------- lib/user_repository.dart | 2 +- lib/widgets/account_create.dart | 42 ++-- pubspec.lock | 23 +- pubspec.yaml | 7 +- 13 files changed, 231 insertions(+), 194 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index bfd2a9a..e539247 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,6 +1,6 @@ plugins { id "com.android.application" - id 'org.jetbrains.kotlin.android' version '2.1.20' + id 'org.jetbrains.kotlin.android' version '2.3.0' id "dev.flutter.flutter-gradle-plugin" } @@ -82,7 +82,7 @@ kotlin { } android { - compileSdk 35 + compileSdk 36 compileOptions { sourceCompatibility = 17 @@ -123,6 +123,9 @@ android { ndk.debugSymbolLevel = symbolLevel testInstrumentationRunner "pl.leancode.patrol.PatrolJUnitRunner" testInstrumentationRunnerArguments clearPackageData: "true" + + // Required for flutter_inapp_purchase: Select Google Play platform + missingDimensionStrategy 'platform', 'play' } testOptions { diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro index de4d436..99794d0 100644 --- a/android/app/proguard-rules.pro +++ b/android/app/proguard-rules.pro @@ -6,4 +6,10 @@ -dontwarn dalvik.system.VMStack -dontwarn java.lang.** -dontwarn javax.naming.** --dontwarn sun.reflect.Reflection \ No newline at end of file +-dontwarn sun.reflect.Reflection + +-dontwarn ch.qos.logback.classic.Level +-dontwarn ch.qos.logback.classic.Logger +-dontwarn ch.qos.logback.classic.LoggerContext +-dontwarn ch.qos.logback.classic.spi.ILoggingEvent +-dontwarn ch.qos.logback.classic.spi.LoggingEvent \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index d174ff3..a66b74e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -9,7 +9,7 @@ rootProject.buildDir = '../build' subprojects { afterEvaluate { android { - compileSdkVersion 35 + compileSdkVersion 36 } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index e83807e..102e5f4 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Thu Jun 19 12:25:55 BST 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/android/settings.gradle b/android/settings.gradle index 3e6dbd7..cf76d02 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -19,8 +19,8 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version '8.10.0' apply false - id "org.jetbrains.kotlin.android" version "2.1.20" apply false + id "com.android.application" version '8.13.2' apply false + id "org.jetbrains.kotlin.android" version "2.3.0" apply false } include ":app" diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 986a3ef..5e2f95c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -4,40 +4,40 @@ PODS: - barcode_scan2 (0.0.1): - Flutter - MTBBarcodeScanner - - SwiftProtobuf + - SwiftProtobuf (~> 1.33) - biometric_storage (0.0.1): - Flutter - device_info_plus (0.0.1): - Flutter - - DKImagePickerController/Core (4.3.4): + - DKImagePickerController/Core (4.3.9): - DKImagePickerController/ImageDataManager - DKImagePickerController/Resource - - DKImagePickerController/ImageDataManager (4.3.4) - - DKImagePickerController/PhotoGallery (4.3.4): + - DKImagePickerController/ImageDataManager (4.3.9) + - DKImagePickerController/PhotoGallery (4.3.9): - DKImagePickerController/Core - DKPhotoGallery - - DKImagePickerController/Resource (4.3.4) - - DKPhotoGallery (0.0.17): - - DKPhotoGallery/Core (= 0.0.17) - - DKPhotoGallery/Model (= 0.0.17) - - DKPhotoGallery/Preview (= 0.0.17) - - DKPhotoGallery/Resource (= 0.0.17) + - DKImagePickerController/Resource (4.3.9) + - DKPhotoGallery (0.0.19): + - DKPhotoGallery/Core (= 0.0.19) + - DKPhotoGallery/Model (= 0.0.19) + - DKPhotoGallery/Preview (= 0.0.19) + - DKPhotoGallery/Resource (= 0.0.19) - SDWebImage - SwiftyGif - - DKPhotoGallery/Core (0.0.17): + - DKPhotoGallery/Core (0.0.19): - DKPhotoGallery/Model - DKPhotoGallery/Preview - SDWebImage - SwiftyGif - - DKPhotoGallery/Model (0.0.17): + - DKPhotoGallery/Model (0.0.19): - SDWebImage - SwiftyGif - - DKPhotoGallery/Preview (0.0.17): + - DKPhotoGallery/Preview (0.0.19): - DKPhotoGallery/Model - DKPhotoGallery/Resource - SDWebImage - SwiftyGif - - DKPhotoGallery/Resource (0.0.17): + - DKPhotoGallery/Resource (0.0.19): - SDWebImage - SwiftyGif - file_picker (0.0.1): @@ -48,9 +48,11 @@ PODS: - Flutter - flutter_inapp_purchase (0.0.1): - Flutter + - openiap (= 1.3.0) - flutter_native_splash (2.4.3): - Flutter - MTBBarcodeScanner (5.0.11) + - openiap (1.3.0) - package_info_plus (0.4.5): - Flutter - path_provider_foundation (0.0.1): @@ -61,9 +63,9 @@ PODS: - rate_my_app (2.2.0): - Flutter - FlutterMacOS - - SDWebImage (5.16.0): - - SDWebImage/Core (= 5.16.0) - - SDWebImage/Core (5.16.0) + - SDWebImage (5.21.5): + - SDWebImage/Core (= 5.21.5) + - SDWebImage/Core (5.21.5) - sensitive_clipboard (0.0.1): - Flutter - share_plus (0.0.1): @@ -71,8 +73,8 @@ PODS: - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS - - SwiftProtobuf (1.22.0) - - SwiftyGif (5.4.4) + - SwiftProtobuf (1.33.3) + - SwiftyGif (5.4.5) - url_launcher_ios (0.0.1): - Flutter @@ -100,6 +102,7 @@ SPEC REPOS: - DKImagePickerController - DKPhotoGallery - MTBBarcodeScanner + - openiap - SDWebImage - SwiftProtobuf - SwiftyGif @@ -142,27 +145,28 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: argon2_ffi: 995b9260d81aa17f5d2a8a497f2d2763ba4c45f3 - barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0 + barcode_scan2: b486db2ac59ce5c3ad04b154303935b1117e7e56 biometric_storage: 1400f1382af3a4cc2bf05340e13c3d8de873ceb9 device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342 - DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac - DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 + DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c + DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49 Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 flutter_file_dialog: 4c014a45b105709a27391e266c277d7e588e9299 - flutter_inapp_purchase: 5c6a1ac3f11b11d0c8c0321c0c41c1f05805e4c8 + flutter_inapp_purchase: f71036b9e28b3865d3313ea6e4fd01052623b43a flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb + openiap: b8ae35279df4060abf7dc2fed33e325022eecdf5 package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 rate_my_app: cd3e1c44d12f387482698ffaf6ea9bd669a69b94 - SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6 + SDWebImage: e9c98383c7572d713c1a0d7dd2783b10599b9838 sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989 - SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f + SwiftProtobuf: e1b437c8e31a4c5577b643249a0bb62ed4f02153 + SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe PODFILE CHECKSUM: 0658f7bb36458779f6da1691e33f9d925242f612 diff --git a/lib/cubit/account_cubit.dart b/lib/cubit/account_cubit.dart index 78f1e28..0f86cc4 100644 --- a/lib/cubit/account_cubit.dart +++ b/lib/cubit/account_cubit.dart @@ -1,8 +1,6 @@ import 'package:bloc/bloc.dart'; import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart'; import 'package:kdbx/kdbx.dart'; -import 'package:keevault/config/platform.dart'; -import 'package:keevault/payment_service.dart'; import 'package:keevault/user_repository.dart'; import 'package:keevault/vault_backend/account_verification_status.dart'; import 'package:keevault/vault_backend/exceptions.dart'; @@ -95,26 +93,22 @@ class AccountCubit extends Cubit { } Future subscriptionSuccess( - PurchasedItem purchasedItem, + Purchase purchasedItem, bool isAndroid, Future Function() ensureRemoteCreated, Future Function() finishTransaction, ) async { try { - if (purchasedItem.purchaseToken == null && purchasedItem.transactionReceipt == null) { + if (purchasedItem.purchaseToken == null) { emit( AccountSubscribeError( currentUser, - 'Unexpected error associating your subscription - we found no purchaseToken and no transactionReceipt', + 'Unexpected error associating your subscription - we found no purchaseToken', ), ); return false; } - final success = await _userRepo.associate( - currentUser, - isAndroid ? 2 : 3, - purchasedItem.purchaseToken ?? purchasedItem.transactionReceipt!, - ); + final success = await _userRepo.associate(currentUser, isAndroid ? 2 : 3, purchasedItem.purchaseToken!); if (success) { // Our association request was successful but we rely on the subscription // provider to respond too. Ideally we'd set up a websocket to receive an @@ -301,25 +295,6 @@ class AccountCubit extends Cubit { await _userRepo.setQuickUnlockUser(user); emitAuthenticatedOrExpiredOrUnvalidated(user); - final psi = PaymentService.instance; - await psi.ensureReady(); - if (KeeVaultPlatform.isIOS && - user.subscriptionStatus == AccountSubscriptionStatus.current && - psi.activePurchaseItem != null && - (user.subscriptionId?.startsWith('ap_') ?? false)) { - // It's impossible to know what the expected subscriptionId is because apple don't - // give us the originaltransactionid unless it is a pointless restoration operation - // to a new phone. So all subscription renewals would sit in the queue forever while - // we have no way to know that we have dealt with them. Thus we just accept that - // everything is probably fine as long as the user has a subscription from the App Store. - // Maybe a problem for subscription restarts after an expiry. User's subscription ID - // is going to stay the same even after expiry but then a new one should come along - // with a whole new original transaction id... or not, if there is some reuse during - // grace periods, etc. But surely in all other cases, any valid app store subscription - // id associated with a user that has a non-expired set of authentication tokens is - // going to be just a renewal operation that we can ignore because we handle it server-side. - await psi.finishTransaction(psi.activePurchaseItem!); - } l.d('sign in complete'); return user; } diff --git a/lib/extension_methods.dart b/lib/extension_methods.dart index 8701bb5..18d04fe 100644 --- a/lib/extension_methods.dart +++ b/lib/extension_methods.dart @@ -166,11 +166,14 @@ T? enumFromString(Iterable values, String value) { return values.firstWhereOrNull((type) => type.toString().split('.').last == value); } -extension KVPurchasedItem on PurchasedItem { +extension KVPurchasedItem on Purchase { String get keeVaultSubscriptionId { - final prefix = purchaseStateAndroid != null ? 'gp_' : 'ap_'; + final prefix = this is PurchaseAndroid ? 'gp_' : 'ap_'; if (KeeVaultPlatform.isIOS) { // Apple does not give us the information needed to derive this information + //TODO:f: maybe now available in purchaseToken with StoreKit2 but we already + // have implemented support for the ID to be changed upon receiving the real + // ID from the server so not likely to be worth changing this. return prefix; } return prefix + (purchaseToken ?? ''); diff --git a/lib/payment_service.dart b/lib/payment_service.dart index 48d5efc..3df47d1 100644 --- a/lib/payment_service.dart +++ b/lib/payment_service.dart @@ -13,16 +13,13 @@ class PaymentService { static final PaymentService instance = PaymentService._internal(); - /// To listen the status of connection between app and the billing server - StreamSubscription? _connectionSubscription; - /// To listen the status of the purchase made inside or outside of the app (App Store / Play Store) /// /// If status is not error then app will be notified by this stream - StreamSubscription? _purchaseUpdatedSubscription; + StreamSubscription? _purchaseUpdatedSubscription; /// To listen the errors of the purchase - StreamSubscription? _purchaseErrorSubscription; + StreamSubscription? _purchaseErrorSubscription; /// List of product ids you want to fetch final List _productIds = KeeVaultPlatform.isAndroid @@ -30,18 +27,18 @@ class PaymentService { : ['sub.supporter.yearly']; /// All available products will be store in this list - List? _products; + List? _products; /// view of the app will subscribe to this to get errors of the purchase final ObserverList _errorListeners = ObserverList(); /// view of the app will subscribe to this to get notified when a purchased is completed - final ObserverList _purchasedListeners = ObserverList(); + final ObserverList _purchasedListeners = ObserverList(); - PurchasedItem? _activePurchaseItem; - PurchasedItem? get activePurchaseItem => _activePurchaseItem; + Purchase? _activePurchaseItem; + Purchase? get activePurchaseItem => _activePurchaseItem; - void deferPurchaseItem(PurchasedItem? item) { + void deferPurchaseItem(Purchase? item) { _activePurchaseItem = item; } @@ -56,17 +53,17 @@ class PaymentService { } /// view can subscribe to _purchasedListeners using this method - void addToPurchasedListeners(Function(PurchasedItem) callback) { + void addToPurchasedListeners(Function(Purchase) callback) { _purchasedListeners.add(callback); } /// view can cancel to _purchasedListeners using this method - void removeFromPurchasedListeners(Function(PurchasedItem) callback) { + void removeFromPurchasedListeners(Function(Purchase) callback) { _purchasedListeners.remove(callback); } /// Call this method to notify all the subscribers of completed purchases - void _callPurchasedListeners(PurchasedItem item) { + void _callPurchasedListeners(Purchase item) { for (var callback in _purchasedListeners) { callback(item); } @@ -85,14 +82,14 @@ class PaymentService { /// with billing server and get all the necessary data Future initConnection() async { readyFuture = Future(() async { - await FlutterInappPurchase.instance.initialize(); - - _connectionSubscription = FlutterInappPurchase.connectionUpdated.listen((connected) {}); - _purchaseUpdatedSubscription = FlutterInappPurchase.purchaseUpdated.listen(_handlePurchaseUpdate); - _purchaseErrorSubscription = FlutterInappPurchase.purchaseError.listen(_handlePurchaseError); + await FlutterInappPurchase.instance.initConnection(); + _purchaseUpdatedSubscription = FlutterInappPurchase.instance.purchaseUpdatedListener.listen( + _handlePurchaseUpdate, + ); + _purchaseErrorSubscription = FlutterInappPurchase.instance.purchaseErrorListener.listen(_handlePurchaseError); await _getItems(); - _activePurchaseItem = await _getPastPurchases(); + _activePurchaseItem = await _getPastPurchase(); }); await ensureReady(); } @@ -111,17 +108,16 @@ class PaymentService { /// call when user close the app void dispose() async { - await _connectionSubscription?.cancel(); await _purchaseErrorSubscription?.cancel(); await _purchaseUpdatedSubscription?.cancel(); - await FlutterInappPurchase.instance.finalize(); + await FlutterInappPurchase.instance.endConnection(); } // Must be called on iOS because Apple don't offer a server API to confirm that // a purchase has been handled. - Future finishTransaction(PurchasedItem purchasedItem) async { + Future finishTransaction(Purchase purchasedItem) async { if (KeeVaultPlatform.isIOS) { - await FlutterInappPurchase.instance.finishTransaction(purchasedItem); + await FlutterInappPurchase.instance.finishTransaction(purchase: purchasedItem.toInput()); // if above fails, we'll not remove the purchasedItem from the queue. If we did // we would risk not responding to App Store update notifications even if there // is only a transient problem. @@ -129,8 +125,8 @@ class PaymentService { } } - void _handlePurchaseError(PurchaseResult? purchaseError) { - _callErrorListeners(purchaseError?.message ?? ''); + void _handlePurchaseError(PurchaseError purchaseError) { + _callErrorListeners(purchaseError.message); } /// Called when new updates arrives at ``purchaseUpdated`` stream @@ -142,71 +138,70 @@ class PaymentService { /// Can happen in iOS at any time and appears to keep sending the same message /// again and again so we need to be able to de-dup. Once we call "finish transaction" /// they will stop sending them. - void _handlePurchaseUpdate(PurchasedItem? productItem) async { + void _handlePurchaseUpdate(Purchase? productItem) async { if (productItem == null) return; if (KeeVaultPlatform.isAndroid) { - await _handlePurchaseUpdateAndroid(productItem); + await _handlePurchaseUpdateAndroid(productItem as PurchaseAndroid); } else { - await _handlePurchaseUpdateIOS(productItem); + await _handlePurchaseUpdateIOS(productItem as PurchaseIOS); } } - Future _handlePurchaseUpdateIOS(PurchasedItem purchasedItem) async { - switch (purchasedItem.transactionStateIOS) { - case TransactionState.deferred: - // Edit: This was a bug that was pointed out here : https://github.com/dooboolab/flutter_inapp_purchase/issues/234 - // FlutterInappPurchase.instance.finishTransaction(purchasedItem); - break; - case TransactionState.failed: - _callErrorListeners('Transaction Failed'); - await FlutterInappPurchase.instance.finishTransaction(purchasedItem); - break; - case TransactionState.purchased: - if (purchasedItem.transactionDate == null) { - l.e('Purchased Item contained no transaction date. Will auto-finish it since it must be an iOS bug or fraud'); - await FlutterInappPurchase.instance.finishTransaction(purchasedItem); - break; - } - - // Could interrupt user to say that their subscription is ready but it will often be - // a renewing subscription and they could be in the middle of something critical so - // that would be a bad user experience and we therefore leave it up to them to handle - // it when they are ready to do so. Alternatively, we will automatically dismiss the - // queued payment item on iOS once they next authenticate / sign-in. - if (_purchasedListeners.isEmpty) { - // If purchased date is different than our current pending purchase item, confirm the older - // transaction straight away since it must be out of date info (e.g. a renewal purchase has since - // superseded it so we have no use for the old information). - // If dates are an exact match we just go with whatever the latest item iOS supplies, - // although it is most likely to just be a duplicate of what we already have. - if (_activePurchaseItem != null) { - if (purchasedItem.transactionDate!.isBefore(_activePurchaseItem!.transactionDate!)) { - await FlutterInappPurchase.instance.finishTransaction(purchasedItem); - break; - } else if (purchasedItem.transactionDate!.isAfter(_activePurchaseItem!.transactionDate!)) { - // Have to make sure we update this now because may be some time before iOS completes - // the transaction finish request and more purchasedItems may arrive in the mean time. - final itemToFinish = _activePurchaseItem!; - _activePurchaseItem = purchasedItem; - await FlutterInappPurchase.instance.finishTransaction(itemToFinish); - break; - } + Future _handlePurchaseUpdateIOS(PurchaseIOS purchase) async { + // iOS purchase updates with valid tokens indicate successful purchases + final bool condition1 = purchase.iosTransactionState == TransactionState.purchased; + bool condition2 = purchase.purchaseToken != null && purchase.purchaseToken!.isNotEmpty; + final bool condition3 = purchase.transactionIdFor != null; + if (condition1 || condition2 || condition3) { + // Could interrupt user to say that their subscription is ready but it will often be + // a renewing subscription and they could be in the middle of something critical so + // that would be a bad user experience and we therefore leave it up to them to handle + // it when they are ready to do so. Alternatively, we will automatically dismiss the + // queued payment item on iOS once they next authenticate / sign-in. + if (_purchasedListeners.isEmpty) { + // If purchased date is different than our current pending purchase item, confirm the older + // transaction straight away since it must be out of date info (e.g. a renewal purchase has since + // superseded it so we have no use for the old information). + // If dates are an exact match we just go with whatever the latest item iOS supplies, + // although it is most likely to just be a duplicate of what we already have. + if (_activePurchaseItem != null) { + if (purchase.transactionDate < _activePurchaseItem!.transactionDate) { + await FlutterInappPurchase.instance.finishTransaction(purchase: purchase); + return; + } else if (purchase.transactionDate > _activePurchaseItem!.transactionDate) { + // Have to make sure we update this now because may be some time before iOS completes + // the transaction finish request and more purchasedItems may arrive in the mean time. + final itemToFinish = _activePurchaseItem!; + _activePurchaseItem = purchase; + await FlutterInappPurchase.instance.finishTransaction(purchase: itemToFinish); + return; } - _activePurchaseItem = purchasedItem; - } else { - _callPurchasedListeners(purchasedItem); } - break; - case TransactionState.purchasing: - break; - case TransactionState.restored: - // It looks like we are never notified of this anyway (transaction is finished in native - // code) but doesn't matter since user's authorisation is tied to their Kee Vault - // Account rather than anything specific to this device so restorations do not need - // to be considered in any way. - await FlutterInappPurchase.instance.finishTransaction(purchasedItem); - break; - default: + _activePurchaseItem = purchase; + } else { + _callPurchasedListeners(purchase); + } + } else { + switch (purchase.iosTransactionState) { + case TransactionState.deferred: + // Edit: This was a bug that was pointed out here : https://github.com/dooboolab/flutter_inapp_purchase/issues/234 + // FlutterInappPurchase.instance.finishTransaction(purchasedItem); + break; + case TransactionState.failed: + _callErrorListeners('Transaction Failed'); + await FlutterInappPurchase.instance.finishTransaction(purchase: purchase); + break; + case TransactionState.purchasing: + break; + case TransactionState.restored: + // It looks like we are never notified of this anyway (transaction is finished in native + // code) but doesn't matter since user's authorisation is tied to their Kee Vault + // Account rather than anything specific to this device so restorations do not need + // to be considered in any way. + await FlutterInappPurchase.instance.finishTransaction(purchase: purchase); + break; + default: + } } } @@ -214,17 +209,22 @@ class PaymentService { /// 0 : UNSPECIFIED_STATE /// 1 : PURCHASED /// 2 : PENDING - Future _handlePurchaseUpdateAndroid(PurchasedItem purchasedItem) async { - switch (purchasedItem.purchaseStateAndroid) { - case PurchaseState.purchased: - _callPurchasedListeners(purchasedItem); - break; - default: - _callErrorListeners('Something went wrong'); + Future _handlePurchaseUpdateAndroid(PurchaseAndroid purchase) async { + // For Android, check multiple conditions since fields can be null + final bool condition1 = purchase.purchaseState == PurchaseState.Purchased; + final bool condition2 = + purchase.androidIsAcknowledged == false && + purchase.purchaseToken != null && + purchase.purchaseToken!.isNotEmpty && + purchase.purchaseState == PurchaseState.Purchased; + final bool condition3 = purchase.androidPurchaseStateValue == AndroidPurchaseState.Purchased.value; + + if (condition1 || condition2 || condition3) { + _callPurchasedListeners(purchase); } } - Future> get products async { + Future> get products async { if (_products == null) { await _getItems(); } @@ -232,22 +232,27 @@ class PaymentService { } Future _getItems() async { - List items = await FlutterInappPurchase.instance.getSubscriptions(_productIds); + final items = await FlutterInappPurchase.instance.fetchProducts( + skus: _productIds, + type: ProductQueryType.Subs, + ); _products = []; for (var item in items) { - l.d('IAP item found: ${item.productId}'); + l.d('IAP item found: ${item.id}'); _products!.add(item); } l.d('${_products!.length} IAP items found.'); } - Future _getPastPurchases() async { + Future _getPastPurchase() async { // pending purchases in iOS are continually pushed to the purchase // stream so we mustn't go looking for them explicitly + //TODO:f: Possibly with Storekit2 we could now do this and may be useful for + // enabling purchasing from outside the normal flow... which is currently nonsensical. if (KeeVaultPlatform.isIOS) { return null; } - List purchasedItems = await FlutterInappPurchase.instance.getAvailablePurchases() ?? []; + List purchasedItems = await FlutterInappPurchase.instance.getAvailablePurchases(); for (var purchasedItem in purchasedItems) { // Assumes only one active subscription at a time. Which should be the case for foreseeable future. @@ -256,7 +261,42 @@ class PaymentService { return null; } - Future buyProduct(IAPItem item, int offerTokenIndex) async { - await FlutterInappPurchase.instance.requestSubscription(item.productId!, offerTokenIndex: offerTokenIndex); + Future buyProduct(ProductSubscription item, int offerTokenIndex) async { + if (item is ProductSubscriptionAndroid) { + final offer = (offerTokenIndex >= 0 && item.subscriptionOfferDetailsAndroid.length > offerTokenIndex) + ? item.subscriptionOfferDetailsAndroid[offerTokenIndex] + : null; + final subsProps = RequestPurchaseProps.subs(( + ios: null, + android: RequestSubscriptionAndroidProps( + skus: [item.id], + subscriptionOffers: offer != null + ? [AndroidSubscriptionOfferInput(offerToken: offer.offerToken, sku: item.id)] + : null, + ), + useAlternativeBilling: null, + )); + await FlutterInappPurchase.instance.requestPurchase(subsProps); + } else if (item is ProductSubscriptionIOS) { + final subsProps = RequestPurchaseProps.subs(( + ios: RequestSubscriptionIosProps(sku: item.id), + android: null, + useAlternativeBilling: null, + )); + await FlutterInappPurchase.instance.requestPurchase(subsProps); + } + } + + Future isEligibleForIntroOfferIOS() async { + try { + // We send the subscription group ID as documented. Unfortunately other + // documentation says we need to use a subscription product ID instead so we may + // still be unable to report an accurate free trial eligibility status to the + // user. + final isEligible = await FlutterInappPurchase.instance.isEligibleForIntroOfferIOS('21222841'); + return isEligible; + } on Exception { + return true; + } } } diff --git a/lib/user_repository.dart b/lib/user_repository.dart index 96c0a8d..6e7019d 100644 --- a/lib/user_repository.dart +++ b/lib/user_repository.dart @@ -88,7 +88,7 @@ class UserRepository { // If user has submitted same subscription ID again, they'll just get stuck here // for ages and be told to try later. not ideal but not unsafe - Future waitUntilValidSubscription(User user, PurchasedItem purchasedItem) async { + Future waitUntilValidSubscription(User user, Purchase purchasedItem) async { for (final delay in [3, 4, 6, 10, 10, 15, 20]) { await Future.delayed(Duration(seconds: delay)); try { diff --git a/lib/widgets/account_create.dart b/lib/widgets/account_create.dart index 0355c8f..5aab3c9 100644 --- a/lib/widgets/account_create.dart +++ b/lib/widgets/account_create.dart @@ -5,7 +5,7 @@ import 'package:email_validator/email_validator.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_inapp_purchase/modules.dart'; +import 'package:flutter_inapp_purchase/types.dart'; import 'package:kdbx/kdbx.dart'; import 'package:keevault/config/platform.dart'; import 'package:keevault/vault_backend/exceptions.dart'; @@ -25,7 +25,7 @@ import 'coloured_safe_area_widget.dart'; import 'subscriber_terms_dialog.dart'; class IapDetails { - List products; + List products; int offerTokenIndex; bool trialAvailable; String? formattedPrice; @@ -64,7 +64,7 @@ class _AccountCreateWidgetState extends State { String? registrationErrorMessage; - Function(PurchasedItem)? purchaseListenerCallback; + Function(Purchase)? purchaseListenerCallback; @override void initState() { @@ -95,7 +95,7 @@ class _AccountCreateWidgetState extends State { } Future handlePurchaseItem( - PurchasedItem item, + Purchase item, bool isAndroid, BlockingOverlayState blockingOverlay, AccountCubit accountCubit, @@ -161,7 +161,7 @@ class _AccountCreateWidgetState extends State { final vaultCubit = BlocProvider.of(context); final blockingOverlay = BlockingOverlay.of(context); final iapReady = await PaymentService.instance.ensureReady(); - List prods = []; + List prods = []; attachIapListeners() { PaymentService.instance.addToErrorListeners((msg) { @@ -169,21 +169,23 @@ class _AccountCreateWidgetState extends State { blockingOverlay.hide(); }); purchaseListenerCallback = (item) async { - if (item.purchaseToken == null && item.transactionReceipt == null) { + if (item.purchaseToken == null) { return; } if (accountCubit.state is AccountSubscribing) { final str = S.current; await handlePurchaseItem( item, - item.purchaseStateAndroid != null, + item.platform == IapPlatform.Android, blockingOverlay, accountCubit, vaultCubit, str, ); } else { - // We're not expecting this purchase so we will defer it until the user has navigated to a point where we can do something useful with it (e.g. either creating a new account or exiting and signing in again with fresh authentication tokens) + // We're not expecting this purchase so we will defer it until the user has + // navigated to a point where we can do something useful with it (e.g. either + // creating a new account or exiting and signing in again with fresh authentication tokens) PaymentService.instance.deferPurchaseItem(item); } }; @@ -196,29 +198,37 @@ class _AccountCreateWidgetState extends State { if (KeeVaultPlatform.isIOS) { attachIapListeners(); + final isTrialAvailable = await PaymentService.instance.isEligibleForIntroOfferIOS(); + setState(() { iap = IapDetails( products: prods, offerTokenIndex: -1, - trialAvailable: true, // Apple don't permit us to know this information so we show the more general text - formattedPrice: prods[0].localizedPrice, + trialAvailable: isTrialAvailable, + formattedPrice: prods[0].displayPrice, ); }); return; } if (KeeVaultPlatform.isAndroid) { - final trialProductIndex = - prods[0].subscriptionOffersAndroid?.indexWhere((o) => o.offerId == 'supporter-yearly-trial') ?? -1; + final prodSub = prods[0] as ProductSubscriptionAndroid; + final trialProductIndex = prodSub.subscriptionOfferDetailsAndroid.indexWhere( + (o) => o.offerId == 'supporter-yearly-trial', + ); final selectedProductIndex = trialProductIndex >= 0 ? trialProductIndex - : prods[0].subscriptionOffersAndroid?.indexWhere((o) => o.basePlanId == 'supporter-yearly') ?? -1; + : prodSub.subscriptionOfferDetailsAndroid.indexWhere((o) => o.basePlanId == 'supporter-yearly'); final selectedProduct = selectedProductIndex >= 0 - ? (prods[0].subscriptionOffersAndroid![selectedProductIndex]) + ? (prodSub.subscriptionOfferDetailsAndroid[selectedProductIndex]) : null; if (selectedProduct != null) { - final pricingIndex = selectedProduct.pricingPhases?.indexWhere((p) => p.recurrenceMode == 1) ?? -1; - final price = pricingIndex >= 0 ? selectedProduct.pricingPhases![pricingIndex].formattedPrice : null; + final pricingIndex = selectedProduct.pricingPhases.pricingPhaseList.indexWhere( + (p) => p.recurrenceMode == 1, + ); + final price = pricingIndex >= 0 + ? selectedProduct.pricingPhases.pricingPhaseList[pricingIndex].formattedPrice + : null; attachIapListeners(); setState(() { diff --git a/pubspec.lock b/pubspec.lock index ea6c559..352416a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -86,10 +86,10 @@ packages: dependency: "direct main" description: name: barcode_scan2 - sha256: "0f3eb7c0a0c80a0f65d3fa88737544fdb6d27127a4fad566e980e626f3fb76e1" + sha256: "50b286021c644deee71e20a06c1709adc6594e39d65024ced0458cc1e3ff298e" url: "https://pub.dev" source: hosted - version: "4.5.1" + version: "4.6.0" base32: dependency: "direct main" description: @@ -355,11 +355,10 @@ packages: flutter_autofill_service: dependency: "direct main" description: - name: flutter_autofill_service - sha256: "54f520588a1fb6cdfd90d1d0424c06d28ee334c6ab62239927491767f8754aa1" - url: "https://pub.dev" - source: hosted - version: "0.20.0" + path: "../flutter_autofill_service" + relative: true + source: path + version: "0.21.0" flutter_bloc: dependency: "direct main" description: @@ -389,10 +388,10 @@ packages: dependency: "direct main" description: name: flutter_inapp_purchase - sha256: "748757271506a3cc7745aa501019c7ce8051d8738b8a36aee12a617d8e9df8d3" + sha256: e392f84a2f3aa2ccf71cd1a432beb0dbc5c062cc6bc755c2966c606e6a671281 url: "https://pub.dev" source: hosted - version: "5.6.2" + version: "7.2.0" flutter_launcher_icons: dependency: "direct dev" description: @@ -865,10 +864,10 @@ packages: dependency: transitive description: name: protobuf - sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" + sha256: "75ec242d22e950bdcc79ee38dd520ce4ee0bc491d7fadc4ea47694604d22bf06" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "6.0.0" provider: dependency: transitive description: @@ -1279,5 +1278,5 @@ packages: source: hosted version: "1.0.0" sdks: - dart: ">=3.8.0 <4.0.0" + dart: ">=3.9.0 <4.0.0" flutter: ">=3.35.0" diff --git a/pubspec.yaml b/pubspec.yaml index e6d6568..0ea9979 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -110,10 +110,7 @@ dependencies: argon2_ffi_base: ^1.1.1 uuid: ^4.5.2 clock: ^1.1.2 - flutter_inapp_purchase: ^5.6.2 - # git: - # url: https://github.com/kee-org/flutter_inapp_purchase - # ref: main + flutter_inapp_purchase: ^7.2.0 sensitive_clipboard: git: url: https://github.com/kee-org/sensitive_clipboard @@ -125,7 +122,7 @@ dependencies: ref: api34 archive: ^4.0.7 device_info_plus: ^11.5.0 - barcode_scan2: ^4.5.1 + barcode_scan2: ^4.6.0 flex_color_scheme: ^8.3.1 # barcode_scan2: # git: From fcd2fbb21c2f084415a823ad0b4ec1510f0c0974 Mon Sep 17 00:00:00 2001 From: luckyrat Date: Sat, 17 Jan 2026 19:34:34 +0000 Subject: [PATCH 03/10] Update autofill lib --- lib/cubit/autofill_cubit.dart | 1 + lib/widgets/autofill_save.dart | 11 +++++++---- pubspec.lock | 8 +++++--- pubspec.yaml | 10 +++++----- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/lib/cubit/autofill_cubit.dart b/lib/cubit/autofill_cubit.dart index 4001a2e..1b3daa1 100644 --- a/lib/cubit/autofill_cubit.dart +++ b/lib/cubit/autofill_cubit.dart @@ -128,6 +128,7 @@ class AutofillCubit extends Cubit { Future autofillWithList(LocalVaultFile vault) async { final androidMetadata = (state as AutofillRequested).androidMetadata; if (shouldIgnoreRequest(androidMetadata)) { + l.d('ignoring autofillWithList request'); await AutofillService().resultWithDatasets(null); return true; } diff --git a/lib/widgets/autofill_save.dart b/lib/widgets/autofill_save.dart index 2c596e9..0fab15f 100644 --- a/lib/widgets/autofill_save.dart +++ b/lib/widgets/autofill_save.dart @@ -60,14 +60,17 @@ class _AutofillSaveWidgetState extends State with TraceableC if (webDomain.isNotEmpty) { newEntry!.addAutofillUrl(webDomain, scheme); - newEntry!.setString(KdbxKeyCommon.TITLE, PlainValue(webDomain)); } else if (appId.isNotEmpty) { newEntry!.addAndroidPackageName(appId); - newEntry!.setString(KdbxKeyCommon.TITLE, PlainValue(appId)); - } else { - newEntry!.setString(KdbxKeyCommon.TITLE, PlainValue('[untitled]')); } + final newTitle = webDomain.isNotEmpty + ? webDomain + : appId.isNotEmpty + ? appId + : '[untitled]'; + newEntry!.setString(KdbxKeyCommon.TITLE, PlainValue(newTitle)); + username?.let((it) => newEntry!.setString(KdbxKeyCommon.USER_NAME, PlainValue(it))); password?.let((it) => newEntry!.setString(KdbxKeyCommon.PASSWORD, PlainValue(it))); BlocProvider.of(context).startEditing(newEntry!, startDirty: false); diff --git a/pubspec.lock b/pubspec.lock index 352416a..d62df46 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -355,9 +355,11 @@ packages: flutter_autofill_service: dependency: "direct main" description: - path: "../flutter_autofill_service" - relative: true - source: path + path: "." + ref: api36 + resolved-ref: "55538f1870abbef1f67f4617a1e4670ee9df13f6" + url: "https://github.com/kee-org/flutter_autofill_service.git" + source: git version: "0.21.0" flutter_bloc: dependency: "direct main" diff --git a/pubspec.yaml b/pubspec.yaml index 0ea9979..d46b3e8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 2.5.0+58 +version: 2.6.0+59 environment: sdk: '>=3.9.0 <4.0.0' @@ -45,10 +45,10 @@ dependencies: git: url: https://github.com/kee-org/argon2_ffi.git ref: master - flutter_autofill_service: ^0.20.0 - # git: - # url: https://github.com/kee-org/flutter_autofill_service.git - # ref: master + flutter_autofill_service: #^0.21.0 + git: + url: https://github.com/kee-org/flutter_autofill_service.git + ref: api36 bloc: ^9.1.0 flutter_bloc: ^9.1.1 fluro: ^2.0.5 From 78a1e9cf9e4320e79fe71bb24a33328b82e1ccdc Mon Sep 17 00:00:00 2001 From: luckyrat Date: Sat, 17 Jan 2026 19:37:24 +0000 Subject: [PATCH 04/10] Update Changelog --- android/fastlane/metadata/android/en-GB/changelogs/59.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 android/fastlane/metadata/android/en-GB/changelogs/59.txt diff --git a/android/fastlane/metadata/android/en-GB/changelogs/59.txt b/android/fastlane/metadata/android/en-GB/changelogs/59.txt new file mode 100644 index 0000000..9521cca --- /dev/null +++ b/android/fastlane/metadata/android/en-GB/changelogs/59.txt @@ -0,0 +1,4 @@ +* New autocomplete feature on the Username field - select from previously used usernames to speed up the creation of new entries with common usernames such as your primary email address. +* Improved AutoFill behaviour in some apps and websites. +* Updated Flutter and other dependencies. +* Improved performance on newer Android devices (by supporting 16K Android memory page size). From 3f7b4248d472bfe58d2c1ca8ed419889bd7fdc23 Mon Sep 17 00:00:00 2001 From: luckyrat Date: Sat, 17 Jan 2026 20:54:28 +0000 Subject: [PATCH 05/10] Upgrade to Flutter 3.38 --- .fvmrc | 2 +- .vscode/settings.json | 2 +- lib/widgets/color_chooser.dart | 2 +- lib/widgets/color_filter.dart | 2 +- lib/widgets/entry.dart | 2 +- lib/widgets/intro_vault_summary.dart | 2 +- pubspec.lock | 200 ++++++++++++++++----------- pubspec.yaml | 6 +- 8 files changed, 125 insertions(+), 93 deletions(-) diff --git a/.fvmrc b/.fvmrc index e8b4151..bd157de 100644 --- a/.fvmrc +++ b/.fvmrc @@ -1,3 +1,3 @@ { - "flutter": "3.35.7" + "flutter": "3.38.7" } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 9615e51..69ae94e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -57,7 +57,7 @@ "*.dll", "**/*.dll" ], - "dart.flutterSdkPath": ".fvm/versions/3.35.7", + "dart.flutterSdkPath": ".fvm/versions/3.38.7", "search.exclude": { "**/.fvm": true }, diff --git a/lib/widgets/color_chooser.dart b/lib/widgets/color_chooser.dart index 64767ee..9d7da35 100644 --- a/lib/widgets/color_chooser.dart +++ b/lib/widgets/color_chooser.dart @@ -23,7 +23,7 @@ class ColorChooser extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(25.0), color: color, - boxShadow: [BoxShadow(color: color.withOpacity(0.8), offset: Offset(1.0, 2.0), blurRadius: 3.0)], + boxShadow: [BoxShadow(color: color.withValues(alpha: 0.8), offset: Offset(1.0, 2.0), blurRadius: 3.0)], ), child: Material( color: Colors.transparent, diff --git a/lib/widgets/color_filter.dart b/lib/widgets/color_filter.dart index dd2ed38..3cb2a74 100644 --- a/lib/widgets/color_filter.dart +++ b/lib/widgets/color_filter.dart @@ -77,7 +77,7 @@ class ColorFilterWidget extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(24.0), color: color, - boxShadow: [BoxShadow(color: color.withOpacity(0.8), offset: Offset(1.0, 2.0), blurRadius: 2.0)], + boxShadow: [BoxShadow(color: color.withValues(alpha: 0.8), offset: Offset(1.0, 2.0), blurRadius: 2.0)], ), child: Material( color: Colors.transparent, diff --git a/lib/widgets/entry.dart b/lib/widgets/entry.dart index 788cd91..9675ba9 100644 --- a/lib/widgets/entry.dart +++ b/lib/widgets/entry.dart @@ -754,7 +754,7 @@ class ObscuredEntryFieldEditor extends StatelessWidget { labelText: field.name ?? field.key?.key, prefixIcon: field.icon != null ? Icon(field.icon) : null, ), - child: Text('*anythIng*', style: TextStyle(color: color.withOpacity(0), fontSize: 16)), + child: Text('*anythIng*', style: TextStyle(color: color.withValues(alpha: 0), fontSize: 16)), ), Positioned.fill( top: 12, diff --git a/lib/widgets/intro_vault_summary.dart b/lib/widgets/intro_vault_summary.dart index 37c9594..c6ce419 100644 --- a/lib/widgets/intro_vault_summary.dart +++ b/lib/widgets/intro_vault_summary.dart @@ -36,7 +36,7 @@ class _IntroVaultSummaryWidgetState extends State with filter: ImageFilter.blur(sigmaX: 1.5, sigmaY: 1.5), child: Container( alignment: Alignment.center, - decoration: BoxDecoration(color: widget.theme.canvasColor.withOpacity(0.75)), + decoration: BoxDecoration(color: widget.theme.canvasColor.withValues(alpha: 0.75)), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8), child: Column( diff --git a/pubspec.lock b/pubspec.lock index d62df46..0cd78dd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f + sha256: c209688d9f5a5f26b2fb47a188131a6fb9e876ae9e47af3737c0b4f58a93470d url: "https://pub.dev" source: hosted - version: "85.0.0" + version: "91.0.0" adaptive_number: dependency: transitive description: @@ -21,18 +21,18 @@ packages: dependency: transitive description: name: analyzer - sha256: "01949bf52ad33f0e0f74f881fbaac4f348c556531951d92c8d16f1262aa19ff8" + sha256: f51c8499b35f9b26820cfe914828a6a98a94efd5cc78b37bb7d03debae3a1d08 url: "https://pub.dev" source: hosted - version: "7.5.4" + version: "8.4.1" animations: dependency: "direct main" description: name: animations - sha256: d3d6dcfb218225bbe68e87ccf6378bbb2e32a94900722c5f81611dad089911cb + sha256: "18938cefd7dcc04e1ecac0db78973761a01e4bc2d6bfae0cfa596bfeac9e96ab" url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.1.1" ansicolor: dependency: transitive description: @@ -86,10 +86,10 @@ packages: dependency: "direct main" description: name: barcode_scan2 - sha256: "50b286021c644deee71e20a06c1709adc6594e39d65024ced0458cc1e3ff298e" + sha256: "9b539b0ce419005c451de66374c79f39801986f1fd7a213e63d948f21487cd69" url: "https://pub.dev" source: hosted - version: "4.6.0" + version: "4.7.2" base32: dependency: "direct main" description: @@ -111,10 +111,10 @@ packages: dependency: "direct main" description: name: bloc - sha256: a2cebb899f91d36eeeaa55c7b20b5915db5a9df1b8fd4a3c9c825e22e474537d + sha256: a48653a82055a900b88cd35f92429f068c5a8057ae9b136d197b3d56c57efb81 url: "https://pub.dev" source: hosted - version: "9.1.0" + version: "9.2.0" boolean_selector: dependency: transitive description: @@ -127,10 +127,10 @@ packages: dependency: transitive description: name: build_config - sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.2.0" characters: dependency: transitive description: @@ -163,6 +163,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: ae0db647e668cbb295a3527f0938e4039e004c80099dce2f964102373f5ce0b5 + url: "https://pub.dev" + source: hosted + version: "0.19.10" collection: dependency: "direct main" description: @@ -183,18 +191,18 @@ packages: dependency: transitive description: name: cross_file - sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + sha256: "701dcfc06da0882883a2657c445103380e53e647060ad8d9dfb710c100996608" url: "https://pub.dev" source: hosted - version: "0.3.4+2" + version: "0.3.5+1" crypto: dependency: transitive description: name: crypto - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.7" csslib: dependency: transitive description: @@ -239,10 +247,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a" + sha256: "4df8babf73058181227e18b08e6ea3520cf5fc5d796888d33b7cb0f33f984b7c" url: "https://pub.dev" source: hosted - version: "11.5.0" + version: "12.3.0" device_info_plus_platform_interface: dependency: transitive description: @@ -295,10 +303,10 @@ packages: dependency: transitive description: name: ffi - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + sha256: d07d37192dbf97461359c1518788f203b0c9102cfd2c35a716b823741219542c url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" file: dependency: transitive description: @@ -311,10 +319,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: f2d9f173c2c14635cc0e9b14c143c49ef30b4934e8d1d274d6206fcb0086a06f + sha256: d974b6ba2606371ac71dd94254beefb6fa81185bde0b59bdc1df09885da85fde url: "https://pub.dev" source: hosted - version: "10.3.3" + version: "10.3.8" fixnum: dependency: transitive description: @@ -327,18 +335,18 @@ packages: dependency: "direct main" description: name: flex_color_scheme - sha256: "6e713c27a2ebe63393a44d4bf9cdd2ac81e112724a4c69905fc41cbf231af11d" + sha256: ab854146f201d2d62cc251fd525ef023b84182c4a0bfe4ae4c18ffc505b412d3 url: "https://pub.dev" source: hosted - version: "8.3.1" + version: "8.4.0" flex_seed_scheme: dependency: transitive description: name: flex_seed_scheme - sha256: b06d8b367b84cbf7ca5c5603c858fa5edae88486c4e4da79ac1044d73b6c62ec + sha256: a3183753bbcfc3af106224bff3ab3e1844b73f58062136b7499919f49f3667e7 url: "https://pub.dev" source: hosted - version: "3.5.1" + version: "4.0.1" fluro: dependency: "direct main" description: @@ -382,10 +390,10 @@ packages: dependency: "direct main" description: name: flutter_file_dialog - sha256: "9344b8f07be6a1b6f9854b723fb0cf84a8094ba94761af1d213589d3cb087488" + sha256: ec904d15e7da3691bb60442a762b0a09afa37ded7265b9fc2088ec202b7d844f url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" flutter_inapp_purchase: dependency: "direct main" description: @@ -436,10 +444,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: f948e346c12f8d5480d2825e03de228d0eb8c3a737e4cdaa122267b89c022b5e + sha256: ee8068e0e1cd16c4a82714119918efdeed33b3ba7772c54b5d094ab53f9b7fd1 url: "https://pub.dev" source: hosted - version: "2.0.28" + version: "2.0.33" flutter_rating_bar: dependency: "direct main" description: @@ -488,10 +496,10 @@ packages: dependency: "direct main" description: name: font_awesome_flutter - sha256: d3a89184101baec7f4600d58840a764d2ef760fe1c5a20ef9e6b0e9b24a07a3a + sha256: b9011df3a1fa02993630b8fb83526368cf2206a711259830325bab2f1d2a4eb0 url: "https://pub.dev" source: hosted - version: "10.8.0" + version: "10.12.0" glob: dependency: transitive description: @@ -500,6 +508,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" + hooks: + dependency: transitive + description: + name: hooks + sha256: "5410b9f4f6c9f01e8ff0eb81c9801ea13a3c3d39f8f0b1613cda08e27eab3c18" + url: "https://pub.dev" + source: hosted + version: "0.20.5" html: dependency: transitive description: @@ -512,10 +528,10 @@ packages: dependency: transitive description: name: http - sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.6.0" http_parser: dependency: transitive description: @@ -528,10 +544,10 @@ packages: dependency: transitive description: name: image - sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" + sha256: "492bd52f6c4fbb6ee41f781ff27765ce5f627910e1e0cbecfa3d9add5562604c" url: "https://pub.dev" source: hosted - version: "4.5.4" + version: "4.7.2" intl: dependency: transitive description: @@ -552,10 +568,10 @@ packages: dependency: "direct main" description: name: jiffy - sha256: "9bafbfe6d97587048bf449165e050029e716a12438f54a3d39e7e3a256decdac" + sha256: e6f3b2aaec032f95ae917268edcbf007a5b834b57a602d39eb0ab17995a9c64a url: "https://pub.dev" source: hosted - version: "6.4.3" + version: "6.4.4" json_annotation: dependency: transitive description: @@ -577,10 +593,10 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "11.0.1" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: @@ -634,10 +650,10 @@ packages: dependency: transitive description: name: logging_appenders - sha256: e329e7472f99416d0edaaf6451fe6c02dec91d34535bd252e284a0b94ab23d79 + sha256: "7fefa09636824f312432721c0bf77967ab19003116650729bd202bdf98142d70" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.4.0+1" matcher: dependency: transitive description: @@ -666,10 +682,10 @@ packages: dependency: "direct main" description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mime: dependency: "direct main" description: @@ -678,6 +694,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + native_toolchain_c: + dependency: transitive + description: + name: native_toolchain_c + sha256: f8872ea6c7a50ce08db9ae280ca2b8efdd973157ce462826c82f3c3051d154ce + url: "https://pub.dev" + source: hosted + version: "0.17.2" nested: dependency: transitive description: @@ -686,6 +710,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "55eb67ede1002d9771b3f9264d2c9d30bc364f0267bc1c6cc0883280d5f0c7cb" + url: "https://pub.dev" + source: hosted + version: "9.2.2" otp: dependency: "direct main" description: @@ -706,10 +738,10 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" + sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d url: "https://pub.dev" source: hosted - version: "8.3.1" + version: "9.0.0" package_info_plus_platform_interface: dependency: transitive description: @@ -738,18 +770,18 @@ packages: dependency: transitive description: name: path_provider_android - sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 + sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e url: "https://pub.dev" source: hosted - version: "2.2.17" + version: "2.2.22" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.6.0" path_provider_linux: dependency: transitive description: @@ -874,10 +906,10 @@ packages: dependency: transitive description: name: provider - sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "6.1.5+1" pub_semver: dependency: transitive description: @@ -949,10 +981,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: d7dc0630a923883c6328ca31b89aa682bacbf2f8304162d29f7c6aaff03a27a1 + sha256: "14c8860d4de93d3a7e53af51bff479598c4e999605290756bbbe45cf65b37840" url: "https://pub.dev" source: hosted - version: "11.1.0" + version: "12.0.1" share_plus_platform_interface: dependency: transitive description: @@ -965,26 +997,26 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64" url: "https://pub.dev" source: hosted - version: "2.5.3" + version: "2.5.4" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac" + sha256: "83af5c682796c0f7719c2bbf74792d113e40ae97981b8f266fa84574573556bc" url: "https://pub.dev" source: hosted - version: "2.4.10" + version: "2.4.18" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" url: "https://pub.dev" source: hosted - version: "2.5.4" + version: "2.5.6" shared_preferences_linux: dependency: transitive description: @@ -1083,10 +1115,10 @@ packages: dependency: transitive description: name: test_api - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.6" + version: "0.7.7" timezone: dependency: transitive description: @@ -1115,10 +1147,10 @@ packages: dependency: transitive description: name: universal_io - sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2 url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.1" universal_platform: dependency: transitive description: @@ -1139,34 +1171,34 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79" + sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611" url: "https://pub.dev" source: hosted - version: "6.3.16" + version: "6.3.28" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" + sha256: cfde38aa257dae62ffe79c87fab20165dfdf6988c1d31b58ebf59b9106062aad url: "https://pub.dev" source: hosted - version: "6.3.3" + version: "6.3.6" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" + sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" + sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" url: "https://pub.dev" source: hosted - version: "3.2.2" + version: "3.2.5" url_launcher_platform_interface: dependency: transitive description: @@ -1179,18 +1211,18 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" + sha256: d0412fcf4c6b31ecfdb7762359b7206ffba3bbffd396c6d9f9c4616ece476c1f url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.5" uuid: dependency: "direct main" description: @@ -1211,18 +1243,18 @@ packages: dependency: transitive description: name: vm_service - sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" url: "https://pub.dev" source: hosted - version: "15.0.0" + version: "15.0.2" watcher: dependency: transitive description: name: watcher - sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.2.1" web: dependency: transitive description: @@ -1235,10 +1267,10 @@ packages: dependency: transitive description: name: win32 - sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03" + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e url: "https://pub.dev" source: hosted - version: "5.14.0" + version: "5.15.0" win32_registry: dependency: transitive description: @@ -1280,5 +1312,5 @@ packages: source: hosted version: "1.0.0" sdks: - dart: ">=3.9.0 <4.0.0" - flutter: ">=3.35.0" + dart: ">=3.10.3 <4.0.0" + flutter: ">=3.38.4" diff --git a/pubspec.yaml b/pubspec.yaml index d46b3e8..ed90568 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,7 +35,7 @@ dependencies: url: https://github.com/kee-org/biometric_storage.git ref: keevault - package_info_plus: ^8.3.1 + package_info_plus: ^9.0.0 shared_preferences: ^2.5.3 # at least 2.3.4 for security patch flutter_settings_screens: git: @@ -93,7 +93,7 @@ dependencies: zxcvbn: ^1.0.0 flutter_rating_bar: ^4.0.1 mime: ^2.0.0 - share_plus: ^11.1.0 + share_plus: ^12.0.1 path: ^1.9.0 #flutter sdk always lags behind so upgrade this only when needed permission_handler: ^12.0.1 flutter_file_dialog: ^3.0.2 @@ -121,7 +121,7 @@ dependencies: url: https://github.com/kee-org/RateMyApp ref: api34 archive: ^4.0.7 - device_info_plus: ^11.5.0 + device_info_plus: ^12.3.0 barcode_scan2: ^4.6.0 flex_color_scheme: ^8.3.1 # barcode_scan2: From c039a10d99fc1aa46ee3749575597cc6de76967e Mon Sep 17 00:00:00 2001 From: luckyrat Date: Sat, 17 Jan 2026 20:54:54 +0000 Subject: [PATCH 06/10] Dart 3.10 --- lib/cubit/filter_cubit.dart | 2 +- pubspec.yaml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/cubit/filter_cubit.dart b/lib/cubit/filter_cubit.dart index a225ac5..7d43dff 100644 --- a/lib/cubit/filter_cubit.dart +++ b/lib/cubit/filter_cubit.dart @@ -104,7 +104,7 @@ class FilterCubit extends Cubit { bool entryMatches(KdbxEntry entry) { final fa = state as FilterActive; final quickCheck = - (fa.tags.isEmpty || entry.tags.get()!.any((tag) => fa.tags.contains(tag.toLowerCase()))) && + (fa.tags.isEmpty || (entry.tags.get() ?? []).any((tag) => fa.tags.contains(tag.toLowerCase()))) && (fa.colors.isEmpty || fa.colors.contains(entry.color)); if (!quickCheck) { diff --git a/pubspec.yaml b/pubspec.yaml index ed90568..c238038 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 2.6.0+59 environment: - sdk: '>=3.9.0 <4.0.0' + sdk: '>=3.10.0 <4.0.0' dependencies: flutter: @@ -36,11 +36,11 @@ dependencies: ref: keevault package_info_plus: ^9.0.0 - shared_preferences: ^2.5.3 # at least 2.3.4 for security patch + shared_preferences: ^2.5.3 flutter_settings_screens: git: url: https://github.com/Juggler98/flutter_settings_screens.git - ref: 52ac240b7ae0cf48b723818ee233565fd562bc13 # 0.3.4 is incompatible with MD2 + ref: 52ac240b7ae0cf48b723818ee233565fd562bc13 argon2_ffi: git: url: https://github.com/kee-org/argon2_ffi.git From a3b1cdda7bbb31ce99f2118dd629dddbe304c576 Mon Sep 17 00:00:00 2001 From: Chris Tomlinson Date: Sat, 17 Jan 2026 21:22:44 +0000 Subject: [PATCH 07/10] Update iOS build for Flutter 3.38 --- ios/Podfile.lock | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 5e2f95c..d2ce496 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -3,7 +3,6 @@ PODS: - Flutter - barcode_scan2 (0.0.1): - Flutter - - MTBBarcodeScanner - SwiftProtobuf (~> 1.33) - biometric_storage (0.0.1): - Flutter @@ -51,13 +50,9 @@ PODS: - openiap (= 1.3.0) - flutter_native_splash (2.4.3): - Flutter - - MTBBarcodeScanner (5.0.11) - openiap (1.3.0) - package_info_plus (0.4.5): - Flutter - - path_provider_foundation (0.0.1): - - Flutter - - FlutterMacOS - permission_handler_apple (9.3.0): - Flutter - rate_my_app (2.2.0): @@ -89,7 +84,6 @@ DEPENDENCIES: - flutter_inapp_purchase (from `.symlinks/plugins/flutter_inapp_purchase/ios`) - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - rate_my_app (from `.symlinks/plugins/rate_my_app/darwin`) - sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`) @@ -101,7 +95,6 @@ SPEC REPOS: trunk: - DKImagePickerController - DKPhotoGallery - - MTBBarcodeScanner - openiap - SDWebImage - SwiftProtobuf @@ -128,8 +121,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_native_splash/ios" package_info_plus: :path: ".symlinks/plugins/package_info_plus/ios" - path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/darwin" permission_handler_apple: :path: ".symlinks/plugins/permission_handler_apple/ios" rate_my_app: @@ -145,7 +136,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: argon2_ffi: 995b9260d81aa17f5d2a8a497f2d2763ba4c45f3 - barcode_scan2: b486db2ac59ce5c3ad04b154303935b1117e7e56 + barcode_scan2: 050b7b327e85954c8918715d42e83c5a35c3ed89 biometric_storage: 1400f1382af3a4cc2bf05340e13c3d8de873ceb9 device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342 DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c @@ -155,19 +146,17 @@ SPEC CHECKSUMS: flutter_file_dialog: 4c014a45b105709a27391e266c277d7e588e9299 flutter_inapp_purchase: f71036b9e28b3865d3313ea6e4fd01052623b43a flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29 - MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb openiap: b8ae35279df4060abf7dc2fed33e325022eecdf5 package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4 - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2 rate_my_app: cd3e1c44d12f387482698ffaf6ea9bd669a69b94 SDWebImage: e9c98383c7572d713c1a0d7dd2783b10599b9838 sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986 share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6 SwiftProtobuf: e1b437c8e31a4c5577b643249a0bb62ed4f02153 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 - url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe + url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa PODFILE CHECKSUM: 0658f7bb36458779f6da1691e33f9d925242f612 From fea101b144cdf99b8656962ed03678ff4029a6f8 Mon Sep 17 00:00:00 2001 From: Chris Tomlinson Date: Sat, 17 Jan 2026 21:33:46 +0000 Subject: [PATCH 08/10] Update iOS CD Github Actions --- .github/workflows/flutter_build.yml | 4 ++-- .github/workflows/flutter_release_ios.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/flutter_build.yml b/.github/workflows/flutter_build.yml index 95ddd00..45efd45 100644 --- a/.github/workflows/flutter_build.yml +++ b/.github/workflows/flutter_build.yml @@ -74,7 +74,7 @@ jobs: BuildAndTestIos: name: Build ios prod - runs-on: macos-15 + runs-on: macos-26 permissions: write-all steps: @@ -113,7 +113,7 @@ jobs: - name: Choose xcode version uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '16.4' + xcode-version: '26.2' - name: Build iOS Flutter App run: flutter build ios --config-only --release --no-codesign --dart-define KEEVAULT_STAGE=prod --dart-define KEEVAULT_NAME_SUFFIX= --dart-define KEEVAULT_ID_SUFFIX= --dart-define IAP_APPLE_APP_STORE=yes diff --git a/.github/workflows/flutter_release_ios.yml b/.github/workflows/flutter_release_ios.yml index 0dbd49f..6d12ca3 100644 --- a/.github/workflows/flutter_release_ios.yml +++ b/.github/workflows/flutter_release_ios.yml @@ -9,7 +9,7 @@ jobs: if: ${{ !contains ( github.event.release.tag_name, '_' ) || endsWith( github.event.release.tag_name, '_ios' ) || endsWith( github.event.release.tag_name, '_ios_betaonly' ) }} # NB: ${{ syntax }} is required despite GitHub docs to the contrary. Appears that ! operator can't be used otherwise. - runs-on: macos-15 + runs-on: macos-26 permissions: write-all steps: @@ -48,7 +48,7 @@ jobs: - name: Choose xcode version uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '16.4' + xcode-version: '26.2' - name: Build iOS Flutter App run: flutter build ios --config-only --release --no-codesign --dart-define KEEVAULT_STAGE=beta --dart-define KEEVAULT_NAME_SUFFIX='(b)' --dart-define KEEVAULT_ID_SUFFIX=.beta @@ -83,7 +83,7 @@ jobs: name: Build and release prod testflight if: ${{ !contains ( github.event.release.tag_name, '_' ) || endsWith( github.event.release.tag_name, '_ios' ) }} - runs-on: macos-15 + runs-on: macos-26 permissions: write-all steps: @@ -122,7 +122,7 @@ jobs: - name: Choose xcode version uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '16.4' + xcode-version: '26.2' - name: Build iOS Flutter App run: flutter build ios --config-only --release --no-codesign --dart-define KEEVAULT_STAGE=prod --dart-define KEEVAULT_NAME_SUFFIX= --dart-define KEEVAULT_ID_SUFFIX= --dart-define IAP_APPLE_APP_STORE=yes From e308aabe8c3d7e02aca537dc58e34720ca1d778a Mon Sep 17 00:00:00 2001 From: luckyrat Date: Sun, 18 Jan 2026 09:34:41 +0000 Subject: [PATCH 09/10] Target Android SDK 36 --- .gitignore | 1 + android/app/build.gradle | 2 +- pubspec.lock | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index a80999c..ef971ce 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,4 @@ ios/Runner.ipa #android/app/.cxx/ ios/build/ios/XCBuildData/ +android/app/local.properties diff --git a/android/app/build.gradle b/android/app/build.gradle index e539247..b24a7b5 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -115,7 +115,7 @@ android { applicationId "com.keevault.keevault" applicationIdSuffix idSuffix minSdkVersion 29 - targetSdk 35 + targetSdk 36 versionCode flutterVersionCode.toInteger() versionName flutterVersionName resValue "string", "app_name", "Kee Vault" + nameSuffix diff --git a/pubspec.lock b/pubspec.lock index 0cd78dd..55ebf48 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -365,7 +365,7 @@ packages: description: path: "." ref: api36 - resolved-ref: "55538f1870abbef1f67f4617a1e4670ee9df13f6" + resolved-ref: f2026df9616618ebffe86cca704a82ba452e0491 url: "https://github.com/kee-org/flutter_autofill_service.git" source: git version: "0.21.0" From 624409dabb30e2c3a0c183b6d0d88aaae53b96b1 Mon Sep 17 00:00:00 2001 From: luckyrat Date: Mon, 19 Jan 2026 20:03:06 +0000 Subject: [PATCH 10/10] Switch to pub.dev version of autofill service --- pubspec.lock | 9 ++++----- pubspec.yaml | 5 +---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 55ebf48..6a5d5ad 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -363,11 +363,10 @@ packages: flutter_autofill_service: dependency: "direct main" description: - path: "." - ref: api36 - resolved-ref: f2026df9616618ebffe86cca704a82ba452e0491 - url: "https://github.com/kee-org/flutter_autofill_service.git" - source: git + name: flutter_autofill_service + sha256: d791c9d29b1a6b0daa37f21604c63a6a16f445d4c96382c9d68e3210c44a9d8f + url: "https://pub.dev" + source: hosted version: "0.21.0" flutter_bloc: dependency: "direct main" diff --git a/pubspec.yaml b/pubspec.yaml index c238038..9a444ea 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -45,10 +45,7 @@ dependencies: git: url: https://github.com/kee-org/argon2_ffi.git ref: master - flutter_autofill_service: #^0.21.0 - git: - url: https://github.com/kee-org/flutter_autofill_service.git - ref: api36 + flutter_autofill_service: ^0.21.0 bloc: ^9.1.0 flutter_bloc: ^9.1.1 fluro: ^2.0.5