From ef3a663b8805354f925d41bb91532d37c8d81721 Mon Sep 17 00:00:00 2001 From: Dain Nilsson Date: Wed, 4 Sep 2024 11:04:13 +0200 Subject: [PATCH 1/7] Handle timed out FIDO reset on older keys --- helper/helper/fido.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/helper/helper/fido.py b/helper/helper/fido.py index 9c2f3d9d..181cac42 100644 --- a/helper/helper/fido.py +++ b/helper/helper/fido.py @@ -186,8 +186,13 @@ class Ctap2Node(RpcNode): try: self.ctap.reset(event=event) except CtapError as e: - if e.code == CtapError.ERR.USER_ACTION_TIMEOUT: + if e.code in ( + # Different keys respond with different errors here + CtapError.ERR.USER_ACTION_TIMEOUT, + CtapError.ERR.ACTION_TIMEOUT, + ): raise InactivityException() + raise self._info = self.ctap.get_info() self._token = None return RpcResponse(dict(), ["device_info"]) From 88fcffd068ada70fc6534b85687b433244b932b2 Mon Sep 17 00:00:00 2001 From: Elias Bonnici Date: Wed, 4 Sep 2024 17:46:48 +0200 Subject: [PATCH 2/7] Ensure search field is not hidden behind title --- lib/app/views/app_page.dart | 7 +++---- lib/app/views/keys.dart | 1 + lib/fido/views/passkeys_screen.dart | 20 ++++++++++++++++++++ lib/oath/views/oath_screen.dart | 20 ++++++++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/lib/app/views/app_page.dart b/lib/app/views/app_page.dart index f204637d..b1c76340 100755 --- a/lib/app/views/app_page.dart +++ b/lib/app/views/app_page.dart @@ -62,7 +62,6 @@ final _navKey = GlobalKey(); final _navExpandedKey = GlobalKey(); final _sliverTitleGlobalKey = GlobalKey(); final _sliverTitleWrapperGlobalKey = GlobalKey(); -final _headerSliverGlobalKey = GlobalKey(); final _detailsViewGlobalKey = GlobalKey(); final _mainContentGlobalKey = GlobalKey(); @@ -446,7 +445,7 @@ class _AppPageState extends ConsumerState { targetKey: _sliverTitleGlobalKey, controller: _sliverTitleController, subTargetKey: - widget.headerSliver != null ? _headerSliverGlobalKey : null, + widget.headerSliver != null ? headerSliverGlobalKey : null, subController: widget.headerSliver != null ? _headerSliverController : null, subAnchorKey: @@ -487,11 +486,11 @@ class _AppPageState extends ConsumerState { _sliverTitleScrollController, _headerSliverController.scrollDirection, _headerSliverController, - _headerSliverGlobalKey, + headerSliverGlobalKey, _sliverTitleWrapperGlobalKey); return Container( - key: _headerSliverGlobalKey, + key: headerSliverGlobalKey, child: widget.headerSliver); }, )) diff --git a/lib/app/views/keys.dart b/lib/app/views/keys.dart index 33f1e73c..1ef73f19 100644 --- a/lib/app/views/keys.dart +++ b/lib/app/views/keys.dart @@ -18,6 +18,7 @@ import 'package:flutter/material.dart'; // global keys final scaffoldGlobalKey = GlobalKey(); +final headerSliverGlobalKey = GlobalKey(); // This is global so we can access it from the global Ctrl+F shortcut. final searchField = GlobalKey(); diff --git a/lib/fido/views/passkeys_screen.dart b/lib/fido/views/passkeys_screen.dart index 09afe129..7deb9666 100644 --- a/lib/fido/views/passkeys_screen.dart +++ b/lib/fido/views/passkeys_screen.dart @@ -238,7 +238,26 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> { super.dispose(); } + void _scrollSearchField() { + // Ensures the search field is fully visible when in focus + final headerSliverContext = headerSliverGlobalKey.currentContext; + if (searchFocus.hasFocus && headerSliverContext != null) { + final scrollable = Scrollable.of(headerSliverContext); + if (scrollable.deltaToScrollOrigin.dy > 0) { + // Need delay to wait for ongoing scroll to finish + Future.delayed(const Duration(milliseconds: 100), () { + scrollable.position.animateTo( + 0, + duration: const Duration(milliseconds: 50), + curve: Curves.ease, + ); + }); + } + } + } + void _onFocusChange() { + _scrollSearchField(); setState(() {}); } @@ -518,6 +537,7 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> { ref .read(passkeysSearchProvider.notifier) .setFilter(value); + _scrollSearchField(); setState(() {}); }, textInputAction: TextInputAction.next, diff --git a/lib/oath/views/oath_screen.dart b/lib/oath/views/oath_screen.dart index e1927218..c97bfcec 100755 --- a/lib/oath/views/oath_screen.dart +++ b/lib/oath/views/oath_screen.dart @@ -154,7 +154,26 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> { super.dispose(); } + void _scrollSearchField() { + // Ensures the search field is fully visible when in focus + final headerSliverContext = headerSliverGlobalKey.currentContext; + if (searchFocus.hasFocus && headerSliverContext != null) { + final scrollable = Scrollable.of(headerSliverContext); + if (scrollable.deltaToScrollOrigin.dy > 0) { + // Need delay to wait for ongoing scroll to finish + Future.delayed(const Duration(milliseconds: 100), () { + scrollable.position.animateTo( + 0, + duration: const Duration(milliseconds: 50), + curve: Curves.ease, + ); + }); + } + } + } + void _onFocusChange() { + _scrollSearchField(); setState(() {}); } @@ -563,6 +582,7 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> { ref .read(accountsSearchProvider.notifier) .setFilter(value); + _scrollSearchField(); setState(() {}); }, textInputAction: TextInputAction.next, From 14d3a13fe5cdbf31ca039c527db57f44f4071f82 Mon Sep 17 00:00:00 2001 From: Elias Bonnici Date: Thu, 5 Sep 2024 13:52:05 +0200 Subject: [PATCH 3/7] Bump Flutter version This also removes a patch for flutter in the MacOS runner, since the issue is resolved in the newer flutter version. --- .github/workflows/env | 2 +- .github/workflows/macos.yml | 7 ------- macos_assemble.patch | 12 ------------ 3 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 macos_assemble.patch diff --git a/.github/workflows/env b/.github/workflows/env index c91c3513..5b14656c 100644 --- a/.github/workflows/env +++ b/.github/workflows/env @@ -1,2 +1,2 @@ -FLUTTER=3.24.1 +FLUTTER=3.24.2 PYVER=3.12.5 diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 5cc2e39d..42932db6 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -56,13 +56,6 @@ jobs: - run: flutter config --enable-macos-desktop - run: flutter --version - - name: Apply Flutter Patch - run: | - cd $FLUTTER_ROOT - git apply $GITHUB_WORKSPACE/macos_assemble.patch - env: - GITHUB_WORKSPACE: ${{ github.workspace }} - - name: Run lints/tests env: SKIP: ${{ steps.cache-helper.outputs.cache-hit == 'true' && 'mypy,flake8,black,bandit' || ''}} diff --git a/macos_assemble.patch b/macos_assemble.patch deleted file mode 100644 index 1db8932f..00000000 --- a/macos_assemble.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/packages/flutter_tools/bin/macos_assemble.sh b/packages/flutter_tools/bin/macos_assemble.sh -index 40c6a5051f..a7f05d9113 100755 ---- a/packages/flutter_tools/bin/macos_assemble.sh -+++ b/packages/flutter_tools/bin/macos_assemble.sh -@@ -222,6 +222,7 @@ EmbedFrameworks() { - - # Iterate through all .frameworks in native assets directory. - for native_asset in "${native_assets_path}"*.framework; do -+ [ -e "$native_asset" ] || continue # Skip when there are no matches. - # Codesign the framework inside the app bundle. - RunCommand codesign --force --verbose --sign "${EXPANDED_CODE_SIGN_IDENTITY}" -- "${xcode_frameworks_dir}/$(basename "$native_asset")" - done From 7565396df2634fe73d9f5c7eb50f88b468ae1841 Mon Sep 17 00:00:00 2001 From: Elias Bonnici Date: Thu, 5 Sep 2024 14:14:26 +0200 Subject: [PATCH 4/7] Increase vertical padding between search and passkeys --- lib/fido/views/passkeys_screen.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/fido/views/passkeys_screen.dart b/lib/fido/views/passkeys_screen.dart index 7deb9666..824fe119 100644 --- a/lib/fido/views/passkeys_screen.dart +++ b/lib/fido/views/passkeys_screen.dart @@ -607,7 +607,8 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> { builder: (context, ref, child) { final layout = ref.watch(passkeysLayoutProvider); return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), + padding: + const EdgeInsets.only(left: 10.0, right: 10.0, top: 8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ From 498dd939ec65c517eb0506c7edb370b9302221a4 Mon Sep 17 00:00:00 2001 From: Elias Bonnici Date: Thu, 5 Sep 2024 14:49:07 +0200 Subject: [PATCH 5/7] Disable `allowImplicitScrolling` --- lib/app/views/app_page.dart | 21 ++++++++++++++++++--- lib/fido/views/passkeys_screen.dart | 13 +++++-------- lib/oath/views/oath_screen.dart | 13 +++++-------- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/lib/app/views/app_page.dart b/lib/app/views/app_page.dart index b1c76340..741eb9fa 100755 --- a/lib/app/views/app_page.dart +++ b/lib/app/views/app_page.dart @@ -452,9 +452,12 @@ class _AppPageState extends ConsumerState { widget.headerSliver != null ? _sliverTitleWrapperGlobalKey : null, child: CustomScrollView( physics: isAndroid - ? const ClampingScrollPhysics( - parent: AlwaysScrollableScrollPhysics()) - : null, + ? const _NoImplicitScrollPhysics( + parent: ClampingScrollPhysics( + parent: AlwaysScrollableScrollPhysics(), + ), + ) + : const _NoImplicitScrollPhysics(), controller: _sliverTitleScrollController, key: _mainContentGlobalKey, slivers: [ @@ -1040,3 +1043,15 @@ class _SliverTitleDelegate extends SliverPersistentHeaderDelegate { @override bool shouldRebuild(_SliverTitleDelegate oldDelegate) => true; } + +class _NoImplicitScrollPhysics extends ScrollPhysics { + const _NoImplicitScrollPhysics({super.parent}); + + @override + bool get allowImplicitScrolling => false; + + @override + _NoImplicitScrollPhysics applyTo(ScrollPhysics? ancestor) { + return _NoImplicitScrollPhysics(parent: buildParent(ancestor)); + } +} diff --git a/lib/fido/views/passkeys_screen.dart b/lib/fido/views/passkeys_screen.dart index 824fe119..b1231088 100644 --- a/lib/fido/views/passkeys_screen.dart +++ b/lib/fido/views/passkeys_screen.dart @@ -244,14 +244,11 @@ class _FidoUnlockedPageState extends ConsumerState<_FidoUnlockedPage> { if (searchFocus.hasFocus && headerSliverContext != null) { final scrollable = Scrollable.of(headerSliverContext); if (scrollable.deltaToScrollOrigin.dy > 0) { - // Need delay to wait for ongoing scroll to finish - Future.delayed(const Duration(milliseconds: 100), () { - scrollable.position.animateTo( - 0, - duration: const Duration(milliseconds: 50), - curve: Curves.ease, - ); - }); + scrollable.position.animateTo( + 0, + duration: const Duration(milliseconds: 100), + curve: Curves.ease, + ); } } } diff --git a/lib/oath/views/oath_screen.dart b/lib/oath/views/oath_screen.dart index c97bfcec..9ac6af30 100755 --- a/lib/oath/views/oath_screen.dart +++ b/lib/oath/views/oath_screen.dart @@ -160,14 +160,11 @@ class _UnlockedViewState extends ConsumerState<_UnlockedView> { if (searchFocus.hasFocus && headerSliverContext != null) { final scrollable = Scrollable.of(headerSliverContext); if (scrollable.deltaToScrollOrigin.dy > 0) { - // Need delay to wait for ongoing scroll to finish - Future.delayed(const Duration(milliseconds: 100), () { - scrollable.position.animateTo( - 0, - duration: const Duration(milliseconds: 50), - curve: Curves.ease, - ); - }); + scrollable.position.animateTo( + 0, + duration: const Duration(milliseconds: 100), + curve: Curves.ease, + ); } } } From 8ad991f2026b51e6a4b590b4caedbd124646e278 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Fri, 6 Sep 2024 13:26:24 +0200 Subject: [PATCH 6/7] fix/add strings --- lib/l10n/app_de.arb | 13 +++++++++++++ lib/l10n/app_en.arb | 13 +++++++++++++ lib/l10n/app_fr.arb | 13 +++++++++++++ lib/l10n/app_ja.arb | 13 +++++++++++++ lib/l10n/app_pl.arb | 13 +++++++++++++ lib/l10n/app_vi.arb | 13 +++++++++++++ lib/oath/views/rename_account_dialog.dart | 2 +- 7 files changed, 79 insertions(+), 1 deletion(-) diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index c1636771..cad2577f 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -446,6 +446,12 @@ "s_rename_account": "Konto umbenennen", "l_rename_account_desc": "Bearbeiten Sie den Aussteller/Namen des Kontos", "s_account_renamed": "Konto umbenannt", + "l_rename_account_failed": null, + "@l_rename_account_failed": { + "placeholders": { + "message": {} + } + }, "p_rename_will_change_account_displayed": "Das ändert die Anzeige dieses Kontos in der Liste.", "s_delete_account": "Konto löschen", "l_delete_account_desc": "Löschen Sie das Konto von Ihrem YubiKey", @@ -915,6 +921,13 @@ "s_nfc_dialog_fido_rename_fingerprint": "Aktion: Fingerabdruck umbenennen", "s_nfc_dialog_fido_failure": "FIDO-Operation fehlgeschlagen", + "@_nfc": {}, + "s_nfc_ready_to_scan": null, + "s_nfc_scanning": null, + "s_nfc_tap_your_yubikey": null, + "l_nfc_failed_to_scan": null, + "s_nfc_done": null, + "@_ndef": {}, "p_ndef_set_otp": "OTP-Code wurde erfolgreich von Ihrem YubiKey in die Zwischenablage kopiert.", "p_ndef_set_password": "Passwort wurde erfolgreich von Ihrem YubiKey in die Zwischenablage kopiert.", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 3f24e4ef..52edfb69 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -446,6 +446,12 @@ "s_rename_account": "Rename account", "l_rename_account_desc": "Edit the issuer/name of the account", "s_account_renamed": "Account renamed", + "l_rename_account_failed": "Failed renaming account: {message}", + "@l_rename_account_failed": { + "placeholders": { + "message": {} + } + }, "p_rename_will_change_account_displayed": "This will change how the account is displayed in the list.", "s_delete_account": "Delete account", "l_delete_account_desc": "Remove the account from your YubiKey", @@ -915,6 +921,13 @@ "s_nfc_dialog_fido_rename_fingerprint": "Action: rename fingerprint", "s_nfc_dialog_fido_failure": "FIDO operation failed", + "@_nfc": {}, + "s_nfc_ready_to_scan": "Ready to scan", + "s_nfc_scanning": "Scanning\u2026", + "s_nfc_tap_your_yubikey": "Tap your YubiKey", + "l_nfc_failed_to_scan": "Failed to scan, try again", + "s_nfc_done": "Done", + "@_ndef": {}, "p_ndef_set_otp": "Successfully copied OTP code from YubiKey to clipboard.", "p_ndef_set_password": "Successfully copied password from YubiKey to clipboard.", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index a9fc5067..69764106 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -446,6 +446,12 @@ "s_rename_account": "Renommer compte", "l_rename_account_desc": "Modifier émetteur/nom du compte", "s_account_renamed": "Compte renommé", + "l_rename_account_failed": null, + "@l_rename_account_failed": { + "placeholders": { + "message": {} + } + }, "p_rename_will_change_account_displayed": "Cela modifiera l'affichage du compte dans la liste.", "s_delete_account": "Supprimer compte", "l_delete_account_desc": "Supprimer le compte de votre YubiKey", @@ -915,6 +921,13 @@ "s_nfc_dialog_fido_rename_fingerprint": "Action : renommer l'empreinte digitale", "s_nfc_dialog_fido_failure": "Échec de l'opération FIDO", + "@_nfc": {}, + "s_nfc_ready_to_scan": null, + "s_nfc_scanning": null, + "s_nfc_tap_your_yubikey": null, + "l_nfc_failed_to_scan": null, + "s_nfc_done": null, + "@_ndef": {}, "p_ndef_set_otp": "Code OTP copié de la YubiKey dans le presse-papiers.", "p_ndef_set_password": "Mot de passe copié de la YubiKey dans le presse-papiers.", diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index c0e0f1ab..adbbdd6f 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -446,6 +446,12 @@ "s_rename_account": "アカウント名を変更", "l_rename_account_desc": "アカウントの発行者/名前を編集", "s_account_renamed": "アカウントの名前が変更されました", + "l_rename_account_failed": null, + "@l_rename_account_failed": { + "placeholders": { + "message": {} + } + }, "p_rename_will_change_account_displayed": "これにより、リスト内のアカウントの表示が変更されます。", "s_delete_account": "アカウントを削除", "l_delete_account_desc": "YubiKeyからアカウントを削除", @@ -915,6 +921,13 @@ "s_nfc_dialog_fido_rename_fingerprint": "アクション: 指紋の名前を変更する", "s_nfc_dialog_fido_failure": "FIDO操作に失敗しました", + "@_nfc": {}, + "s_nfc_ready_to_scan": null, + "s_nfc_scanning": null, + "s_nfc_tap_your_yubikey": null, + "l_nfc_failed_to_scan": null, + "s_nfc_done": null, + "@_ndef": {}, "p_ndef_set_otp": "OTPコードがYubiKeyからクリップボードに正常にコピーされました。", "p_ndef_set_password": "パスワードがYubiKeyからクリップボードに正常にコピーされました。", diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index cf061df9..8a081ab1 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -446,6 +446,12 @@ "s_rename_account": "Zmień nazwę konta", "l_rename_account_desc": "Edytuj wydawcę/nazwę konta", "s_account_renamed": "Zmieniono nazwę konta", + "l_rename_account_failed": null, + "@l_rename_account_failed": { + "placeholders": { + "message": {} + } + }, "p_rename_will_change_account_displayed": "Spowoduje to zmianę sposobu wyświetlania konta na liście.", "s_delete_account": "Usuń konto", "l_delete_account_desc": "Usuń konto z klucza YubiKey", @@ -915,6 +921,13 @@ "s_nfc_dialog_fido_rename_fingerprint": null, "s_nfc_dialog_fido_failure": null, + "@_nfc": {}, + "s_nfc_ready_to_scan": null, + "s_nfc_scanning": null, + "s_nfc_tap_your_yubikey": null, + "l_nfc_failed_to_scan": null, + "s_nfc_done": null, + "@_ndef": {}, "p_ndef_set_otp": "OTP zostało skopiowane do schowka.", "p_ndef_set_password": "Hasło statyczne zostało skopiowane do schowka.", diff --git a/lib/l10n/app_vi.arb b/lib/l10n/app_vi.arb index b6c4e0c8..c2ac123a 100644 --- a/lib/l10n/app_vi.arb +++ b/lib/l10n/app_vi.arb @@ -446,6 +446,12 @@ "s_rename_account": "Đổi tên tài khoản", "l_rename_account_desc": "Chỉnh sửa nhà phát hành/tên của tài khoản", "s_account_renamed": "Tài khoản đã được đổi tên", + "l_rename_account_failed": null, + "@l_rename_account_failed": { + "placeholders": { + "message": {} + } + }, "p_rename_will_change_account_displayed": "Điều này sẽ thay đổi cách tài khoản được hiển thị trong danh sách.", "s_delete_account": "Xóa tài khoản", "l_delete_account_desc": "Xóa tài khoản khỏi YubiKey của bạn", @@ -915,6 +921,13 @@ "s_nfc_dialog_fido_rename_fingerprint": "Hành động: đổi tên dấu vân tay", "s_nfc_dialog_fido_failure": "Hành động FIDO thất bại", + "@_nfc": {}, + "s_nfc_ready_to_scan": null, + "s_nfc_scanning": null, + "s_nfc_tap_your_yubikey": null, + "l_nfc_failed_to_scan": null, + "s_nfc_done": null, + "@_ndef": {}, "p_ndef_set_otp": "Đã sao chép mã OTP từ YubiKey vào clipboard.", "p_ndef_set_password": "Đã sao chép mật khẩu từ YubiKey vào clipboard.", diff --git a/lib/oath/views/rename_account_dialog.dart b/lib/oath/views/rename_account_dialog.dart index bf6a26ce..c3eee142 100755 --- a/lib/oath/views/rename_account_dialog.dart +++ b/lib/oath/views/rename_account_dialog.dart @@ -104,7 +104,7 @@ class RenameAccountDialog extends ConsumerStatefulWidget { await withContext((context) async => showMessage( context, AppLocalizations.of(context)! - .l_account_add_failed(errorMessage), + .l_rename_account_failed(errorMessage), duration: const Duration(seconds: 4), )); return null; From 6b9f8e36337507d088701bf371b22b75a788c5b2 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Fri, 6 Sep 2024 13:37:54 +0200 Subject: [PATCH 7/7] update key for "Done" --- lib/l10n/app_de.arb | 2 +- lib/l10n/app_en.arb | 2 +- lib/l10n/app_fr.arb | 2 +- lib/l10n/app_ja.arb | 2 +- lib/l10n/app_pl.arb | 2 +- lib/l10n/app_vi.arb | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index cad2577f..427100e1 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -38,6 +38,7 @@ "s_calculate": "Berechnen", "s_import": "Importieren", "s_overwrite": "Überschreiben", + "s_done": null, "s_label": "Beschriftung", "s_name": "Name", "s_usb": "USB", @@ -926,7 +927,6 @@ "s_nfc_scanning": null, "s_nfc_tap_your_yubikey": null, "l_nfc_failed_to_scan": null, - "s_nfc_done": null, "@_ndef": {}, "p_ndef_set_otp": "OTP-Code wurde erfolgreich von Ihrem YubiKey in die Zwischenablage kopiert.", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 52edfb69..ca3546b2 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -38,6 +38,7 @@ "s_calculate": "Calculate", "s_import": "Import", "s_overwrite": "Overwrite", + "s_done": "Done", "s_label": "Label", "s_name": "Name", "s_usb": "USB", @@ -926,7 +927,6 @@ "s_nfc_scanning": "Scanning\u2026", "s_nfc_tap_your_yubikey": "Tap your YubiKey", "l_nfc_failed_to_scan": "Failed to scan, try again", - "s_nfc_done": "Done", "@_ndef": {}, "p_ndef_set_otp": "Successfully copied OTP code from YubiKey to clipboard.", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 69764106..b7f979e8 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -38,6 +38,7 @@ "s_calculate": "Calculer", "s_import": "Importer", "s_overwrite": "Écraser", + "s_done": null, "s_label": "Étiquette", "s_name": "Nom", "s_usb": "USB", @@ -926,7 +927,6 @@ "s_nfc_scanning": null, "s_nfc_tap_your_yubikey": null, "l_nfc_failed_to_scan": null, - "s_nfc_done": null, "@_ndef": {}, "p_ndef_set_otp": "Code OTP copié de la YubiKey dans le presse-papiers.", diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index adbbdd6f..be067bf5 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -38,6 +38,7 @@ "s_calculate": "計算", "s_import": "インポート", "s_overwrite": "上書き", + "s_done": null, "s_label": "ラベル", "s_name": "名前", "s_usb": "USB", @@ -926,7 +927,6 @@ "s_nfc_scanning": null, "s_nfc_tap_your_yubikey": null, "l_nfc_failed_to_scan": null, - "s_nfc_done": null, "@_ndef": {}, "p_ndef_set_otp": "OTPコードがYubiKeyからクリップボードに正常にコピーされました。", diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 8a081ab1..fe68b781 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -38,6 +38,7 @@ "s_calculate": "Oblicz", "s_import": "Importuj", "s_overwrite": "Nadpisz", + "s_done": null, "s_label": "Etykieta", "s_name": "Nazwa", "s_usb": "USB", @@ -926,7 +927,6 @@ "s_nfc_scanning": null, "s_nfc_tap_your_yubikey": null, "l_nfc_failed_to_scan": null, - "s_nfc_done": null, "@_ndef": {}, "p_ndef_set_otp": "OTP zostało skopiowane do schowka.", diff --git a/lib/l10n/app_vi.arb b/lib/l10n/app_vi.arb index c2ac123a..2a9c003c 100644 --- a/lib/l10n/app_vi.arb +++ b/lib/l10n/app_vi.arb @@ -38,6 +38,7 @@ "s_calculate": "Tính toán", "s_import": "Nhập khẩu", "s_overwrite": "Ghi đè", + "s_done": null, "s_label": "Nhãn", "s_name": "Tên", "s_usb": "USB", @@ -926,7 +927,6 @@ "s_nfc_scanning": null, "s_nfc_tap_your_yubikey": null, "l_nfc_failed_to_scan": null, - "s_nfc_done": null, "@_ndef": {}, "p_ndef_set_otp": "Đã sao chép mã OTP từ YubiKey vào clipboard.",