From d2fcb24d7900ae9dba35c93c4e55dc093d13f628 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Mon, 25 Nov 2024 20:47:20 +0100 Subject: [PATCH 01/44] Fix state updates for the lock and sort menu items Turns out I was a little too enthusiastically removing things in 9d383b85d8c5581f12a1a22407ce4615c4d499f3. The menu may not necessarily have been created yet in all cases. --- .../main/java/com/beemdevelopment/aegis/ui/MainActivity.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java index 97102017..87182888 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java @@ -920,6 +920,9 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene _menu = menu; getMenuInflater().inflate(R.menu.menu_main, menu); + updateLockIcon(); + updateSortCategoryMenu(); + MenuItem searchViewMenuItem = menu.findItem(R.id.mi_search); _searchView = (SearchView) searchViewMenuItem.getActionView(); _searchView.setMaxWidth(Integer.MAX_VALUE); From 503ce87c9115fb5c6abd7495ff50d3082f68674c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Mon, 25 Nov 2024 00:17:37 +0100 Subject: [PATCH 02/44] Improve search feature for better UX --- .../aegis/ui/MainActivity.java | 3 +++ .../aegis/ui/views/EntryAdapter.java | 23 ++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java index 97102017..2083a751 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java @@ -930,6 +930,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene _searchView.setOnCloseListener(() -> { boolean enabled = _submittedSearchQuery != null; _searchViewBackPressHandler.setEnabled(enabled); + _groupChip.setVisibility(_groups.isEmpty() ? View.GONE : View.VISIBLE); return false; }); @@ -963,6 +964,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene }); _searchView.setOnSearchClickListener(v -> { String query = _submittedSearchQuery != null ? _submittedSearchQuery : _pendingSearchQuery; + _groupChip.setVisibility(View.GONE); _searchView.setQuery(query, false); }); @@ -1028,6 +1030,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene } private void collapseSearchView() { + _groupChip.setVisibility(_groups.isEmpty() ? View.GONE : View.VISIBLE); _searchView.setQuery(null, false); _searchView.setIconified(true); } diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryAdapter.java b/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryAdapter.java index 480ba267..9fce5424 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryAdapter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryAdapter.java @@ -37,6 +37,7 @@ import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.vault.VaultGroup; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -196,6 +197,19 @@ public class EntryAdapter extends RecyclerView.Adapter String name = entry.getName().toLowerCase(); String note = entry.getNote().toLowerCase(); + if (_searchFilter != null) { + String[] tokens = _searchFilter.toLowerCase().split("\\s+"); + + // Return true if not all tokens match at least one of the relevant fields + return !Arrays.stream(tokens) + .allMatch(token -> + ((_searchBehaviorMask & Preferences.SEARCH_IN_ISSUER) != 0 && issuer.contains(token)) || + ((_searchBehaviorMask & Preferences.SEARCH_IN_NAME) != 0 && name.contains(token)) || + ((_searchBehaviorMask & Preferences.SEARCH_IN_NOTE) != 0 && note.contains(token)) || + ((_searchBehaviorMask & Preferences.SEARCH_IN_GROUPS) != 0 && doesAnyGroupMatchSearchFilter(groups, token)) + ); + } + if (!_groupFilter.isEmpty()) { if (groups.isEmpty() && !_groupFilter.contains(null)) { return true; @@ -205,14 +219,7 @@ public class EntryAdapter extends RecyclerView.Adapter } } - if (_searchFilter == null) { - return false; - } - - return ((_searchBehaviorMask & Preferences.SEARCH_IN_ISSUER) == 0 || !issuer.contains(_searchFilter)) - && ((_searchBehaviorMask & Preferences.SEARCH_IN_NAME) == 0 || !name.contains(_searchFilter)) - && ((_searchBehaviorMask & Preferences.SEARCH_IN_NOTE) == 0 || !note.contains(_searchFilter)) - && ((_searchBehaviorMask & Preferences.SEARCH_IN_GROUPS) == 0 || !doesAnyGroupMatchSearchFilter(entry.getGroups(), _searchFilter)); + return false; } private boolean doesAnyGroupMatchSearchFilter(Set entryGroupUUIDs, String searchFilter) { From f9ada479560558eb56a00c7f2ece928799e822b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Mon, 2 Dec 2024 17:38:28 +0100 Subject: [PATCH 03/44] Add fix for importing multiple entries --- .../main/java/com/beemdevelopment/aegis/ui/MainActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java index 2083a751..b0da5cbe 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java @@ -685,6 +685,10 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene if (entries.size() == 1) { startEditEntryActivityForNew(entries.get(0)); } else if (entries.size() > 1) { + for (VaultEntry entry: entries) { + _vaultManager.getVault().addEntry(entry); + } + if (saveAndBackupVault()) { Toast.makeText(this, getResources().getQuantityString(R.plurals.added_new_entries, entries.size(), entries.size()), Toast.LENGTH_LONG).show(); } From 3efe74d3752c00db6c023464d264c314f7611783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Mon, 2 Dec 2024 17:56:04 +0100 Subject: [PATCH 04/44] Reset selection state when changing groups --- .../main/java/com/beemdevelopment/aegis/ui/MainActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java index 97102017..bf510871 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java @@ -312,6 +312,10 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene chip.setOnCheckedChangeListener((group1, isChecked) -> { Set groupFilter = new HashSet<>(); + if (_actionMode != null) { + _actionMode.finish(); + } + setSaveChipVisibility(true); if (!isChecked) { From 51f656dd6b3df59e12a55a1055495038f02bef19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Mon, 2 Dec 2024 18:06:12 +0100 Subject: [PATCH 05/44] Make file name of exports consistent --- .../fragments/preferences/ImportExportPreferencesFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/ImportExportPreferencesFragment.java b/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/ImportExportPreferencesFragment.java index 36bf71f9..f544bf6f 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/ImportExportPreferencesFragment.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/ImportExportPreferencesFragment.java @@ -296,7 +296,7 @@ public class ImportExportPreferencesFragment extends PreferencesFragment { boolean encrypt = checkBoxEncrypt.isChecked(); try { VaultBackupManager.FileInfo fileInfo = getExportFileInfo(pos, encrypt); - file = File.createTempFile(fileInfo.getFilename() + "-", "." + fileInfo.getExtension(), getExportCacheDir()); + file = new File(getExportCacheDir(), fileInfo.toString()); } catch (IOException e) { e.printStackTrace(); Dialogs.showErrorDialog(requireContext(), R.string.exporting_vault_error, e); From 3a9e27bacbb4d3a3aa47a0a35fff6af0dbd47368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Mon, 2 Dec 2024 18:21:18 +0100 Subject: [PATCH 06/44] Improve contrast of next code color --- app/src/main/res/values/colors.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 38d45937..a71bdfbc 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -101,8 +101,8 @@ #F9A825 #518242 #d9e7cb - #FFB0B1B5 - #44464f + #9D9EA2 + #616371 @android:color/transparent From 170f626c9e9e8b7f67b2d33eeb27e1a6a0b0d519 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Mon, 2 Dec 2024 22:29:48 +0100 Subject: [PATCH 07/44] Update translations from Crowdin --- app/src/main/res/values-ca-rES/strings.xml | 2 +- app/src/main/res/values-de-rDE/strings.xml | 2 +- app/src/main/res/values-hu-rHU/strings.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index a9b669d9..2993a46a 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -355,7 +355,7 @@ Grup Nom del grup Edita els grups - Gestiona i elimina els grups aqui + Gestiona i elimina els grups aquí Reiniciar comptador d\'usos Reinicia el comptador d\'usos de totes les entrades Segur que vols reiniciar el comptador d\'us de cada entrada a 0? diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index ca804b87..d657c84c 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -37,7 +37,7 @@ Symbolpakete verwalten und importieren. Design Dynamische Farben - Overlay basierend auf den Farben deines Android-Designs anwenden + Design basierend auf den Systemfarben anpassen Darstellungsstil Sprache Symbole anzeigen diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index b5e2403d..ab1d4d98 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -65,7 +65,7 @@ Biztonsági mentési emlékeztető kikapcsolása Az emlékeztető kikapcsolása után az Aegis nem fogja jelezni hogy a változásokról készült-e biztonsági mentés. Ezzel az adatvesztést kockáztatja. Biztos, hogy kikapcsolja az emlékeztetőt? Biztonsági mentési stratégia - Verziószámok megtartása + Több verzió megtartása Egyszeri biztonsági mentés A kiválasztott biztonsági mentési stratégia nem megbízható és nem ajánlott. Az egyszeri biztonsági mentés meghibásodása az egyetlen biztonsági mentés elvesztéséhez vezethet. Biztonsági mentési stratégia kiválasztása From 0eb11945782f3cdf876978188ed25644c3e68c20 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Mon, 2 Dec 2024 22:35:13 +0100 Subject: [PATCH 08/44] Release v3.3.2 --- app/build.gradle | 4 ++-- app/src/main/assets/changelog.html | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a5d0d21c..cc554916 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,8 +28,8 @@ android { applicationId "${packageName}" minSdkVersion 21 targetSdkVersion 35 - versionCode 74 - versionName "3.3.1" + versionCode 75 + versionName "3.3.2" multiDexEnabled true buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\"" buildConfigField "String", "GIT_BRANCH", "\"${getGitBranch()}\"" diff --git a/app/src/main/assets/changelog.html b/app/src/main/assets/changelog.html index b3a7443f..bb803312 100644 --- a/app/src/main/assets/changelog.html +++ b/app/src/main/assets/changelog.html @@ -31,6 +31,19 @@
+

Version 3.3.2

+

New

+
    +
  • Find entries by searching in multiple fields simultaneously
  • +
+

Fixes

+
    +
  • Entries would not actually be added to the Aegis vault in some cases when importing from Google Authenticator export QR codes
  • +
  • The lock button was sometimes shown for unencrypted vaults
  • +
  • The sort category menu item did not always reflect the current sorting
  • +
  • The next code was not always easy to read because its color had low contrast with the background
  • +
  • Entry selection was not cancelled when changing the group filter
  • +

Version 3.3.1

Fixes

    From 6039cfa20e024f0059d5e206cdf686fa8447e0d1 Mon Sep 17 00:00:00 2001 From: cillyvms Date: Tue, 26 Nov 2024 01:05:20 +0100 Subject: [PATCH 09/44] Apply window insets to prevent UI elements from going behind system windows. --- .../aegis/helpers/ViewHelper.java | 26 +++++++++++++++++++ .../aegis/ui/AboutActivity.java | 16 ++++++++++++ .../aegis/ui/AssignIconsActivity.java | 2 ++ .../aegis/ui/EditEntryActivity.java | 2 ++ .../aegis/ui/GroupManagerActivity.java | 2 ++ .../aegis/ui/ImportEntriesActivity.java | 2 ++ .../aegis/ui/MainActivity.java | 2 ++ .../aegis/ui/PreferencesActivity.java | 2 ++ .../aegis/ui/ScannerActivity.java | 2 ++ .../aegis/ui/TransferEntriesActivity.java | 2 ++ .../AuditLogPreferencesFragment.java | 14 ++++++++++ .../preferences/IconPacksManagerFragment.java | 17 ++++++++++++ .../preferences/PreferencesFragment.java | 24 +++++++++++++++++ .../aegis/ui/views/EntryListView.java | 20 ++++++++++++++ app/src/main/res/layout/activity_about.xml | 1 + .../main/res/layout/fragment_audit_log.xml | 1 + .../res/layout/fragment_entry_list_view.xml | 1 + 17 files changed, 136 insertions(+) create mode 100644 app/src/main/java/com/beemdevelopment/aegis/helpers/ViewHelper.java diff --git a/app/src/main/java/com/beemdevelopment/aegis/helpers/ViewHelper.java b/app/src/main/java/com/beemdevelopment/aegis/helpers/ViewHelper.java new file mode 100644 index 00000000..910aae2f --- /dev/null +++ b/app/src/main/java/com/beemdevelopment/aegis/helpers/ViewHelper.java @@ -0,0 +1,26 @@ +package com.beemdevelopment.aegis.helpers; + +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +import com.google.android.material.appbar.AppBarLayout; + +public class ViewHelper { + private ViewHelper() { + + } + + public static void setupAppBarInsets(AppBarLayout appBar) { + ViewCompat.setOnApplyWindowInsetsListener(appBar, (targetView, windowInsets) -> { + Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout()); + targetView.setPadding( + insets.left, + insets.top, + insets.right, + 0 + ); + return WindowInsetsCompat.CONSUMED; + }); + } +} diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/AboutActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/AboutActivity.java index c9eee550..4b974b68 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/AboutActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/AboutActivity.java @@ -13,11 +13,15 @@ import android.widget.Toast; import androidx.annotation.AttrRes; import androidx.annotation.StringRes; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; import com.beemdevelopment.aegis.BuildConfig; import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.ui.dialogs.ChangelogDialog; import com.beemdevelopment.aegis.ui.dialogs.LicenseDialog; +import com.beemdevelopment.aegis.helpers.ViewHelper; import com.google.android.material.color.MaterialColors; public class AboutActivity extends AegisActivity { @@ -39,6 +43,7 @@ public class AboutActivity extends AegisActivity { setContentView(R.layout.activity_about); setSupportActionBar(findViewById(R.id.toolbar)); + ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout)); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); @@ -90,6 +95,17 @@ public class AboutActivity extends AegisActivity { .setTheme(_themeHelper.getConfiguredTheme()) .show(getSupportFragmentManager(), null); }); + + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.about_scroll_view), (targetView, windowInsets) -> { + Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout()); + targetView.setPadding( + 0, + 0, + 0, + insets.bottom + ); + return WindowInsetsCompat.CONSUMED; + }); } private static String getCurrentAppVersion() { diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/AssignIconsActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/AssignIconsActivity.java index f049f70d..024f9200 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/AssignIconsActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/AssignIconsActivity.java @@ -25,6 +25,7 @@ import com.beemdevelopment.aegis.ui.models.AssignIconEntry; import com.beemdevelopment.aegis.ui.views.AssignIconAdapter; import com.beemdevelopment.aegis.ui.views.IconAdapter; import com.beemdevelopment.aegis.util.IOUtils; +import com.beemdevelopment.aegis.helpers.ViewHelper; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.vault.VaultEntryIcon; import com.bumptech.glide.Glide; @@ -61,6 +62,7 @@ public class AssignIconsActivity extends AegisActivity implements AssignIconAdap setContentView(R.layout.activity_assign_icons); setSupportActionBar(findViewById(R.id.toolbar)); + ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout)); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java index 68f3db7a..086559de 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java @@ -59,6 +59,7 @@ import com.beemdevelopment.aegis.ui.tasks.ImportFileTask; import com.beemdevelopment.aegis.ui.views.IconAdapter; import com.beemdevelopment.aegis.util.Cloner; import com.beemdevelopment.aegis.util.IOUtils; +import com.beemdevelopment.aegis.helpers.ViewHelper; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.vault.VaultEntryIcon; import com.beemdevelopment.aegis.vault.VaultGroup; @@ -164,6 +165,7 @@ public class EditEntryActivity extends AegisActivity { } setContentView(R.layout.activity_edit_entry); setSupportActionBar(findViewById(R.id.toolbar)); + ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout)); _groups = _vaultManager.getVault().getGroups(); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/GroupManagerActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/GroupManagerActivity.java index b2872e72..4c29dea2 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/GroupManagerActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/GroupManagerActivity.java @@ -15,6 +15,7 @@ import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.ui.dialogs.Dialogs; import com.beemdevelopment.aegis.ui.views.GroupAdapter; import com.beemdevelopment.aegis.util.Cloner; +import com.beemdevelopment.aegis.helpers.ViewHelper; import com.beemdevelopment.aegis.vault.VaultGroup; import com.google.android.material.dialog.MaterialAlertDialogBuilder; @@ -39,6 +40,7 @@ public class GroupManagerActivity extends AegisActivity implements GroupAdapter. } setContentView(R.layout.activity_groups); setSupportActionBar(findViewById(R.id.toolbar)); + ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout)); if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java index 54cf675e..0bf70b36 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java @@ -24,6 +24,7 @@ import com.beemdevelopment.aegis.ui.models.ImportEntry; import com.beemdevelopment.aegis.ui.tasks.RootShellTask; import com.beemdevelopment.aegis.ui.views.ImportEntriesAdapter; import com.beemdevelopment.aegis.util.UUIDMap; +import com.beemdevelopment.aegis.helpers.ViewHelper; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.vault.VaultGroup; import com.beemdevelopment.aegis.vault.VaultRepository; @@ -58,6 +59,7 @@ public class ImportEntriesActivity extends AegisActivity { } setContentView(R.layout.activity_import_entries); setSupportActionBar(findViewById(R.id.toolbar)); + ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout)); _view = findViewById(R.id.importEntriesRootView); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java index 97102017..13d82f66 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java @@ -59,6 +59,7 @@ import com.beemdevelopment.aegis.ui.tasks.QrDecodeTask; import com.beemdevelopment.aegis.ui.views.EntryListView; import com.beemdevelopment.aegis.util.TimeUtils; import com.beemdevelopment.aegis.util.UUIDMap; +import com.beemdevelopment.aegis.helpers.ViewHelper; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.vault.VaultFile; import com.beemdevelopment.aegis.vault.VaultGroup; @@ -183,6 +184,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setSupportActionBar(findViewById(R.id.toolbar)); + ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout)); _loaded = false; _isDPadPressed = false; _isDoingIntro = false; diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesActivity.java index e4d55919..1e7dff67 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/PreferencesActivity.java @@ -13,6 +13,7 @@ import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.ui.fragments.preferences.AppearancePreferencesFragment; import com.beemdevelopment.aegis.ui.fragments.preferences.MainPreferencesFragment; import com.beemdevelopment.aegis.ui.fragments.preferences.PreferencesFragment; +import com.beemdevelopment.aegis.helpers.ViewHelper; public class PreferencesActivity extends AegisActivity implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { @@ -27,6 +28,7 @@ public class PreferencesActivity extends AegisActivity implements } setContentView(R.layout.activity_preferences); setSupportActionBar(findViewById(R.id.toolbar)); + ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout)); getSupportFragmentManager() .registerFragmentLifecycleCallbacks(new FragmentResumeListener(), true); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/ScannerActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/ScannerActivity.java index e98a2ca3..cc0d6095 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/ScannerActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/ScannerActivity.java @@ -22,6 +22,7 @@ import com.beemdevelopment.aegis.helpers.QrCodeAnalyzer; import com.beemdevelopment.aegis.otp.GoogleAuthInfo; import com.beemdevelopment.aegis.otp.GoogleAuthInfoException; import com.beemdevelopment.aegis.ui.dialogs.Dialogs; +import com.beemdevelopment.aegis.helpers.ViewHelper; import com.beemdevelopment.aegis.vault.VaultEntry; import com.google.common.util.concurrent.ListenableFuture; import com.google.zxing.Result; @@ -56,6 +57,7 @@ public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Lis } setContentView(R.layout.activity_scanner); setSupportActionBar(findViewById(R.id.toolbar)); + ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout)); _entries = new ArrayList<>(); _lenses = new ArrayList<>(); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/TransferEntriesActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/TransferEntriesActivity.java index a0e81849..a4deae57 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/TransferEntriesActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/TransferEntriesActivity.java @@ -28,6 +28,7 @@ import com.beemdevelopment.aegis.otp.GoogleAuthInfo; import com.beemdevelopment.aegis.otp.GoogleAuthInfoException; import com.beemdevelopment.aegis.otp.Transferable; import com.beemdevelopment.aegis.ui.dialogs.Dialogs; +import com.beemdevelopment.aegis.helpers.ViewHelper; import com.google.android.material.color.MaterialColors; import com.google.android.material.imageview.ShapeableImageView; import com.google.zxing.WriterException; @@ -55,6 +56,7 @@ public class TransferEntriesActivity extends AegisActivity { } setContentView(R.layout.activity_share_entry); setSupportActionBar(findViewById(R.id.toolbar)); + ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout)); _qrImage = findViewById(R.id.ivQrCode); _description = findViewById(R.id.tvDescription); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/AuditLogPreferencesFragment.java b/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/AuditLogPreferencesFragment.java index daa722a8..8199dfa1 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/AuditLogPreferencesFragment.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/AuditLogPreferencesFragment.java @@ -6,6 +6,9 @@ import android.view.View; import android.widget.LinearLayout; import androidx.annotation.NonNull; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.LiveData; import androidx.recyclerview.widget.LinearLayoutManager; @@ -58,6 +61,17 @@ public class AuditLogPreferencesFragment extends Fragment { _auditLogRecyclerView.setAdapter(_adapter); _auditLogRecyclerView.setNestedScrollingEnabled(false); + ViewCompat.setOnApplyWindowInsetsListener(_auditLogRecyclerView, (targetView, windowInsets) -> { + Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout()); + targetView.setPadding( + 0, + 0, + 0, + insets.bottom + ); + return WindowInsetsCompat.CONSUMED; + }); + entries.observe(getViewLifecycleOwner(), entries1 -> { _noAuditLogsView.setVisibility(entries1.isEmpty() ? View.VISIBLE : View.GONE); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/IconPacksManagerFragment.java b/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/IconPacksManagerFragment.java index 0b23328e..a95713a1 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/IconPacksManagerFragment.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/IconPacksManagerFragment.java @@ -6,6 +6,7 @@ import android.net.Uri; import android.os.Bundle; import android.text.method.LinkMovementMethod; import android.view.View; +import android.view.ViewGroup.MarginLayoutParams; import android.view.animation.Animation; import android.widget.LinearLayout; import android.widget.TextView; @@ -14,6 +15,9 @@ import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -67,6 +71,19 @@ public class IconPacksManagerFragment extends Fragment implements IconPackAdapte fab.setOnClickListener(v -> startImportIconPack()); _fabScrollHelper = new FabScrollHelper(fab); + final MarginLayoutParams fabInitialMargin = (MarginLayoutParams) fab.getLayoutParams(); + ViewCompat.setOnApplyWindowInsetsListener(fab, (targetView, windowInsets) -> { + Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout()); + + MarginLayoutParams marginParams = (MarginLayoutParams) targetView.getLayoutParams(); + marginParams.leftMargin = fabInitialMargin.leftMargin + insets.left; + marginParams.bottomMargin = fabInitialMargin.bottomMargin + insets.bottom; + marginParams.rightMargin = fabInitialMargin.rightMargin + insets.right; + targetView.setLayoutParams(marginParams); + + return WindowInsetsCompat.CONSUMED; + }); + _noIconPacksView = view.findViewById(R.id.vEmptyList); ((TextView) view.findViewById(R.id.txt_no_icon_packs)).setMovementMethod(LinkMovementMethod.getInstance()); _adapter = new IconPackAdapter(this); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/PreferencesFragment.java b/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/PreferencesFragment.java index 367c32e1..63069160 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/PreferencesFragment.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/PreferencesFragment.java @@ -1,13 +1,20 @@ package com.beemdevelopment.aegis.ui.fragments.preferences; import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.ViewGroup; import android.view.animation.Animation; import androidx.annotation.CallSuper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import androidx.recyclerview.widget.RecyclerView; import com.beemdevelopment.aegis.Preferences; import com.beemdevelopment.aegis.R; @@ -61,6 +68,23 @@ public abstract class PreferencesFragment extends PreferenceFragmentCompat { return super.onCreateAnimation(transit, enter, nextAnim); } + @NonNull + @Override + public RecyclerView onCreateRecyclerView(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent, @Nullable Bundle savedInstanceState) { + RecyclerView recyclerView = super.onCreateRecyclerView(inflater, parent, savedInstanceState); + ViewCompat.setOnApplyWindowInsetsListener(recyclerView, (targetView, windowInsets) -> { + Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout()); + targetView.setPadding( + 0, + 0, + 0, + insets.bottom + ); + return WindowInsetsCompat.CONSUMED; + }); + return recyclerView; + } + protected boolean saveAndBackupVault() { try { _vaultManager.saveAndBackup(); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryListView.java b/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryListView.java index 500198c0..3d359290 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryListView.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryListView.java @@ -19,6 +19,9 @@ import androidx.annotation.AttrRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StyleRes; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.ItemTouchHelper; @@ -149,6 +152,23 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { } }); + final int rvInitialPaddingLeft = _recyclerView.getPaddingLeft(); + final int rvInitialPaddingTop = _recyclerView.getPaddingTop(); + final int rvInitialPaddingRight = _recyclerView.getPaddingRight(); + final int rvInitialPaddingBottom = _recyclerView.getPaddingBottom(); + + ViewCompat.setOnApplyWindowInsetsListener(_recyclerView, (targetView, windowInsets) -> { + Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout()); + // left and right padding seems to be handled by fitsSystemWindows="true" on the CoordinatorLayout in activity_main.xml + targetView.setPadding( + rvInitialPaddingLeft, + rvInitialPaddingTop, + rvInitialPaddingRight, + rvInitialPaddingBottom + insets.bottom + ); + return WindowInsetsCompat.CONSUMED; + }); + _emptyStateView = view.findViewById(R.id.vEmptyList); return view; } diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 280d52d5..d4b17d0b 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -17,6 +17,7 @@ android:layout_height="?attr/actionBarSize" /> diff --git a/app/src/main/res/layout/fragment_entry_list_view.xml b/app/src/main/res/layout/fragment_entry_list_view.xml index eaacfb4b..4f4fc0e3 100644 --- a/app/src/main/res/layout/fragment_entry_list_view.xml +++ b/app/src/main/res/layout/fragment_entry_list_view.xml @@ -20,6 +20,7 @@ android:paddingHorizontal="8dp" android:scrollbars="vertical" android:scrollbarStyle="outsideOverlay" + android:clipToPadding="false" android:id="@+id/rvKeyProfiles" android:layout_weight="1"/> From aec16f22c10d514378780c0f104f466146549150 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Fri, 20 Dec 2024 15:36:23 +0100 Subject: [PATCH 10/44] Update reactivecircus/android-emulator-runner Required for the ubuntu-latest switch to ubuntu-24.04 --- .github/workflows/build-app-workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-app-workflow.yaml b/.github/workflows/build-app-workflow.yaml index d3c55f8e..ab511ab7 100644 --- a/.github/workflows/build-app-workflow.yaml +++ b/.github/workflows/build-app-workflow.yaml @@ -35,7 +35,7 @@ jobs: sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - name: Tests - uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 + uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d with: api-level: 31 arch: x86_64 From 19a77209d8f75cb9d491a7fdaf4cdcd6f74547b2 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Fri, 20 Dec 2024 15:04:26 +0100 Subject: [PATCH 11/44] Store service name as issuer and tolerate spaces in secret for 2FAS --- .../aegis/importers/TwoFASImporter.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/TwoFASImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/TwoFASImporter.java index e618bf59..f0387afb 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/TwoFASImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/TwoFASImporter.java @@ -4,9 +4,9 @@ import android.content.Context; import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.crypto.CryptoUtils; -import com.beemdevelopment.aegis.encoding.Base32; import com.beemdevelopment.aegis.encoding.Base64; import com.beemdevelopment.aegis.encoding.EncodingException; +import com.beemdevelopment.aegis.otp.GoogleAuthInfo; import com.beemdevelopment.aegis.otp.HotpInfo; import com.beemdevelopment.aegis.otp.OtpInfo; import com.beemdevelopment.aegis.otp.OtpInfoException; @@ -16,6 +16,7 @@ import com.beemdevelopment.aegis.ui.dialogs.Dialogs; import com.beemdevelopment.aegis.util.IOUtils; import com.beemdevelopment.aegis.util.JsonUtils; import com.beemdevelopment.aegis.vault.VaultEntry; +import com.google.common.base.Strings; import com.topjohnwu.superuser.io.SuFile; import org.json.JSONArray; @@ -173,9 +174,12 @@ public class TwoFASImporter extends DatabaseImporter { private static VaultEntry convertEntry(JSONObject obj) throws DatabaseImporterEntryException { try { - byte[] secret = Base32.decode(obj.getString("secret")); + byte[] secret = GoogleAuthInfo.parseSecret(obj.getString("secret")); JSONObject info = obj.getJSONObject("otp"); - String issuer = info.optString("issuer"); + String issuer = obj.optString("name"); + if (Strings.isNullOrEmpty(issuer)) { + issuer = info.optString("issuer"); + } String name = info.optString("account"); int digits = info.optInt("digits", TotpInfo.DEFAULT_DIGITS); String algorithm = info.optString("algorithm", TotpInfo.DEFAULT_ALGORITHM); From 05a415bb38fbe9366a1ead7f494aa28513c08113 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Tue, 31 Dec 2024 19:44:52 +0100 Subject: [PATCH 12/44] Only run the scheduled codeql job on the upstream repo --- .github/workflows/codeql-analysis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d4570016..b575535b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -14,6 +14,7 @@ jobs: actions: read contents: read security-events: write + if: github.event_name != 'schedule' || github.repository == 'beemdevelopment/Aegis' steps: - name: Checkout uses: actions/checkout@v4 From fe8b638818d3bdab6fe386ce6380cfaa829d5aa3 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Thu, 2 Jan 2025 21:46:57 +0100 Subject: [PATCH 13/44] Set largeHeap to true in AndroidManifest This is a temporary measure to help users who are stuck in a situation where they run into OOM conditions due to large icons in their vault file. --- app/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d3ea78bb..9339e659 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,6 +27,7 @@ android:icon="@mipmap/${iconName}" android:label="Aegis" android:supportsRtl="true" + android:largeHeap="true" android:theme="@style/Theme.Aegis.Launch" tools:targetApi="tiramisu"> Date: Thu, 2 Jan 2025 22:01:35 +0100 Subject: [PATCH 14/44] Update translations from Crowdin --- app/src/main/res/values-gl-rES/strings.xml | 61 +++++++++++++-- app/src/main/res/values-in-rID/strings.xml | 91 +++++++++++++++------- app/src/main/res/values-it-rIT/strings.xml | 10 +++ app/src/main/res/values-sv-rSE/strings.xml | 10 +++ app/src/main/res/values-zh-rTW/strings.xml | 5 ++ 5 files changed, 143 insertions(+), 34 deletions(-) diff --git a/app/src/main/res/values-gl-rES/strings.xml b/app/src/main/res/values-gl-rES/strings.xml index fccaa629..3e4310f1 100644 --- a/app/src/main/res/values-gl-rES/strings.xml +++ b/app/src/main/res/values-gl-rES/strings.xml @@ -10,6 +10,7 @@ Restablecer icona predeterminada Desbotar Gardar + Todo Provedor PIN (4–16 cifras) PIN (4 cifras) @@ -39,13 +40,19 @@ Aplica unha superposición baseada nas cores do teu tema de Android Modo de visualización Idioma - Amosar iconas - Amosar iconas ao lado de cada entrada + Mostrar iconas + Mostra iconas ao lado de cada entrada Agrupación dos díxitos do código Escolle o número de díxitos polos que agrupar os códigos Mostrar o nome da conta + Mostrar código seguinte + Xera e amosa o seguinte código antes de tempo + Indicar que os códigos van caducar + Cambia a cor dos códigos e fainos titilar cando estean a piques de caducar + Cambia a cor dos códigos cando estean a piques de caducar Mostrar o nome da conta só cando sexa necesario - Mostrar nomes de conta só cando teñan o mesmo emisor. Os demáis nomes de conta ocultaranse. + Mostrar nomes de conta só cando teñan o mesmo provedor. Os demáis nomes de conta ocultaranse. + Este axuste está anulado polo modo de visualización de mosaico. O nome da conta mostrarase debaixo do provedor. Importar desde un ficheiro Importar tokens desde un ficheiro Copias de seguridade na nube de Android @@ -57,7 +64,14 @@ Mostra un recordatorio para facer a copia de seguridade do almacén, no caso de que non fixeras ningunha copia dos teus últimos cambios. Desactivar recordatorio da copia de seguridade Se desactivas este recordatorio, Aegis non che dirá se hai cambios sen gardar ou non nas copias de seguridade, polo que estarás no risco de perder o acceso aos teus tokens. Tes a certeza de que queres desactivar o recordatorio? + Estratexia da copia de seguridade + Manter certo número de versións + Copia de seguridade única + A estratexia escollida non é fiable nin recomendable. Un único fallo ao facer a copia de seguridade pode levar a que quedes sen a única copia que tiveras. + Escolle unha estratexia para a copia de seguridade + Localización da copia de seguridade As copias de seguridade gardaranse en + A copia de seguridade gardarase en Executar copia de seguridade Lanza manualmente unha copia de seguridade Número de versións a manter @@ -102,6 +116,12 @@ Cifra o almacén e permite desbloquealo mediante un contrasinal ou por biometría Desbloqueo biométrico Permite a autenticación mediante biometría para desbloquear o almacén + Buscar en: %s + Buscar nos seguintes campos + Nome + Provedor + Nota + Grupos Cambiar contrasinal Establece un novo contrasinal co que desbloquear o teu almacén Non hai ningún evento rexistrado @@ -121,6 +141,7 @@ Fallo de desbloqueo do almacén (biometría) Houbo un intento errado de desbloquear o almacén mediante datos biométricos Tipo de evento descoñecido + (borrado) Hoxe ás %1$s %1$s ás %2$s Cifrar o almacén @@ -189,6 +210,9 @@ Editar Seleccionar todo Asignar iconas + Asignar a un grupo + Escolle o grupo ao que queiras asignar os elementos seleccionados. + Escolle o grupo Marcar como favorito Desmarcar como favorito ERRO @@ -206,6 +230,7 @@ Lendo ficheiro Pedindo acceso root Analizando código QR + Analizando código QR %1$d/%2$d (%3$s) Engadida %d nova entrada ao almacén Engadidas %d novas entradas ao almacén @@ -231,6 +256,7 @@ Copiado Copiáronse os erros no portapapeis Versión copiada no portapapeis + Este campo é obrigatorio Ocorreu un erro Ocorreu un erro ao intentar desbloquear o almacén Ocorreu un erro ao intentar desbloquear o almacén. O ficheiro do almacén podería estar corrompido. @@ -294,6 +320,10 @@ Detectouse una exportación de Google Authenticator incompleta Faltan algúns códigos QR na importación. Os seguintes códigos non se atoparon:\n\n%s\n\nPodes continuar importando esta exportación parcial, pero o recomendable é volvelo a intentar con tódolos códigos QR para que non te arrisques a perder o acceso a ningún token. • código QR %d + + Importar %d token de tódolos xeitos + Importar %d tokens de tódolos xeitos + Fallou a importación do exportado con Google Authenticator A exportación contén información sobre un lote non relacionado. Intenta importar 1 lote de cada vez. Polo tanto, non se pode importar ningún token @@ -312,8 +342,8 @@ Nome Sen grupo Ordenar - Emisor (A a Z) - Emisor (Z a A) + Provedor (A a Z) + Provedor (Z a A) Conta (A a Z) Conta (Z a A) Contador de usos @@ -336,6 +366,7 @@ Minimizar ao copiar Minimiza a aplicación despois de copiar un token Copiar códigos no portapapeis + Comportamento da busca Conxelar tokens ao premelos Pausa a actualización automática dos tokens ao premer neles. Os tokens non se actualizarán mentres teñan o foco. Require \"Resaltar tokens ao premelos\" ou \"Tocar para mostrar\". Introduce o teu contrasinal para activar o teclado do PIN. Ten en conta que isto só funciona se o teu contrasinal consiste só de números @@ -352,7 +383,7 @@ Compacto Pequeno Mosaico - Emisor descoñecido + Provedor descoñecido Nome de conta descoñecido Aegis non puido importar %d token. Este token omitirase. Preme en \"detalles\" para ver máis información sobre o erro. @@ -361,6 +392,7 @@ Non se puido procesar o enlace profundo Non se puido ler e procesar o código QR do ficheiro: %s. Non se puido procesar o texto compartido como OTP + Non se puideron ler e procesar algúns dos códigos QR. Só se importarán %1$d/%2$d elementos. Non se puido xerar o código QR Seleccionar imaxe Seleccionar icona @@ -391,7 +423,16 @@ Aegis depende de que a hora do sistema estea sincronizada para poder xerar códigos correctos. Unha desviación de tan só uns poucos segundos pode resultar en que os códigos sexan incorrectos. Semella que o teu dispositivo non está configurado para sincronizar automaticamente a hora. Queres configuralo agora? Non me avises máis. Sei o que fago. Atopouse un código QR non relacionado. Proba a reiniciar o escáner. + + %1$d/%2$d código QR escaneado + %1$d/%2$d códigos QR escaneados + + Esperábase o código QR nº %1$d, pero escaneouse o nº %2$d A copia de seguridade do almacén fallou recentemente + Un intento de facer unha copia de seguridade do almacén usando %1$s fallou debido a algún erro. A copia de seguridade intentouse %2$s. Comproba os axustes da copia de seguridade para asegurarte de que poidan completar correctamente. + + Un recente intento de copia de seguridade utilizando %1$s fallou porque Aegis non tiña permiso de escritura no destino da copia de seguridade. A copia de seguridade intentouse %2$s. Este erro pode ocorrer se moviches ou renomeaches o destino ou se fai pouco que recuperaches Aegis desde unha copia de seguridade. Volve a configurar o destino da copia de seguridade. + Copias de seguridade automáticas de Aegis Copias de seguridade na nube de Android A última copia de seguridade está desactualizada (%s) @@ -464,7 +505,11 @@ Proporciona un ficheiro de copia de seguridade ou de exportación de Bitwarden. Non se admiten os ficheiros cifrados. Proporciona unha copia de /data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml, localizado no directorio do almacenamento interno de Battle.net Authenticator. Proporciona unha copia de /data/data/com.duosecurity.duomobile/files/duokit/accounts.json, localizado no directorio do almacenamento interno de DUO. + Proporciona un ficheiro de exportación de Ente Auth. Polo momento só se admiten ficheiros sen cifrar. + FreeOTP 2: Proporciona unha copia de seguridade.\nFreeOTP 1.x: Proporciona unha copia de /data/data/org.fedorahosted.freeotp/shared_prefs/tokens.xml, localizado no directorio do almacenamento interno de FreeOTP. Proporciona un ficheiro de exportación de FreeOTP+. + Compatibilidade con FreeOTP 2 + Hai varios problemas en FreeOTP 2 que poden provocar copias de seguridade corrompidas. Aegis intentará recuperar o máximo número de elementos posible, pero pode que haxa algúns, ou incluso todos, que non se poidan importar. Só se admiten ficheiros de base de datos de Google Authenticator v5.10 e anteriores.\n\nProporciona unha copia de /data/data/com.google.android.apps.authenticator2/databases/databases, localizado no directorio do almacenamento interno de Google Authenticator. Proporciona unha copia de /data/data/com.azure.authenticator/databases/PhoneFactor, localizado no directorio do almacenamento interno de Microsoft Authenticator. Proporciona un ficheiro de texto plano cunha URI de Google Authenticator en cada liña. @@ -487,8 +532,8 @@ Un toque Dobre toque Oculto - Ao lado do emisor - Debaixo do emisor + Ao lado do provedor + Debaixo do provedor fai %d segundo fai %d segundos diff --git a/app/src/main/res/values-in-rID/strings.xml b/app/src/main/res/values-in-rID/strings.xml index 020eb9f8..ec3a2f80 100644 --- a/app/src/main/res/values-in-rID/strings.xml +++ b/app/src/main/res/values-in-rID/strings.xml @@ -3,13 +3,14 @@ Pengaturan Tentang Hapus - Kirim - Mengedit ikon - Setel ulang jumlah penggunaan - Apakah Anda yakin ingin mengatur jumlah penggunaan entri ini menjadi 0? - Pulihkan ikon baku + Transfer + Ubah ikon + Reset jumlah penggunaan + Apakah Anda yakin ingin mengatur jumlah penggunaan entri ini ke 0? + Pulihkan ikon bawaan Buang Simpan + Semua Penerbit PIN (4–16 digit) PIN (4 digit) @@ -44,52 +45,64 @@ Pengelompokan digit kode Pilih jumlah digit untuk mengelompokkan kode berdasarkan Tampilkan nama akun + Tampilkan kode selanjutnya + Hasilkan dan tampilkan kode berikutnya lebih awal + Tunjukkan kapan kode akan kedaluwarsa + Ubah warna kode dan buat kode tersebut berkedip ketika akan kedaluwarsa + Ubah warna kode saat kode akan kedaluwarsa Hanya tampilkan nama akun jika diperlukan Hanya tampilkan nama akun ketika mereka memiliki penerbit yang sama. Nama akun lain akan disembunyikan. - Pengaturan ini digantikan oleh mode tampilan ubin. Nama akun akan selalu ditampilkan di bawah penerbit. - Impor berkas + Pengaturan ini digantikan oleh mode tampilan kotak. Nama akun akan ditampilkan di bawah penerbit. + Impor dari berkas Impor token dari berkas Pencadangan awan Android - Bolehkan sistem pencadangan awan Android untuk menyertakan brankas Aegis di pencadangan mereka. Ini hanya didukung untuk brankas terenkripsi. - Pencadangan perangkat-ke-perangkat (D2D) selalu diperbolehkan, terlepas dari setelan di atas + Izinkan sistem pencadangan awan Android untuk menyertakan brankas Aegis dalam pencadangannya. Ini hanya didukung untuk brankas terenkripsi. + Pencadangan perangkat-ke-perangkat (D2D) selalu diizinkan, terlepas dari pengaturan di atas. Otomatis cadangkan brankas - Secara otomatis membuat cadangan vault di penyimpanan eksternal saat ada perubahan. Ini hanya didukung untuk brankas terenkripsi. - Pengingat backup + Secara otomatis membuat cadangan brankas pada penyimpanan eksternal ketika ada perubahan. Ini hanya didukung untuk brankas terenkripsi. + Pengingat pencadangan Tampilkan pengingat untuk mencadangkan cadangan jika Anda belum mencadangkan perubahan terakhir. - Menonaktifkan pengingat cadangan + Menonaktifkan pengingat pencadangan Dengan menonaktifkan pengingat ini, Aegis tidak akan memberi tahu Anda apakah Anda memiliki perubahan yang belum dicadangkan atau tidak. Hal ini membuat Anda berisiko kehilangan akses ke token Anda. Apakah Anda yakin ingin menonaktifkan pengingat ini? + Strategi pencadangan + Simpan beberapa versi + Pencadangan tunggal + Strategi pencadangan yang dipilih tidak dapat diandalkan dan tidak direkomendasikan. Kegagalan pencadangan tunggal dapat menyebabkan kehilangan satu-satunya cadangan Anda. + Pilih strategi pencadangan + Lokasi pencadangan Cadangan akan disimpan di - Perintah pencadangan - Perintah pencadangan secara manual - Nomor versi untuk disimpan + Cadangan akan disimpan di + Jalankan pencadangan + Jalankan pencadangan secara manual + Banyaknya versi yang harus disimpan \u221E - Simpan %1$d versi cadangan + Simpan versi %1$d dari cadangan - Simpan cadangan dalam jumlah tak terbatas + Menyimpan cadangan dalam jumlah tak terbatas Impor dari aplikasi Impor token dari aplikasi (membutuhkan akses root) Ekspor Ekspor ke brankas Pengingat kata sandi Ekspor untuk Google Authenticator - Buat kode QR ekspor yang kompatibel dengan Google Authenticator + Membuat kode QR ekspor yang kompatibel dengan Google Authenticator Tidak ada data untuk diekspor - Melewati %d entri yang tidak kompatibel + Melewatkan %d entri yang tidak kompatibel - Tampilkan pengingat %s untuk memasukkan kata sandi, agar Anda tidak lupa. + Tampilkan pengingat %s untuk memasukkan kata sandi agar Anda tidak lupa. Dinonaktifkan Keamanan layar Blokir tangkapan layar dan upaya lain untuk menangkap layar di dalam aplikasi - Sentuh untuk melihat - Token akan disembunyikan secara default. Sentuh token untuk melihat kode. - Batas waktu sentuh untuk melihat - Kunci Otomatis + Ketuk untuk menampilkan + Token akan disembunyikan secara bawaan. Ketuk pada token untuk menampilkan kode. + Batas waktu ketuk untuk menampilkan + Kunci otomatis Kapan %s Dinonaktifkan - Secara otomatis mengunci Aegis saat - Tombol kembali ditekan + Otomatis mengunci Aegis saat + Tombol kembali sudah ditekan Aplikasi diminimalkan Perangkat terkunci Cadangan & Ekspor @@ -101,6 +114,12 @@ Enkripsi brankas dan buka dengan kata sandi atau biometrik Buka kunci dengan biometrik Izinkan otentikasi biometrik untuk membuka brankas + Telusuri melalui: %s + Cari di salah satu kolom berikut + Nama + Penerbit + Catatan + Grup Ganti kata sandi Atur kata sandi baru untuk digunkan membuka brankas Anda Tidak ada kejadian yang dilaporkan @@ -188,6 +207,9 @@ Ubah Pilih semua Tetapkan ikon + Tetapkan ke grup + Pilih grup yang ingin Anda tetapkan untuk menetapkan entri yang dipilih. + Pilih grup Favorit Hapus dari favorit ERROR @@ -205,6 +227,7 @@ Baca berkas Meminta akses root Menganalisis kode QR + Menganalisis kode QR %1$d/%2$d (%3$s) Menambahkan %d entri baru ke brankas @@ -228,6 +251,7 @@ Disalin Kesalahan menyalin ke Clipboard Versi disalin ke Clipboard + Kolom ini wajib diisi Terjadi kesalahan Terjadi kesalahan saat membuka brankas Terjadi kesalahan saat membuka brankas. Mungkin file berkas brankas Anda rusak. @@ -288,6 +312,9 @@ Ekspor Google Authenticator tidak lengkap terdeteksi Beberapa kode QR tidak ditemukan dalam impor Anda. Kode berikut ini tidak ditemukan:\n\n%s\n\nAnda dapat melanjutkan mengimpor ekspor parsial ini, tetapi kami sarankan untuk mencoba kembali dengan semua kode QR agar Anda tidak mengambil risiko kehilangan akses ke token apa pun. • - Kode QR %d + + Tetap mengimpor token %d + Mengimpor ekspor Google Authenticator gagal Ekspor berisi informasi untuk batch yang tidak terkait. Coba impor 1 batch dalam satu waktu. Tidak ada token yang dapat diimpor sebagai hasilnya @@ -330,6 +357,7 @@ Meminimalkan penyalinan Meminimalkan aplikasi setelah menyalin token Menyalin token ke papan klip + Aktivitas pencarian Bekukan token ketika disentuh Hentikan penyegaran otomatis token dengan menyentuh mereka. Token tidak akan diperbarui selama mereka difokuskan. Membutuhkan \"Sorot token saat disentuh\" atau \"Sentuh untuk melihat.\" Masukkan kata sandi Anda untuk mengaktifkan keyboard PIN. Perhatikan bahwa ini hanya berfungsi jika kata sandi Anda hanya terdiri dari angka @@ -354,6 +382,7 @@ Tidak dapat memproses tautan dalam Tidak dapat membaca dan memproses kode QR dari berkas: %s. Tidak dapat memproses teks bersama sebagai OTP + Tidak dapat membaca dan memproses sebagian kode QR. Hanya entri %1$d/%2$d yang akan diimpor. Tidak dapat membuat kode QR Pilih gambar Pilih ikon @@ -384,7 +413,13 @@ Aegis mengandalkan waktu sistem untuk disinkronkan menjadi kode yang benar. Selisih hanya beberapa detik dapat menyebabkan kode salah. Sepertinya perangkat Anda tidak dikonfigurasi untuk menyinkronkan waktu secara otomatis. Apakah Anda ingin melakukannya sekarang? Berhenti memperingatkan saya. Saya tahu apa yang saya lakukan. Ditemukan kode QR yang tidak terkait. Coba mulai ulang pemindai. + + Kode QR yang dipindai %1$d/%2$d + + Kode QR yang seharusnya #%1$d, tetapi yang dipindai justru #%2$d Pencadangan Brankas baru-baru ini gagal + Upaya pencadangan brankas terkini menggunakan %1$s gagal karena terjadi kesalahan. Pencadangan telah dilakukan dengan menggunakan %2$s. Periksa pengaturan pencadangan Anda untuk memastikan pencadangan berhasil diselesaikan. + Upaya pencadangan brankas terkini menggunakan %1$s gagal karena Aegis tidak memiliki izin untuk menulis ke tujuan pencadangan. Pencadangan telah dilakukan dengan menggunakan %2$s. Kesalahan ini dapat terjadi jika Anda memindahkan/mengganti nama tujuan pencadangan atau jika Anda baru saja memulihkan Aegis dari pencadangan. Harap konfigurasikan ulang tujuan pencadangan. Pencadangan otomatis bawaan Aegis Sistem pencadangan awan Android Backup terakhir sudah kedaluwarsa (%s) @@ -457,7 +492,11 @@ Sediakan salinan /data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml, yang terletak di direktori penyimpanan internal Battle.net Authenticator. Siapkan salinan /data/data/com.duosecurity.duomobile/files/duokit/accounts.json, yang terletak di direktori penyimpanan internal DUO. + Menyediakan file ekspor Ente Auth. Saat ini hanya file yang tidak dienkripsi yang didukung. + FreeOTP 2: Menyediakan berkas cadangan.\nFreeOTP 1.x: Menyediakan salinan /data/data/org.fedorahosted.freeotp/shared_prefs/tokens.xml, yang terletak di direktori penyimpanan internal FreeOTP. Siapkan berkas ekspor FreeOTP+. + Kompatibilitas FreeOTP 2 + Ada sejumlah masalah dalam FreeOTP 2 yang dapat mengakibatkan cadangan rusak. Aegis akan mencoba menyelamatkan sebanyak mungkin entri, tetapi ada kemungkinan beberapa atau bahkan semuanya gagal diimpor. Hanya berkas basis data dari Google Authenticator v5.10 dan sebelumnya yang didukung.\n\nMasukkan salinan dari /data/data/com.google.android.apps.authenticator2/databases/databases, yang tersimpan di direktori penyimpanan internal Google Authenticator. Siapkan salinan /data/data/com.azure.authenticator/databases/PhoneFactor, yang terletak di direktori penyimpanan internal Microsoft Authenticator. diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index 9fdd98b3..d8ad81b7 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -29,6 +29,7 @@ Configura la crittografia, lo sblocco biometrico, il blocco automatico e altre impostazioni di sicurezza. Importa / Esporta Importa i backup di Aegis o di altre applicazioni di autenticazione. Crea esportazioni manuali della tua cassaforte di Aegis. + Trova un elenco di tutti gli eventi importanti segnalati che sono avvenuti nell\'app. Backup Imposta i backup automatici in una posizione a tua scelta o abilita la partecipazione al sistema di backup cloud di Android. Pacchetti di icone @@ -43,6 +44,11 @@ Raggruppamento delle cifre dei codici Seleziona il numero di cifre per cui raggruppare i codici Mostra il nome dell\'account + Mostra il codice successivo + Genera e mostra il codice successivo in anticipo + Mostra quando qualche codice sta per scadere + Cambia il colore e fa\' lampeggiare i codici che stanno per scadere + Cambia il colore dei codici quando stanno per scadere Mostra il nome dell\'account solo se necessario Mostra i nomi degli account quando condividono lo stesso servizio. I nomi degli altri account verranno nascosti. Importa da un file @@ -56,7 +62,11 @@ Mostra un promemoria per effettuare il backup della cassaforte nel caso in cui non sia stato fatto dopo le ultime modifiche. Disabilita i promemoria di backup Se disabiliti i promemoria, Aegis non ti avviserà delle eventuali modifiche di cui non hai ancora effettuato il backup. Ciò comporta il rischio di perdere l\'accesso ai tuoi token. Sei sicuro di voler disabilitare i promemoria? + Strategia di backup + Backup singolo + Seleziona una strategia di backup I backup saranno salvati in + I backup saranno salvati in Effettua un backup Effettua un backup manualmente Numero di versioni da salvare diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index bd8a0199..c135f526 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -64,7 +64,14 @@ Visa en påminnelse om att säkerhetskopiera ditt valv ifall du inte har säkerhetskopierat dina senaste ändringar. Inaktivera påminnelse om säkerhetskopiering Inaktivering av denna påminnelse innebär att Aegis inte kommer att meddela dig om du har ändringar som ännu inte har säkerhetskopierats. Detta utsätter dig för risken att förlora åtkomst till dina polletter. Är du säker på att du vill inaktivera påminnelsen? + Strategi för säkerhetskopiering + Behåll ett antal versioner + Enstaka säkerhetskopia + Den valda strategin för säkerhetskopiering är inte tillförlitlig och rekommenderas inte. Ett enda säkerhetskopieringsfel kan leda till att du förlorar din enda säkerhetskopia. + Välj en strategi för säkerhetskopiering + Plats för säkerhetskopior Säkerhetskopior kommer att lagras i + Säkerhetskopia kommer att lagras i Skapa säkerhetskopia Skapa en säkerhetskopia manuellt Antal versioner att behålla @@ -499,7 +506,10 @@ Tillhandahåll en kopia av /data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml, som finns i den interna lagringskatalogen för Battle.net Authenticator. Tillhandahåll en kopia av /data/data/com.duosecurity.duomobile/files/duokit/accounts.json, som finns i den interna lagringskatalogen för DUO. Tillhandahåll en exportfil från Ente Auth. För närvarande stöds endast okrypterade filer. + FreeOTP 2: Tillhandahåll en säkerhetskopiefil.\nFreeOTP 1.x: Tillhandahåll en kopia av /data/data/org.fedorahosted.freeotp/shared_prefs/tokens.xml, som finns i den interna lagringskatalogen för FreeOTP. Tillhandahåll en exportfil från FreeOTP+. + FreeOTP 2-kompatibilitet + Det finns ett antal problem i FreeOTP 2 som kan resultera i korrupta säkerhetskopior. Aegis kommer att försöka att rädda så många poster som möjligt, men det är möjligt att vissa eller till och med alla av dem inte kan importeras. Endast databasfiler från Google Authenticator v5.10 och tidigare stöds.\n\nTillhandahåll en kopia av /data/data/com.google.android.apps.authenticator2/databases/databases, som finns i den interna lagringskatalogen för Google Authenticator. Tillhandahåll en kopia av /data/data/com.azure.authenticator/databases/PhoneFactor, som finns i den interna lagringskatalogen för Microsoft Authenticator. Tillhandahåll en klartextfil med en Google Authenticator-URI per rad. diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 0f6b5e5e..89c18b89 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -57,10 +57,14 @@ 備份提醒 提示您備份保險箱以避免最後的變更狀態未被加入備份。 關閉備份提醒 + 備份策略 + 選擇備份策略 + 備份位置 備份將儲存在 觸發備份 手動觸發備份 保留的版本數 + \u221E 保留 %1$d 個備份 @@ -115,6 +119,7 @@ 已分享一筆資料 密碼庫解鎖失敗(密碼) 密碼庫解鎖失敗(生物特徵辨識) + 未知的事件類型 (已刪除) 今天 %1$s %1$s 的 %2$s From 81a26ccad82ba727b1d663e853d6cd40b026768c Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Thu, 2 Jan 2025 22:08:00 +0100 Subject: [PATCH 15/44] Release v3.3.3 --- app/build.gradle | 4 ++-- app/src/main/assets/changelog.html | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index cc554916..c1edd235 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,8 +28,8 @@ android { applicationId "${packageName}" minSdkVersion 21 targetSdkVersion 35 - versionCode 75 - versionName "3.3.2" + versionCode 76 + versionName "3.3.3" multiDexEnabled true buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\"" buildConfigField "String", "GIT_BRANCH", "\"${getGitBranch()}\"" diff --git a/app/src/main/assets/changelog.html b/app/src/main/assets/changelog.html index bb803312..f829c697 100644 --- a/app/src/main/assets/changelog.html +++ b/app/src/main/assets/changelog.html @@ -31,6 +31,13 @@
    +

    Version 3.3.3

    +

    Fixes

    +
      +
    • Some users ran into out of memory conditions due to large icons in their vault file. We've introduced a temporary measure that should help in most cases, but we'll follow up with a more comprehensive fix soon.
    • +
    • Window insets were not always applied correctly, causing parts of the UI to appear off-screen
    • +
    • The 2FAS importer did not tolerate spaces for secrets and was not always able to extract the issuer
    • +

    Version 3.3.2

    New

      From 5439067e9fd7f389805826d9a57e81f1d2e3b9fb Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Sun, 5 Jan 2025 13:21:55 +0100 Subject: [PATCH 16/44] Rename Authenticator Pro -> Stratum --- app/src/main/AndroidManifest.xml | 2 +- .../aegis/importers/DatabaseImporter.java | 2 +- ...rProImporter.java => StratumImporter.java} | 12 +++++------ app/src/main/res/values-ar-rSA/strings.xml | 1 - app/src/main/res/values-bg-rBG/strings.xml | 1 - app/src/main/res/values-ca-rES/strings.xml | 1 - app/src/main/res/values-cs-rCZ/strings.xml | 1 - app/src/main/res/values-da-rDK/strings.xml | 1 - app/src/main/res/values-de-rDE/strings.xml | 1 - app/src/main/res/values-el-rGR/strings.xml | 1 - app/src/main/res/values-es-rES/strings.xml | 1 - app/src/main/res/values-eu-rES/strings.xml | 1 - app/src/main/res/values-fi-rFI/strings.xml | 1 - app/src/main/res/values-fr-rFR/strings.xml | 1 - app/src/main/res/values-fy-rNL/strings.xml | 1 - app/src/main/res/values-gl-rES/strings.xml | 1 - app/src/main/res/values-hi-rIN/strings.xml | 1 - app/src/main/res/values-hu-rHU/strings.xml | 1 - app/src/main/res/values-in-rID/strings.xml | 1 - app/src/main/res/values-it-rIT/strings.xml | 1 - app/src/main/res/values-iw-rIL/strings.xml | 1 - app/src/main/res/values-ja-rJP/strings.xml | 1 - app/src/main/res/values-lv-rLV/strings.xml | 1 - app/src/main/res/values-nl-rNL/strings.xml | 1 - app/src/main/res/values-pl-rPL/strings.xml | 1 - app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-pt-rPT/strings.xml | 1 - app/src/main/res/values-ro-rRO/strings.xml | 1 - app/src/main/res/values-ru-rRU/strings.xml | 1 - app/src/main/res/values-sv-rSE/strings.xml | 1 - app/src/main/res/values-tr-rTR/strings.xml | 1 - app/src/main/res/values-vi-rVN/strings.xml | 1 - app/src/main/res/values-zh-rCN/strings.xml | 1 - app/src/main/res/values/strings.xml | 2 +- .../aegis/importers/DatabaseImporterTest.java | 20 +++++++++--------- ...ro_encrypted.bin => stratum_encrypted.bin} | Bin ...egacy.bin => stratum_encrypted_legacy.bin} | Bin ...uthpro_internal.db => stratum_internal.db} | Bin ...{authpro_plain.json => stratum_plain.json} | 0 39 files changed, 19 insertions(+), 49 deletions(-) rename app/src/main/java/com/beemdevelopment/aegis/importers/{AuthenticatorProImporter.java => StratumImporter.java} (97%) rename app/src/test/resources/com/beemdevelopment/aegis/importers/{authpro_encrypted.bin => stratum_encrypted.bin} (100%) rename app/src/test/resources/com/beemdevelopment/aegis/importers/{authpro_encrypted_legacy.bin => stratum_encrypted_legacy.bin} (100%) rename app/src/test/resources/com/beemdevelopment/aegis/importers/{authpro_internal.db => stratum_internal.db} (100%) rename app/src/test/resources/com/beemdevelopment/aegis/importers/{authpro_plain.json => stratum_plain.json} (100%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9339e659..9156f0bf 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -150,7 +150,7 @@ - + diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/DatabaseImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/DatabaseImporter.java index 1be462f5..fe1b5b5f 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/DatabaseImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/DatabaseImporter.java @@ -34,7 +34,6 @@ public abstract class DatabaseImporter { _importers.add(new Definition("Aegis", AegisImporter.class, R.string.importer_help_aegis, false)); _importers.add(new Definition("andOTP", AndOtpImporter.class, R.string.importer_help_andotp, false)); _importers.add(new Definition("Authenticator Plus", AuthenticatorPlusImporter.class, R.string.importer_help_authenticator_plus, false)); - _importers.add(new Definition("Authenticator Pro", AuthenticatorProImporter.class, R.string.importer_help_authenticator_pro, true)); _importers.add(new Definition("Authy", AuthyImporter.class, R.string.importer_help_authy, true)); _importers.add(new Definition("Battle.net Authenticator", BattleNetImporter.class, R.string.importer_help_battle_net_authenticator, true)); _importers.add(new Definition("Bitwarden", BitwardenImporter.class, R.string.importer_help_bitwarden, false)); @@ -46,6 +45,7 @@ public abstract class DatabaseImporter { _importers.add(new Definition("Microsoft Authenticator", MicrosoftAuthImporter.class, R.string.importer_help_microsoft_authenticator, true)); _importers.add(new Definition("Plain text", GoogleAuthUriImporter.class, R.string.importer_help_plain_text, false)); _importers.add(new Definition("Steam", SteamImporter.class, R.string.importer_help_steam, true)); + _importers.add(new Definition("Stratum (Authenticator Pro)", StratumImporter.class, R.string.importer_help_stratum, true)); _importers.add(new Definition("TOTP Authenticator", TotpAuthenticatorImporter.class, R.string.importer_help_totp_authenticator, true)); _importers.add(new Definition("WinAuth", WinAuthImporter.class, R.string.importer_help_winauth, false)); } diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/AuthenticatorProImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/StratumImporter.java similarity index 97% rename from app/src/main/java/com/beemdevelopment/aegis/importers/AuthenticatorProImporter.java rename to app/src/main/java/com/beemdevelopment/aegis/importers/StratumImporter.java index 1f755962..7504d98a 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/AuthenticatorProImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/StratumImporter.java @@ -45,11 +45,11 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; -public class AuthenticatorProImporter extends DatabaseImporter { +public class StratumImporter extends DatabaseImporter { private static final String HEADER = "AUTHENTICATORPRO"; private static final String HEADER_LEGACY = "AuthenticatorPro"; - private static final String PKG_NAME = "me.jmh.authenticatorpro"; - private static final String PKG_DB_PATH = "files/proauth.db3"; + private static final String PKG_NAME = "com.stratumauth.app"; + private static final String PKG_DB_PATH = "databases/authenticator.db3"; private enum Algorithm { SHA1, @@ -57,7 +57,7 @@ public class AuthenticatorProImporter extends DatabaseImporter { SHA512 } - public AuthenticatorProImporter(Context context) { + public StratumImporter(Context context) { super(context); } @@ -169,7 +169,7 @@ public class AuthenticatorProImporter extends DatabaseImporter { Argon2Task.Params params = getKeyDerivationParams(password); Argon2Task task = new Argon2Task(context, key -> { try { - AuthenticatorProImporter.JsonState state = decrypt(key); + StratumImporter.JsonState state = decrypt(key); listener.onStateDecrypted(state); } catch (DatabaseImporterException e) { listener.onError(e); @@ -244,7 +244,7 @@ public class AuthenticatorProImporter extends DatabaseImporter { PBKDFTask.Params params = getKeyDerivationParams(password); PBKDFTask task = new PBKDFTask(context, key -> { try { - AuthenticatorProImporter.JsonState state = decrypt(key); + StratumImporter.JsonState state = decrypt(key); listener.onStateDecrypted(state); } catch (DatabaseImporterException e) { listener.onError(e); diff --git a/app/src/main/res/values-ar-rSA/strings.xml b/app/src/main/res/values-ar-rSA/strings.xml index a21363fa..9b0ed729 100644 --- a/app/src/main/res/values-ar-rSA/strings.xml +++ b/app/src/main/res/values-ar-rSA/strings.xml @@ -515,7 +515,6 @@ توفير مِلَفّ النسخ الاحتياطي 2FAS Authenticator. توفير مِلَفّ Aegis للتصدير / النسخ الاحتياطي. توفير مِلَفّ تصدير Authenticator Plus الذي تم الحصول عليه من خلال الإعدادات -> النسخ الاحتياطي & استعادة -> تصدير كنص و HTML. - توفير مِلَفّ تصدير Authenticator Pro الذي تم الحصول عليه من خلال <b>الإعدادات -> النسخ الاحتياطي -> النسخ الاحتياطي إلى مِلَفّ مشفر (مستحسن). توفير نسخة من /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml، الموجود في دليل التخزين الداخلي لـ Authy. توفير مِلَفّ تصدير / نسخ احتياطي andOTP. توفير مِلَفّ تصدير / نسخ احتياطي لـ Bitwarden. الملفات المشفرة غير مدعومة. diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml index 725b1067..7398978f 100644 --- a/app/src/main/res/values-bg-rBG/strings.xml +++ b/app/src/main/res/values-bg-rBG/strings.xml @@ -499,7 +499,6 @@ Изберете файл с резервно копие на 2FAS Authenticator. Изберете изнесен файл или резервно копие на Aegis. Изберете файл с резервно копие на Authenticator Plus, получен от Настройки → Резервни копия и възстановяване → Изнасяне като текст и HTML. - Изберете файл с резервно копие на Authenticator Pro, получен от Настройки → Резервно копие → Резервно копие в шифрован файл (препотъчително). Изберете копие на файла /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, който се намира в папката с данни на Authy. Изберете изнесен файл или резервно копие на andOTP. Изберете изнесен файл или резервно копие на Bitwarden. Шифровани файлове не се поддържат. diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index 2993a46a..cdb7e264 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -497,7 +497,6 @@ Subministra un fitxer exportat del 2FAS Authenticator. Subministra un fitxer exportat del Aegis. Subministra un fitxer exportat del Authenticator Plus, obtingut amb Settings -> Backup & Restore -> Export as Text and HTML. - Proveeix un fitxer exportat d\'Authenticat Pro, aconseguit a Settings > Back up > Back up to encrypted file (recommended). Subministra una còpia de /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, que està a l\'emmagatzematge intern del teu dispositiu, al directori del Authy. Subministra un fitxer exportat del andOTP. Subministreu un fitxer d\'exportació/còpia de seguretat de Bitwarden. Els fitxers xifrats no són compatibles. diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 353ca221..79c7a16f 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -525,7 +525,6 @@ Dodejte záložní soubor 2FAS Authenticator. Dodejte soubor exportu/zálohy Aegis. Dodejte exportovaný soubor Authenticator Plus získaný přes Nastavení -> Záloha a obnovení -> Exportovat jako text a HTML. - Dodejte exportovaný soubor Authenticator Pro získaný přes Nastavení -> Záloha -> Exportovat do šifrovaného souboru (doporučeno). Dodejte kopii /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, která se nachází v interním úložišti Authy. Dodejte soubor exportu/zálohy andOTP. Vyberte soubor exportu/zálohy Bitwardenu. Šifrované soubory nejsou podporovány. diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da-rDK/strings.xml index 1abf8833..d53c5040 100644 --- a/app/src/main/res/values-da-rDK/strings.xml +++ b/app/src/main/res/values-da-rDK/strings.xml @@ -499,7 +499,6 @@ Stil en 2FAS-godkendelse sikkerhedskopifil til rådighed. Levér en Aegis eksport/backup fil. Levér en Authenticator Plus-eksportfil opnået gennem Indstillinger -> Sikkerhedskopi & Gendan -> Eksport som tekst og HTML. - Benyt en Authenticator Pro-eksportfil genereret via Indstillinger -> Sikkerhedskopiering -> Sikkerhedskopiering til krypteret fil (anbefalet). Levér en kopi af /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, der er placeret i den interne lagermappe i Authy. Levér en andOTP eksport/backup fil. Vælg en Bitwarden-eksport-/sikkerhedskopifil. Krypterede filer understøttes ikke. diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index d657c84c..828fc4c0 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -499,7 +499,6 @@ Gib eine 2FAS-Authenticator-Sicherungsdatei an. Gib eine Aegis-Export-/Sicherungsdatei an. Gib eine Authenticator-Plus-Exportdatei an, die du über Einstellungen -> Sicherung & Rücksicherung -> Exportieren als Text und HTML Format erhältst. - Gib eine Authenticator-Pro-Exportdatei an, die du über Einstellungen -> Sicherung -> Als verschlüsselte Datei sichern (empfohlen) erhältst. Gib eine Kopie von /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml an, die sich im internen Speicherverzeichnis von Authy befindet. Gib eine andOTP-Export-/Sicherungsdatei an. Gib eine Bitwarden-Export-/Sicherungsdatei an. Verschlüsselte Dateien werden nicht unterstützt. diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el-rGR/strings.xml index 3954d4eb..244447c8 100644 --- a/app/src/main/res/values-el-rGR/strings.xml +++ b/app/src/main/res/values-el-rGR/strings.xml @@ -498,7 +498,6 @@ Παρέχετε ένα αντίγραφο ασφαλείας 2FAS Authenticator. Παρέχετε ένα αρχείο εξαγωγής/αντιγράφων ασφαλείας Aegis. Παρέχετε ένα αρχείο εξαγωγής Authenticator Plus που αποκτήθηκε μέσω των Ρυθμίσεων - > Αντιγράφων ασφαλείας & Επαναφορά - > Εξαγωγή ως Κείμενο και HTML . - Παρέχεται ένα αρχείο εξαγωγής Authenticator Pro που λαμβάνεται μέσω Ρυθμίσεις -> Δημιουργία αντιγράφων ασφαλείας -> Δημιουργία σε κρυπτογραφημένο αρχείο (συνιστάται). Παρέχετε ένα αντίγραφο του /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, που βρίσκεται στον κατάλογο εσωτερικής αποθήκευσης του Authy. Παρέχετε ένα αρχείο εξαγωγής/αντιγράφου ασφαλείας andOTP. Παρέχετε ένα αρχείο εξαγωγής/αντιγράφων ασφαλείας Bitwarden. Τα κρυπτογραφημένα αρχεία δεν υποστηρίζονται. diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index bcb4afa7..0566e604 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -499,7 +499,6 @@ Suministre un archivo exportado de 2FAS Authenticator. Suministre un archivo exportado/copia de seguridad de Aegis. Suministre un archivo exportado de Authenticator Plus obtenido a través de Ajustes -> Copias de seguridad -> Exportar como texto y HTML. - Suministra un archivo de exportación de Authenticator Pro obtenido a través de Configuración -> Copias de seguridad -> Copia de seguridad en archivo cifrado (recomendado). Proporciona una copia del archivo /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, ubicado en la carpeta de almacenamiento interno de Authy. Suministre un archivo exportado/copia de seguridad de andOTP. Suministra un archivo de exportación/copia de seguridad de Bitwarden. Los archivos encriptados no están soportados. diff --git a/app/src/main/res/values-eu-rES/strings.xml b/app/src/main/res/values-eu-rES/strings.xml index 160807b7..2564a00c 100644 --- a/app/src/main/res/values-eu-rES/strings.xml +++ b/app/src/main/res/values-eu-rES/strings.xml @@ -489,7 +489,6 @@ Aukeratu 2FAS Authenticator segurtasun-kopia fitxategia. Aegisen esportazio/segurtasun-kopia fitxategia aukeratu. Authenticator Plus esportazio fitxategia aukeratu. Lortzeko modua: Settings -> Backup & Restore -> Export as Text and HTML. - Aukeratu Authenticator Proren esportazio fitxategia Settings -> Back up -> Back up to encrypted file (recommended) aukeratik lortu bezala. /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml fitxategia aukeratu. andOTPren esportazio/segurtasun-kopia fitxategia aukeratu. Kargatu Bitwardenen esportazio/segurtasun-kopia fitxategi bat. Ezin dituzu zifratutako fitxategiak kargatu. diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index d4c3c316..9b52b6db 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -499,7 +499,6 @@ Anna 2FAS Authenticatorin varmuuskopiotiedosto. Anna Aegisisin vienti-/varmuuskopiotiedosto. Anna Authenticator Plus -varmuuskopiotiedosto, jonka saat menemällä Asetukset ->Varmuuskopiointi ja palautus -> Vie teksti- tai HTML-tiedostona. - Toimita Authenticator Pro -vientitiedosto, jonka löydät menemällä Asetukset -> Varmuuskopioi -> Varmuuskopioi salattuun tiedostoon (suositus). Anna kopio tiedostosta /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, joka sijaitsee Authyn sisäisessä tallennushakemistossa. Anna andOTP:n vienti-/varmuuskopiotiedosto. Anna Bitwardenin vienti-/varmuuskopiotiedosto. Salattuja tiedostoja ei tueta. diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml index ace507da..3b3fcfc0 100644 --- a/app/src/main/res/values-fr-rFR/strings.xml +++ b/app/src/main/res/values-fr-rFR/strings.xml @@ -499,7 +499,6 @@ Fournir une sauvegarde 2FAS Authenticator. Fournir un export/sauvegarde Aegis. Fournir un export Authenticator Plus obtenu via Paramètres -> Sauvegarde & Restauration -> Exporter en tant que texte et HTML. - Fournir un export Authenticator Pro obtenu via Paramètres -> Sauvegarde -> Sauvegarder en tant que fichier chiffré (recommandé). Fournir une copie de /data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, situé dans le répertoire de stockage interne d\'Authy. Fournir un export/sauvegarde andOTP. Fournir un export/sauvegarde Bitwarden. Les fichiers chiffrés ne sont pas pris en charge. diff --git a/app/src/main/res/values-fy-rNL/strings.xml b/app/src/main/res/values-fy-rNL/strings.xml index 746d2364..a512cd75 100644 --- a/app/src/main/res/values-fy-rNL/strings.xml +++ b/app/src/main/res/values-fy-rNL/strings.xml @@ -499,7 +499,6 @@ Leverje in 2FAS-autentikator-eksportbestân oan. Leverje in Aegis-eksport-/reservekopybestân oan. Leverje in Authenticator Plus-eksportbestân oan krigen fia Ynstellingen -> Reservekopy & Werstelle -> Eksportearje as Tekst en HTML. - Leverje in Authenticator Pro-eksportbestân oan krigen fia Ynstellingen -> Reservekopy -> Reservekopy nei fersifere bestân (oanrekommandearre). Leverje in kopy oan fan /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, pleatst yn de ynterne ûnthâldmap fan Authy. Leverje in andOTP-eksport-/reservekopybestân oan. Leverje in Bitwarden-eksport-/reservekopybestân oan. Fersifere bestannen wurde net stipe. diff --git a/app/src/main/res/values-gl-rES/strings.xml b/app/src/main/res/values-gl-rES/strings.xml index 3e4310f1..06c4d24b 100644 --- a/app/src/main/res/values-gl-rES/strings.xml +++ b/app/src/main/res/values-gl-rES/strings.xml @@ -499,7 +499,6 @@ Proporciona un ficheiro de copia de seguridade de 2FAS Authenticator. Proporciona un ficheiro de copia de seguridade ou de exportación de Aegis. Proporciona un ficheiro de exportación de Authenticator Plus obtido mediante Axustes -> Copia de seguridade e restauración -> Exportar como texto e HTML. - Proporciona un ficheiro de exportación de Authenticator Pro, obtido desde Axustes -> Copia de seguridade -> Facer copia de seguridade nun ficheiro cifrado (recomendado). Proporciona unha copia de /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, localizado no directorio do almacenamento interno de Authy. Proporciona un ficheiro de copia de seguridade ou de exportación de andOTP. Proporciona un ficheiro de copia de seguridade ou de exportación de Bitwarden. Non se admiten os ficheiros cifrados. diff --git a/app/src/main/res/values-hi-rIN/strings.xml b/app/src/main/res/values-hi-rIN/strings.xml index d5959077..392d3dde 100644 --- a/app/src/main/res/values-hi-rIN/strings.xml +++ b/app/src/main/res/values-hi-rIN/strings.xml @@ -399,7 +399,6 @@ एजिस निर्यात/बैकअप फ़ाइल की आपूर्ति करें। एक प्रमाणक प्लस निर्यात फ़ाइल की आपूर्ति करें सेटिंग्स -> बैकअप & पुनर्स्थापना -> पाठ और HTML के रूप में निर्यात करें - सेटिंग्स -> बैक अप -> के माध्यम से प्राप्त ऑथेंटिकेटर प्रो एक्सपोर्ट फ़ाइल की आपूर्ति करें। एन्क्रिप्टेड फ़ाइल का बैकअप लें (अनुशंसित) Authy की आंतरिक संग्रहण निर्देशिका में स्थित /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml की एक प्रति प्रदान करें। एक andOTP निर्यात/बैकअप फ़ाइल की आपूर्ति करें। एक बिटवर्डन निर्यात/बैकअप फ़ाइल की आपूर्ति करें। एन्क्रिप्टेड फ़ाइलें समर्थित नहीं हैं। diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index ab1d4d98..bea2a8d7 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -499,7 +499,6 @@ Adja meg a 2FAS Authenticator egy biztonsági mentési fájlját. Adja meg az Aegis egy exportját vagy biztonsági mentési fájlját. Adja meg az Authenticator Plus egy exportfájlját, melyet a Beállítások -> Mentés és visszaállítás -> Exportálás szövegként vagy HTML-ként résznél állíthat elő. - Adja meg az Authenticator Plus egy exportfájlját, melyet a Beállítások -> Biztonsági mentés -> Biztonsági mentés titkosított fájlba (ajánlott) résznél állíthat elő. Adja meg a /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml másolatát, mely az Authy belső háttértáron levő mappájában található. Adja meg az andOTP egy exportját vagy biztonsági mentési fájlját. Adja meg a Bitwarden egy exportját vagy biztonsági mentési fájlját. A titkosított fájlok nem támogatottak. diff --git a/app/src/main/res/values-in-rID/strings.xml b/app/src/main/res/values-in-rID/strings.xml index ec3a2f80..dcb49a00 100644 --- a/app/src/main/res/values-in-rID/strings.xml +++ b/app/src/main/res/values-in-rID/strings.xml @@ -484,7 +484,6 @@ Sediakan sebuah berkas cadangan Autetikator 2FAS. Siapkan berkas ekspor/cadangan Aegis. Siapkan berkas ekspor Authenticator Plus yang didapat melaluiPengaturan -> Pemulihan & Cadangan -> Ekspor sebagai Teks dan HTML. - Sediakan file ekspor Authenticator Pro yang diperoleh melalui Pengaturan -> Cadangkan -> Cadangkan ke file terenkripsi (disarankan). Siapkan salinan /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, yang terletak di direktori penyimpanan internal Authy. Siapkan berkas ekspor/cadangan andOTP. diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index d8ad81b7..4b890e12 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -445,7 +445,6 @@ Seleziona un backup di 2FAS Authenticator. Seleziona un file di backup di Aegis. Seleziona un file di esportazione di Authenticator Plus ottenuto tramite Impostazioni -> Backup & Ripristino -> Esporta come testo e HTML. - Fornire un file di esportazione di Authenticator Pro ottenuto tramite Impostazioni -> Backup -> Backup in file cifrato (raccomandato). Seleziona una copia di /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, situata nella directory della memoria interna di Authy. Seleziona un file di backup di andOTP. Seleziona un file di esportazione/backup di Bitwarden. I file crittografati non sono supportati. diff --git a/app/src/main/res/values-iw-rIL/strings.xml b/app/src/main/res/values-iw-rIL/strings.xml index 6468bf9a..7a94c368 100644 --- a/app/src/main/res/values-iw-rIL/strings.xml +++ b/app/src/main/res/values-iw-rIL/strings.xml @@ -388,7 +388,6 @@ ספק קובץ גיבוי של 2FAS Authenticator. ספק קובץ ייצוא/גיבוי של Aegis. ספק קובץ ייצוא של Authenticator Plus שהושג דרך הגדרות -> גיבוי & שחזור -> ייצוא כטקסט ו-HTML. - ספק קובץ ייצוא של Authenticator Pro שהושג דרך הגדרות -> גיבוי -> גבה לקובץ מוצפן (מומלץ). ספק עותק של /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, הממוקם בספריית האחסון הפנימית של Authy. ספק קובץ יצוא/גיבוי andOTP. ספק קובץ יצוא/גיבוי של Bitwarden. קבצים מוצפנים אינם נתמכים. diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 7c11b8fc..ce763803 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -416,7 +416,6 @@ 2FAS Authenticatorのバックアップファイルを提供します。 Aegisのエクスポート/バックアップファイルを提供します。 Authenticator PlusのSettings -> Backup & Restore -> Export as Text and HTMLで取得したエクスポートファイルを提供します。 - Authenticator Pro でファイルをエクスポートするには、設定 -> バックアップ -> 暗号化されたファイルへバックアップ (推奨) と進みます。 Authyの内部ストレージディレクトリにある /data/data/com.authy/shared_prefs/com.auth.storage.tokens.authenticator.xmlのコピーを提供します。 andOTPのエクスポート/バックアップ ファイルを提供します。 Bitwarden のエクスポート/バックアップファイルを提供します。暗号化されたファイルはサポートされていません。 diff --git a/app/src/main/res/values-lv-rLV/strings.xml b/app/src/main/res/values-lv-rLV/strings.xml index 23ad5f3a..6973b8bf 100644 --- a/app/src/main/res/values-lv-rLV/strings.xml +++ b/app/src/main/res/values-lv-rLV/strings.xml @@ -512,7 +512,6 @@ Jāiesniedz 2FAS Authenticator izgūšanas datne. Jāiesniedz Aegis izgūšanas/rezerves kopijas datne. Jāiesniedz Authenticator Plus izgūšanas datne, kas ir iegūta ar Iestatījumi -> Dublēšana un atjaunošana -> Izgūt kā tekstu un HTML. - Jāiesniedz Authenticator Pro izgūšanas datne, kas ir iegūstama Iestatījumi -> Rezerves kopijas -> Dublēt šifrētā datnē (ieteicams). Jāiesniedz /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml kopija, kas atrodas iekšējās krātuves Authy mapē. Jāiesniedz andOTP izgūšanas/rezerves kopijas datne. Jāiesniedz Bitwarden izgūšanas/rezerves kopijas datne. Šifrētas datnes netiek atbalstītas. diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml index bc8c60cb..a395701e 100644 --- a/app/src/main/res/values-nl-rNL/strings.xml +++ b/app/src/main/res/values-nl-rNL/strings.xml @@ -499,7 +499,6 @@ Lever een 2FAS Authenticator-back-upbestand aan. Lever een Aegis-export/-back-upbestand aan. Lever een Authenticator Plus-exportbestand aan verkregen via Instellingen -> Back-up & Herstellen -> Exporteren als Tekst en HTML. - Lever een Authenticator Pro-exportbestand aan verkregen via Instellingen -> Back-up -> Back-up naar versleuteld bestand (aanbevolen). Lever een kopie aan van /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, geplaatst in de interne opslagmap van Authy. Lever een andOTP-export/-back-upbestand aan. Lever een Bitwarden-export/-back-upbestand aan. Versleutelde bestanden worden niet ondersteund. diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml index e43b89d2..5229310d 100644 --- a/app/src/main/res/values-pl-rPL/strings.xml +++ b/app/src/main/res/values-pl-rPL/strings.xml @@ -524,7 +524,6 @@ Dostarcz plik zapasowy 2FAS Authenticator. Dostarcz plik zapasowy Aegis. Dostarcz plik eksportu Authenticator Plus uzyskany w Ustawienia -> Kopia zapasowa & Przywróć -> Eksportuj jako tekst i HTML. - Dostarcz plik eksportu Authenticator Pro uzyskany przez Ustawienia -> Kopia zapasowa -> Kopia zapasowa do zaszyfrowanego pliku (zalecana). Dostarcz kopię /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, znajdującą się w wewnętrznym katalogu pamięci Authy. Dostarcz plik andOTP eksportu/kopii zapasowej. Dostarcz plik kopii zapasowej Bitwarden. Zaszyfrowane pliki nie są obsługiwane. diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 3dcde193..3ec74df7 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -500,7 +500,6 @@ Por favor, configure o local de backup. Forneça um arquivo de backup do 2FAS Authenticator. Fornecer um arquivo de exportação/backup do Aegis. Fornecer um arquivo de exportação do Autenticador Plus obtido através de Configurações -> Backup & Restaurar -> Exportar como Texto e HTML. - Forneça um arquivo de exportação do Autenticador Pro obtido através de Configurações -> Fazer backup -> Fazer backup para arquivo criptografado (recomendado). Fornecer uma cópia de /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, localizado no diretório de armazenamento interno do Authy. Fornecer um arquivo de exportação/backup do andOTP. Forneça um arquivo de exportação/backup do Bitwarden. Arquivos criptografados não são suportados. diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 1709495f..e54f1ac2 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -453,7 +453,6 @@ Fornecer um arquivo de backup de 2FAS Authenticator. Fornecer um arquivo de exportação/backup do Aegis. Fornecer um arquivo de exportação do Autenticador Plus obtido através de Configurações -> Backup & Restaurar -> Exportar como Texto e HTML. - Forneça um ficheiro de exportação do Authenticator Pro obtido através de Settings -> Back up -> Back up to encrypted file (recommended). Fornecer uma cópia de /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, localizado no diretório de armazenamento interno do Authy. Fornecer um arquivo de exportação/backup do andOTP. Forneça um ficheiro de exportação/backup Bitwarden. Os ficheiros encriptados não são suportados. diff --git a/app/src/main/res/values-ro-rRO/strings.xml b/app/src/main/res/values-ro-rRO/strings.xml index 2b7b773b..9444f572 100644 --- a/app/src/main/res/values-ro-rRO/strings.xml +++ b/app/src/main/res/values-ro-rRO/strings.xml @@ -500,7 +500,6 @@ Furnizează un fișier de backup 2FAS autentificator. Furnizează un fișier export/copie de rezervă Aegis. Furnizează un fişier de export de Autentificator Plus obţinut prin Setări -> Copie de rezervă & Restore -> Export ca Text şi HTML. - Furnizează fișierul cu parole provenit de la Authenticator Pro, fișier ce poate fi obținut prin Setări -> Backup -> Backup criptat (recomandat). Furnizează o copie a /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, localizată în directorul de stocare internă al Authy. Furnizați un fişier de export/copie de rezervă andOTP. Furnizează un fișier de backup din aplicația Bitwarden. Fișierele criptate nu sunt suportate. diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml index 5a7a3d85..c9e52ed7 100644 --- a/app/src/main/res/values-ru-rRU/strings.xml +++ b/app/src/main/res/values-ru-rRU/strings.xml @@ -525,7 +525,6 @@ Необходим файл резервной копии 2FAS. Необходим файл экспорта/резервной копии Aegis. Необходим файл экспорта Authenticator Plus, полученный через «Настройки» → «Рез. копия и восстановление» → «Экспорт текста и HTML». - Необходим файл экспорта Authenticator Pro, полученный через «Настройки» → «Резервное копирование» → «Резервное копирование в зашифрованный файл (рекомендуется)». Необходима копия файла /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, расположенного в папке «Authy» во внутренней памяти. Необходим файл экспорта/резервной копии andOTP. Необходим файл экспорта/резервной копии Bitwarden. Зашифрованные файлы не поддерживаются. diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index c135f526..fc530014 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -499,7 +499,6 @@ Tillhandahåll en säkerhetskopieringsfil från 2FAS Authenticator. Tillhandahåll en export-/säkerhetskopieringsfil från Aegis. Tillhandahåll en exportfil från Authenticator Plus som har erhållits genom Settings -> Backup & Restore -> Export as Text and HTML. - Tillhandahåll en exportfil från Authenticator Pro som har erhållits genom Inställningar -> Säkerhetskopiera -> Säkerhetskopiera till krypterad fil (rekommenderas). Tillhandahåll en kopia av /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, som finns i den interna lagringskatalogen för Authy. Tillhandahåll en export-/säkerhetskopieringsfil från andOTP. Tillhandahåll en export-/säkerhetskopieringsfil från Bitwarden. Krypterade filer stöds ej. diff --git a/app/src/main/res/values-tr-rTR/strings.xml b/app/src/main/res/values-tr-rTR/strings.xml index 95bc7bcd..75594245 100644 --- a/app/src/main/res/values-tr-rTR/strings.xml +++ b/app/src/main/res/values-tr-rTR/strings.xml @@ -432,7 +432,6 @@ 2FAS Authenticator dışa aktarım dosyasını sağlayın. Aegis dışarı aktarım/yedek dosyası sağlayın. Ayarlar -> Yedekleme & Geri Yükleme -> Metin ya da HTML olarak dışa aktar yolunu izleyerek bir Authenticator Plus dışa aktarım dosyası sağlayın. - Ayarlar ->; Yedekle ->; Şifreli dosyaya yedekle (önerilir) aracılığıyla elde edilen bir Authenticator Pro dışa aktarma dosyası sağlar. /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xmldosyasını sağlayın, Authy\'nin dahili depolama konumunda bulunabilir. andOTP dışa aktarım dosyasını sağlayın. Bitwarden\'a ait bir yedekleme/aktarma dosyası sağlayın. Şifrelenmiş dosyalar desteklenmiyor. diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml index d4c95d4c..72f5d93e 100644 --- a/app/src/main/res/values-vi-rVN/strings.xml +++ b/app/src/main/res/values-vi-rVN/strings.xml @@ -487,7 +487,6 @@ Cung cấp một tập tin sao lưu 2FAS Authenticator. Cung cấp một file xuất/sao lưu Aegis. Cung cấp một tập tin xuất Authenticator Plus được nhận qua Cài đặt -> Sao lưu & Khôi phục -> Xuất dưới dạng Văn bản và HTML. - Cung cấp tập tin xuất Authenticator Pro có được thông qua Cài đặt -> Sao lưu -> Sao lưu tập tin mã hóa (đề xuất). Cung cấp một bản sao của /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, nằm trong thư mục bộ nhớ trong của Authy. Cung cấp một tập tin xuất/sao lưu andOTP. Hãy chọn tập tin xuất/sao lưu của Bitwarden. Tập tin mã hoá không được hỗ trợ. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 94479df0..5629658c 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -485,7 +485,6 @@ 提供一个 2FAS 身份验证器备份文件。 提供一个 Aegis 导出/备份文件。 提供一个通过 设置 -> 备份 & 还原 -> 导出为纯文本和 HTML 获得的 Authenticator Plus 导出文件。 - 提供一个用如下方式获取的 Authenticator Pro 导出文件:设置 -> 备份 -> 备份到加密文件(推荐) 提供 /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml 的一个副本,位于 Authy 的内部存储目录。 提供 andOTP 导出/备份文件。 提供 Bitwarden 导出 / 备份文件。不支持加密的文件。 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2725c77f..e115154b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -530,7 +530,6 @@ Supply a 2FAS Authenticator backup file. Supply an Aegis export/backup file. Supply an Authenticator Plus export file obtained through Settings -> Backup & Restore -> Export as Text and HTML. - Supply an Authenticator Pro export file obtained through Settings -> Back up -> Back up to encrypted file (recommended). Supply a copy of /data/data/com.authy.authy/shared_prefs/com.authy.storage.tokens.authenticator.xml, located in the internal storage directory of Authy. Supply an andOTP export/backup file. Supply a Bitwarden export/backup file. Encrypted files are not supported. @@ -545,6 +544,7 @@ Supply a copy of /data/data/com.azure.authenticator/databases/PhoneFactor, located in the internal storage directory of Microsoft Authenticator. Supply a plain text file with a Google Authenticator URI on each line. Steam v3.0 and newer are not supported. Supply a copy of /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json, located in the internal storage directory of Steam. + Supply a Stratum export file obtained through Settings -> Back up -> Back up to encrypted file (recommended). Supply a TOTP Authenticator export file. Supply a WinAuth export file. Assign icons diff --git a/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java b/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java index 959252c6..4742eabd 100644 --- a/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java +++ b/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java @@ -149,32 +149,32 @@ public class DatabaseImporterTest { } @Test - public void testImportAuthProEncrypted() throws DatabaseImporterException, IOException, OtpInfoException { - List entries = importEncrypted(AuthenticatorProImporter.class, "authpro_encrypted.bin", state -> { + public void testImportStratumEncrypted() throws DatabaseImporterException, IOException, OtpInfoException { + List entries = importEncrypted(StratumImporter.class, "stratum_encrypted.bin", state -> { char[] password = "test".toCharArray(); - return ((AuthenticatorProImporter.EncryptedState) state).decrypt(password); + return ((StratumImporter.EncryptedState) state).decrypt(password); }); checkImportedEntries(entries); } @Test - public void testImportAuthProEncryptedLegacy() throws DatabaseImporterException, IOException, OtpInfoException { - List entries = importEncrypted(AuthenticatorProImporter.class, "authpro_encrypted_legacy.bin", state -> { + public void testImportStratumEncryptedLegacy() throws DatabaseImporterException, IOException, OtpInfoException { + List entries = importEncrypted(StratumImporter.class, "stratum_encrypted_legacy.bin", state -> { char[] password = "test".toCharArray(); - return ((AuthenticatorProImporter.LegacyEncryptedState) state).decrypt(password); + return ((StratumImporter.LegacyEncryptedState) state).decrypt(password); }); checkImportedEntries(entries); } @Test - public void testImportAuthProInternal() throws DatabaseImporterException, IOException, OtpInfoException { - List entries = importPlain(AuthenticatorProImporter.class, "authpro_internal.db", true); + public void testImportStratumInternal() throws DatabaseImporterException, IOException, OtpInfoException { + List entries = importPlain(StratumImporter.class, "stratum_internal.db", true); checkImportedEntries(entries); } @Test - public void testImportAuthProPlain() throws DatabaseImporterException, IOException, OtpInfoException { - List entries = importPlain(AuthenticatorProImporter.class, "authpro_plain.json"); + public void testImportStratumPlain() throws DatabaseImporterException, IOException, OtpInfoException { + List entries = importPlain(StratumImporter.class, "stratum_plain.json"); checkImportedEntries(entries); } diff --git a/app/src/test/resources/com/beemdevelopment/aegis/importers/authpro_encrypted.bin b/app/src/test/resources/com/beemdevelopment/aegis/importers/stratum_encrypted.bin similarity index 100% rename from app/src/test/resources/com/beemdevelopment/aegis/importers/authpro_encrypted.bin rename to app/src/test/resources/com/beemdevelopment/aegis/importers/stratum_encrypted.bin diff --git a/app/src/test/resources/com/beemdevelopment/aegis/importers/authpro_encrypted_legacy.bin b/app/src/test/resources/com/beemdevelopment/aegis/importers/stratum_encrypted_legacy.bin similarity index 100% rename from app/src/test/resources/com/beemdevelopment/aegis/importers/authpro_encrypted_legacy.bin rename to app/src/test/resources/com/beemdevelopment/aegis/importers/stratum_encrypted_legacy.bin diff --git a/app/src/test/resources/com/beemdevelopment/aegis/importers/authpro_internal.db b/app/src/test/resources/com/beemdevelopment/aegis/importers/stratum_internal.db similarity index 100% rename from app/src/test/resources/com/beemdevelopment/aegis/importers/authpro_internal.db rename to app/src/test/resources/com/beemdevelopment/aegis/importers/stratum_internal.db diff --git a/app/src/test/resources/com/beemdevelopment/aegis/importers/authpro_plain.json b/app/src/test/resources/com/beemdevelopment/aegis/importers/stratum_plain.json similarity index 100% rename from app/src/test/resources/com/beemdevelopment/aegis/importers/authpro_plain.json rename to app/src/test/resources/com/beemdevelopment/aegis/importers/stratum_plain.json From e59df63e94e68fdc826028599e26af5f408b83bd Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Sun, 5 Jan 2025 16:11:37 +0100 Subject: [PATCH 17/44] Store non-SVG icons at a maximum of 512x512 and migrate existing icons --- .../aegis/helpers/BitmapHelper.java | 32 ++++++++++ .../aegis/ui/EditEntryActivity.java | 20 +++--- .../aegis/ui/ImportEntriesActivity.java | 40 +++++++++--- .../aegis/ui/MainActivity.java | 38 ++++++++++- .../aegis/ui/tasks/IconOptimizationTask.java | 63 +++++++++++++++++++ .../beemdevelopment/aegis/vault/Vault.java | 14 +++++ .../aegis/vault/VaultEntry.java | 10 ++- .../aegis/vault/VaultEntryIcon.java | 8 ++- .../aegis/vault/VaultEntryIconException.java | 11 ++++ .../aegis/vault/VaultRepository.java | 8 +++ app/src/main/res/values/strings.xml | 2 + 11 files changed, 224 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/com/beemdevelopment/aegis/ui/tasks/IconOptimizationTask.java create mode 100644 app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntryIconException.java diff --git a/app/src/main/java/com/beemdevelopment/aegis/helpers/BitmapHelper.java b/app/src/main/java/com/beemdevelopment/aegis/helpers/BitmapHelper.java index a97fb6a4..339c1760 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/helpers/BitmapHelper.java +++ b/app/src/main/java/com/beemdevelopment/aegis/helpers/BitmapHelper.java @@ -1,6 +1,13 @@ package com.beemdevelopment.aegis.helpers; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import com.beemdevelopment.aegis.icons.IconType; +import com.beemdevelopment.aegis.vault.VaultEntryIcon; + +import java.io.ByteArrayOutputStream; +import java.util.Objects; public class BitmapHelper { private BitmapHelper() { @@ -28,4 +35,29 @@ public class BitmapHelper { return Bitmap.createScaledBitmap(bitmap, width, height, true); } + + public static boolean isVaultEntryIconOptimized(VaultEntryIcon icon) { + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inJustDecodeBounds = true; + BitmapFactory.decodeByteArray(icon.getBytes(), 0, icon.getBytes().length, opts); + return opts.outWidth <= VaultEntryIcon.MAX_DIMENS && opts.outHeight <= VaultEntryIcon.MAX_DIMENS; + } + + public static VaultEntryIcon toVaultEntryIcon(Bitmap bitmap, IconType iconType) { + if (bitmap.getWidth() > VaultEntryIcon.MAX_DIMENS + || bitmap.getHeight() > VaultEntryIcon.MAX_DIMENS) { + bitmap = resize(bitmap, VaultEntryIcon.MAX_DIMENS, VaultEntryIcon.MAX_DIMENS); + } + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + if (Objects.equals(iconType, IconType.PNG)) { + bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); + } else { + iconType = IconType.JPEG; + bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream); + } + + byte[] data = stream.toByteArray(); + return new VaultEntryIcon(data, iconType); + } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java index 086559de..a7c92591 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/EditEntryActivity.java @@ -35,12 +35,14 @@ import com.beemdevelopment.aegis.encoding.Base32; import com.beemdevelopment.aegis.encoding.EncodingException; import com.beemdevelopment.aegis.encoding.Hex; import com.beemdevelopment.aegis.helpers.AnimationsHelper; +import com.beemdevelopment.aegis.helpers.BitmapHelper; import com.beemdevelopment.aegis.helpers.DropdownHelper; import com.beemdevelopment.aegis.helpers.EditTextHelper; import com.beemdevelopment.aegis.helpers.SafHelper; import com.beemdevelopment.aegis.helpers.SimpleAnimationEndListener; import com.beemdevelopment.aegis.helpers.SimpleTextWatcher; import com.beemdevelopment.aegis.helpers.TextDrawableHelper; +import com.beemdevelopment.aegis.helpers.ViewHelper; import com.beemdevelopment.aegis.icons.IconPack; import com.beemdevelopment.aegis.icons.IconType; import com.beemdevelopment.aegis.otp.GoogleAuthInfo; @@ -59,7 +61,6 @@ import com.beemdevelopment.aegis.ui.tasks.ImportFileTask; import com.beemdevelopment.aegis.ui.views.IconAdapter; import com.beemdevelopment.aegis.util.Cloner; import com.beemdevelopment.aegis.util.IOUtils; -import com.beemdevelopment.aegis.helpers.ViewHelper; import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.vault.VaultEntryIcon; import com.beemdevelopment.aegis.vault.VaultGroup; @@ -76,7 +77,6 @@ import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputLayout; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -103,6 +103,7 @@ public class EditEntryActivity extends AegisActivity { // keep track of icon changes separately as the generated jpeg's are not deterministic private boolean _hasChangedIcon = false; private IconPack.Icon _selectedIcon; + private String _pickedMimeType; private ShapeableImageView _iconView; private ImageView _saveImageButton; @@ -140,8 +141,8 @@ public class EditEntryActivity extends AegisActivity { if (activityResult.getResultCode() != RESULT_OK || data == null || data.getData() == null) { return; } - String fileType = SafHelper.getMimeType(this, data.getData()); - if (fileType != null && fileType.equals(IconType.SVG.toMimeType())) { + _pickedMimeType = SafHelper.getMimeType(this, data.getData()); + if (_pickedMimeType != null && _pickedMimeType.equals(IconType.SVG.toMimeType())) { ImportFileTask.Params params = new ImportFileTask.Params(data.getData(), "icon", null); ImportFileTask task = new ImportFileTask(this, result -> { if (result.getError() == null) { @@ -804,11 +805,12 @@ public class EditEntryActivity extends AegisActivity { VaultEntryIcon icon; if (_selectedIcon == null) { Bitmap bitmap = ((BitmapDrawable) _iconView.getDrawable()).getBitmap(); - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - // the quality parameter is ignored for PNG - bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); - byte[] data = stream.toByteArray(); - icon = new VaultEntryIcon(data, IconType.PNG); + IconType iconType = _pickedMimeType == null + ? IconType.INVALID : IconType.fromMimeType(_pickedMimeType); + if (iconType == IconType.INVALID) { + iconType = bitmap.hasAlpha() ? IconType.PNG : IconType.JPEG; + } + icon = BitmapHelper.toVaultEntryIcon(bitmap, iconType); } else { byte[] iconBytes; try (FileInputStream inStream = new FileInputStream(_selectedIcon.getFile())){ diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java index 0bf70b36..9a5cec40 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java @@ -15,17 +15,21 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.beemdevelopment.aegis.R; +import com.beemdevelopment.aegis.helpers.BitmapHelper; import com.beemdevelopment.aegis.helpers.FabScrollHelper; +import com.beemdevelopment.aegis.helpers.ViewHelper; +import com.beemdevelopment.aegis.icons.IconType; import com.beemdevelopment.aegis.importers.DatabaseImporter; import com.beemdevelopment.aegis.importers.DatabaseImporterEntryException; import com.beemdevelopment.aegis.importers.DatabaseImporterException; import com.beemdevelopment.aegis.ui.dialogs.Dialogs; import com.beemdevelopment.aegis.ui.models.ImportEntry; +import com.beemdevelopment.aegis.ui.tasks.IconOptimizationTask; import com.beemdevelopment.aegis.ui.tasks.RootShellTask; import com.beemdevelopment.aegis.ui.views.ImportEntriesAdapter; import com.beemdevelopment.aegis.util.UUIDMap; -import com.beemdevelopment.aegis.helpers.ViewHelper; import com.beemdevelopment.aegis.vault.VaultEntry; +import com.beemdevelopment.aegis.vault.VaultEntryIcon; import com.beemdevelopment.aegis.vault.VaultGroup; import com.beemdevelopment.aegis.vault.VaultRepository; import com.google.android.material.dialog.MaterialAlertDialogBuilder; @@ -40,8 +44,10 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; public class ImportEntriesActivity extends AegisActivity { private View _view; @@ -172,7 +178,7 @@ public class ImportEntriesActivity extends AegisActivity { state.decrypt(this, new DatabaseImporter.DecryptListener() { @Override public void onStateDecrypted(DatabaseImporter.State state) { - importDatabase(state); + processDecryptedImporterState(state); } @Override @@ -187,7 +193,7 @@ public class ImportEntriesActivity extends AegisActivity { } }); } else { - importDatabase(state); + processDecryptedImporterState(state); } } catch (DatabaseImporterException e) { e.printStackTrace(); @@ -195,8 +201,7 @@ public class ImportEntriesActivity extends AegisActivity { } } - private void importDatabase(DatabaseImporter.State state) { - List importEntries = new ArrayList<>(); + private void processDecryptedImporterState(DatabaseImporter.State state) { DatabaseImporter.Result result; try { result = state.convert(); @@ -206,8 +211,29 @@ public class ImportEntriesActivity extends AegisActivity { return; } - UUIDMap entries = result.getEntries(); - for (VaultEntry entry : entries.getValues()) { + Map icons = result.getEntries().getValues().stream() + .filter(e -> e.getIcon() != null + && !e.getIcon().getType().equals(IconType.SVG) + && !BitmapHelper.isVaultEntryIconOptimized(e.getIcon())) + .collect(Collectors.toMap(VaultEntry::getUUID, VaultEntry::getIcon)); + if (!icons.isEmpty()) { + IconOptimizationTask task = new IconOptimizationTask(this, newIcons -> { + for (Map.Entry mapEntry : newIcons.entrySet()) { + VaultEntry entry = result.getEntries().getByUUID(mapEntry.getKey()); + entry.setIcon(mapEntry.getValue()); + } + + processImporterResult(result); + }); + task.execute(getLifecycle(), icons); + } else { + processImporterResult(result); + } + } + + private void processImporterResult(DatabaseImporter.Result result) { + List importEntries = new ArrayList<>(); + for (VaultEntry entry : result.getEntries().getValues()) { ImportEntry importEntry = new ImportEntry(entry); _adapter.addEntry(importEntry); importEntries.add(importEntry); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java index 1dc5cbd5..0a4767c8 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java @@ -44,9 +44,12 @@ import com.beemdevelopment.aegis.GroupPlaceholderType; import com.beemdevelopment.aegis.Preferences; import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.SortCategory; +import com.beemdevelopment.aegis.helpers.BitmapHelper; import com.beemdevelopment.aegis.helpers.DropdownHelper; import com.beemdevelopment.aegis.helpers.FabScrollHelper; import com.beemdevelopment.aegis.helpers.PermissionHelper; +import com.beemdevelopment.aegis.helpers.ViewHelper; +import com.beemdevelopment.aegis.icons.IconType; import com.beemdevelopment.aegis.otp.GoogleAuthInfo; import com.beemdevelopment.aegis.otp.GoogleAuthInfoException; import com.beemdevelopment.aegis.otp.OtpInfoException; @@ -55,12 +58,13 @@ import com.beemdevelopment.aegis.ui.fragments.preferences.BackupsPreferencesFrag import com.beemdevelopment.aegis.ui.fragments.preferences.PreferencesFragment; import com.beemdevelopment.aegis.ui.models.ErrorCardInfo; import com.beemdevelopment.aegis.ui.models.VaultGroupModel; +import com.beemdevelopment.aegis.ui.tasks.IconOptimizationTask; import com.beemdevelopment.aegis.ui.tasks.QrDecodeTask; import com.beemdevelopment.aegis.ui.views.EntryListView; import com.beemdevelopment.aegis.util.TimeUtils; import com.beemdevelopment.aegis.util.UUIDMap; -import com.beemdevelopment.aegis.helpers.ViewHelper; import com.beemdevelopment.aegis.vault.VaultEntry; +import com.beemdevelopment.aegis.vault.VaultEntryIcon; import com.beemdevelopment.aegis.vault.VaultFile; import com.beemdevelopment.aegis.vault.VaultGroup; import com.beemdevelopment.aegis.vault.VaultRepository; @@ -724,6 +728,37 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene } } + private void checkIconOptimization() { + if (!_vaultManager.getVault().areIconsOptimized()) { + Map oldIcons = _vaultManager.getVault().getEntries().stream() + .filter(e -> e.getIcon() != null + && !e.getIcon().getType().equals(IconType.SVG) + && !BitmapHelper.isVaultEntryIconOptimized(e.getIcon())) + .collect(Collectors.toMap(VaultEntry::getUUID, VaultEntry::getIcon)); + + if (!oldIcons.isEmpty()) { + IconOptimizationTask task = new IconOptimizationTask(this, this::onIconsOptimized); + task.execute(getLifecycle(), oldIcons); + } else { + onIconsOptimized(Collections.emptyMap()); + } + } + } + + private void onIconsOptimized(Map newIcons) { + for (Map.Entry mapEntry : newIcons.entrySet()) { + VaultEntry entry = _vaultManager.getVault().getEntryByUUID(mapEntry.getKey()); + entry.setIcon(mapEntry.getValue()); + } + + _vaultManager.getVault().setIconsOptimized(true); + saveAndBackupVault(); + + if (!newIcons.isEmpty()) { + _entryListView.setEntries(_vaultManager.getVault().getEntries()); + } + } + private void onDecryptResult() { _auditLogRepository.addVaultUnlockedEvent(); @@ -912,6 +947,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene } else { loadEntries(); checkTimeSyncSetting(); + checkIconOptimization(); } _lockBackPressHandler.setEnabled( diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/IconOptimizationTask.java b/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/IconOptimizationTask.java new file mode 100644 index 00000000..d7be90d5 --- /dev/null +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/IconOptimizationTask.java @@ -0,0 +1,63 @@ +package com.beemdevelopment.aegis.ui.tasks; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import com.beemdevelopment.aegis.R; +import com.beemdevelopment.aegis.helpers.BitmapHelper; +import com.beemdevelopment.aegis.icons.IconType; +import com.beemdevelopment.aegis.vault.VaultEntryIcon; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class IconOptimizationTask extends ProgressDialogTask, Map> { + private final Callback _cb; + + public IconOptimizationTask(Context context, Callback cb) { + super(context, context.getString(R.string.optimizing_icon)); + _cb = cb; + } + + @Override + protected Map doInBackground(Map... params) { + Map res = new HashMap<>(); + Context context = getDialog().getContext(); + + int i = 0; + Map icons = params[0]; + for (Map.Entry entry : icons.entrySet()) { + if (icons.size() > 1) { + publishProgress(context.getString(R.string.optimizing_icon_multiple, i + 1, icons.size())); + } + i++; + + VaultEntryIcon oldIcon = entry.getValue(); + if (oldIcon == null || oldIcon.getType().equals(IconType.SVG)) { + continue; + } + if (BitmapHelper.isVaultEntryIconOptimized(oldIcon)) { + continue; + } + + Bitmap bitmap = BitmapFactory.decodeByteArray(oldIcon.getBytes(), 0, oldIcon.getBytes().length); + VaultEntryIcon newIcon = BitmapHelper.toVaultEntryIcon(bitmap, oldIcon.getType()); + bitmap.recycle(); + res.put(entry.getKey(), newIcon); + } + + return res; + } + + @Override + protected void onPostExecute(Map results) { + super.onPostExecute(results); + _cb.onTaskFinished(results); + } + + public interface Callback { + void onTaskFinished(Map results); + } +} diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/Vault.java b/app/src/main/java/com/beemdevelopment/aegis/vault/Vault.java index ff90046d..74f8a126 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/Vault.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/Vault.java @@ -15,6 +15,7 @@ public class Vault { private static final int VERSION = 3; private final UUIDMap _entries = new UUIDMap<>(); private final UUIDMap _groups = new UUIDMap<>(); + private boolean _iconsOptimized = true; // Whether we've migrated the group list to the new format while parsing the vault private boolean _isGroupsMigrationFresh = false; @@ -42,6 +43,7 @@ public class Vault { obj.put("version", VERSION); obj.put("entries", entriesArray); obj.put("groups", groupsArray); + obj.put("icons_optimized", _iconsOptimized); return obj; } catch (JSONException e) { @@ -86,6 +88,10 @@ public class Vault { entries.add(entry); } + + if (!obj.optBoolean("icons_optimized")) { + vault.setIconsOptimized(false); + } } catch (VaultEntryException | JSONException e) { throw new VaultException(e); } @@ -101,6 +107,14 @@ public class Vault { return _isGroupsMigrationFresh; } + public void setIconsOptimized(boolean optimized) { + _iconsOptimized = optimized; + } + + public boolean areIconsOptimized() { + return _iconsOptimized; + } + public boolean migrateOldGroup(VaultEntry entry) { if (entry.getOldGroup() != null) { Optional optGroup = getGroups().getValues() diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntry.java b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntry.java index 080580c9..1fafb5ab 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntry.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntry.java @@ -103,8 +103,14 @@ public class VaultEntry extends UUIDMap.Value { entry.setOldGroup(JsonUtils.optString(obj, "group")); } - VaultEntryIcon icon = VaultEntryIcon.fromJson(obj); - entry.setIcon(icon); + // Silently ignore any errors that occur when trying to parse the icon of an + // entry. This allows us to introduce new icon types in the future (e.g. WebP) + // without breaking compatibility with older versions of Aegis. + try { + VaultEntryIcon icon = VaultEntryIcon.fromJson(obj); + entry.setIcon(icon); + } catch (VaultEntryIconException ignored) { + } return entry; } catch (OtpInfoException | JSONException e) { diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntryIcon.java b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntryIcon.java index 44c7babb..f45a71ec 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntryIcon.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntryIcon.java @@ -23,6 +23,8 @@ public class VaultEntryIcon implements Serializable { private final byte[] _hash; private final IconType _type; + public static final int MAX_DIMENS = 512; + public VaultEntryIcon(byte @NonNull [] bytes, @NonNull IconType type) { this(bytes, type, generateHash(bytes, type)); } @@ -70,7 +72,7 @@ public class VaultEntryIcon implements Serializable { } @Nullable - static VaultEntryIcon fromJson(@NonNull JSONObject obj) throws VaultEntryException { + static VaultEntryIcon fromJson(@NonNull JSONObject obj) throws VaultEntryIconException { try { Object icon = obj.get("icon"); if (icon == JSONObject.NULL) { @@ -80,7 +82,7 @@ public class VaultEntryIcon implements Serializable { String mime = JsonUtils.optString(obj, "icon_mime"); IconType iconType = mime == null ? IconType.JPEG : IconType.fromMimeType(mime); if (iconType == IconType.INVALID) { - throw new VaultEntryException(String.format("Bad icon MIME type: %s", mime)); + throw new VaultEntryIconException(String.format("Bad icon MIME type: %s", mime)); } byte[] iconBytes = Base64.decode((String) icon); @@ -92,7 +94,7 @@ public class VaultEntryIcon implements Serializable { return new VaultEntryIcon(iconBytes, iconType); } catch (JSONException | EncodingException e) { - throw new VaultEntryException(e); + throw new VaultEntryIconException(e); } } diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntryIconException.java b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntryIconException.java new file mode 100644 index 00000000..2391de3e --- /dev/null +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntryIconException.java @@ -0,0 +1,11 @@ +package com.beemdevelopment.aegis.vault; + +public class VaultEntryIconException extends Exception { + public VaultEntryIconException(Throwable cause) { + super(cause); + } + + public VaultEntryIconException(String message) { + super(message); + } +} diff --git a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultRepository.java b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultRepository.java index 7792c953..865d126e 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultRepository.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultRepository.java @@ -333,6 +333,14 @@ public class VaultRepository { return _vault.isGroupsMigrationFresh(); } + public boolean areIconsOptimized() { + return _vault.areIconsOptimized(); + } + + public void setIconsOptimized(boolean optimized) { + _vault.setIconsOptimized(optimized); + } + public VaultFileCredentials getCredentials() { return _creds == null ? null : _creds.clone(); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2725c77f..9683b2f9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -236,6 +236,8 @@ Please select an authentication method Encrypting the vault Exporting the vault + Optimizing icon + Optimizing icons %1$d/%2$d Reading file Requesting root access Analyzing QR code From d98e23a1e59c76b8a623eba78612471ece05b68c Mon Sep 17 00:00:00 2001 From: David Creswick Date: Sun, 5 Jan 2025 16:18:01 -0600 Subject: [PATCH 18/44] delete temporary export file when finished --- .../java/com/beemdevelopment/aegis/ui/tasks/ExportTask.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/ExportTask.java b/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/ExportTask.java index 590e05d0..79943ac2 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/ExportTask.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/tasks/ExportTask.java @@ -34,6 +34,8 @@ public class ExportTask extends ProgressDialogTask return null; } catch (IOException e) { return e; + } finally { + boolean ignored = params.getFile().delete(); } } From 919e6854e821430af3c68832f07825edefa7428c Mon Sep 17 00:00:00 2001 From: David Creswick Date: Sun, 5 Jan 2025 16:31:49 -0600 Subject: [PATCH 19/44] add test for html exports Do some basic tests of the html export code. - Make sure that a file was created. - Make sure that the file can be parsed by an xml parser without error. - Make sure that the document tag is "html". --- .../aegis/BackupExportTest.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/java/com/beemdevelopment/aegis/BackupExportTest.java b/app/src/androidTest/java/com/beemdevelopment/aegis/BackupExportTest.java index 9f15019b..e0151395 100644 --- a/app/src/androidTest/java/com/beemdevelopment/aegis/BackupExportTest.java +++ b/app/src/androidTest/java/com/beemdevelopment/aegis/BackupExportTest.java @@ -61,13 +61,20 @@ import org.junit.Test; import org.junit.rules.RuleChain; import org.junit.rules.TestRule; import org.junit.runner.RunWith; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.List; +import java.util.Locale; import javax.crypto.Cipher; import javax.crypto.SecretKey; @@ -183,7 +190,9 @@ public class BackupExportTest extends AegisTest { onView(withText(R.string.export_format_html)).inRoot(RootMatchers.isPlatformPopup()).perform(click()); onView(withId(android.R.id.button1)).perform(click()); onView(withId(R.id.checkbox_accept)).perform(click()); - doExport(); + File file = doExport(); + + checkHtmlExport(file); } @Test @@ -196,7 +205,9 @@ public class BackupExportTest extends AegisTest { onView(withText(R.string.export_format_html)).inRoot(RootMatchers.isPlatformPopup()).perform(click()); onView(withId(android.R.id.button1)).perform(click()); onView(withId(R.id.checkbox_accept)).perform(click()); - doExport(); + File file = doExport(); + + checkHtmlExport(file); } @Test @@ -380,6 +391,26 @@ public class BackupExportTest extends AegisTest { checkReadEntries(entries); } + private void checkHtmlExport(File file) { + try (InputStream inStream = new FileInputStream(file)) { + Reader inReader = new InputStreamReader(inStream, StandardCharsets.UTF_8); + XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); + XmlPullParser parser = factory.newPullParser(); + parser.setInput(inReader); + while (parser.getEventType() != XmlPullParser.START_TAG) { + parser.next(); + } + if (!parser.getName().toLowerCase(Locale.ROOT).equals("html")) { + throw new RuntimeException("not an html document!"); + } + while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { + parser.next(); + } + } catch (IOException | XmlPullParserException e) { + throw new RuntimeException("Unable to read html export file", e); + } + } + private void checkReadEntries(Collection entries) { List vectors = VaultEntries.get(); assertEquals(vectors.size(), entries.size()); From e8bf7b0506e70bb05dafa1fb95808ab84a0c622c Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Sun, 12 Jan 2025 18:49:41 +0100 Subject: [PATCH 20/44] Update translations from Crowdin --- app/src/main/res/values-ar-rSA/strings.xml | 43 +++++++++++++++++++++- app/src/main/res/values-bg-rBG/strings.xml | 1 + app/src/main/res/values-ca-rES/strings.xml | 3 ++ app/src/main/res/values-cs-rCZ/strings.xml | 1 + app/src/main/res/values-da-rDK/strings.xml | 1 + app/src/main/res/values-de-rDE/strings.xml | 3 ++ app/src/main/res/values-el-rGR/strings.xml | 3 ++ app/src/main/res/values-es-rES/strings.xml | 39 +++++++++++--------- app/src/main/res/values-fr-rFR/strings.xml | 1 + app/src/main/res/values-fy-rNL/strings.xml | 1 + app/src/main/res/values-hu-rHU/strings.xml | 3 +- app/src/main/res/values-lv-rLV/strings.xml | 1 + app/src/main/res/values-nl-rNL/strings.xml | 1 + app/src/main/res/values-pl-rPL/strings.xml | 3 ++ app/src/main/res/values-pt-rBR/strings.xml | 3 ++ app/src/main/res/values-ru-rRU/strings.xml | 1 + app/src/main/res/values-sv-rSE/strings.xml | 5 ++- app/src/main/res/values-vi-rVN/strings.xml | 37 ++++++++++--------- app/src/main/res/values-zh-rCN/strings.xml | 1 + 19 files changed, 111 insertions(+), 40 deletions(-) diff --git a/app/src/main/res/values-ar-rSA/strings.xml b/app/src/main/res/values-ar-rSA/strings.xml index 9b0ed729..59308d91 100644 --- a/app/src/main/res/values-ar-rSA/strings.xml +++ b/app/src/main/res/values-ar-rSA/strings.xml @@ -46,8 +46,13 @@ حدد عدد الأرقام لتجميع الرموز حسبها اضهِر اسم الحساب أظهِر الرمز التالي + ولّد وأظهِر الكود التالي قبل الوقت + أشر متى تكون الرموز على وشك الانتهاء + غيّر لون الرموز البرمجية وجعلها غير واضحة عندما تكون على وشك الانتهاء + غيّر لون الرموز عندما تكون على وشك الانتهاء اضهِر اسم الحساب فقط عند الضرورة أضهِر أسماء الحسابات فقط عندما يشتركون نفس المصدر. سيتم إخفاء أسماء الحسابات الأخرى. + تم تجاوز هذا الإعداد بوضع عرض البلاط. سيتم عرض اسم الحساب أسفل المُصدّر. استيراد من ملف استيراد الرموز من ملف النسخ الاحتياطية السحابية للأندرويد @@ -59,7 +64,14 @@ أظهر تذكيرًا للاحتفاظ بنسخة احتياطية من مخزنك في حالة عدم إجراء نسخ احتياطي لآخر تغييراتك. تعطيل تذكير النسخ الاحتياطي يعني تعطيل هذا التذكير أن Aegis لن يخبرك بما إذا كان لديك تغييرات لم يتم نسخها احتياطيًا حتى الآن أم لا. هذا يعرضك لخطر فقدان الوصول إلى الرموز الخاصة بك. هل أنت متأكد أنك تريد تعطيل التذكير؟ + استراتيجية النسخ الاحتياطي + احتفظ بعدد من الإصدارات + نُسخة احتياطية واحدة + استراتيجية النسخ الاحتياطي المحددة غير موثوقة ولا يُنصح بها. فشل احتياطي واحد يمكن أن يؤدي إلى فقدان النسخة الاحتياطية الوحيدة. + حدد استراتيجية النسخ الاحتياطي + موقع النسخة الاحتياطية سيتم تخزين النسخ الاحتياطية في + سيتم تخزين النسخ الاحتياطي في اصنع نسخة احتياطية قم بعمل نسخة احتياطية يدويًّا عدد الإصدارات المراد الاحتفاظ بها @@ -72,7 +84,7 @@ احتفظ ب%1$d إصدارات من النسخ الاحتياطية احتفظ ب%1$d إصدارات من النسخ الاحتياطية - الاحتفاظ بعدد غير محدود من النُسخ الاحتياطية + احتفظ بعدد غير محدود من النُسخ الاحتياطية استيراد من تطبيق استيراد الرموز من تطبيق (يتطلب الوصول إلى الجذر root) تصدير @@ -112,6 +124,8 @@ قم بتشفير المخزن وفك قفله بكملة مرور أو مصادقة بيومترية الفتح البيومتري السماح بالمصادقة البيومترية لفتح قفل المخزن + البحث من خلال: %s + البحث في أي من الحقول التالية الاسم المصدِّر ملاحظة @@ -200,7 +214,7 @@ العداد الأرقام السر - امسح كود QR + امسح رمز QR امسح الصورة أدخل يدويًا تعيين الفتح البيومتري @@ -225,6 +239,8 @@ الرجاء تحديد طريقة مصادقة يتم تشفير المخزن يجري تصدير المخزن + تحسين الأيقونة + تحسين الأيقونات %1$d/%2$d قراءة الملف طلب صلاحية الجذر تحليل رمز QR @@ -338,6 +354,14 @@ اكتُشف تصدير Google Authenticator غير مكتمل بعض رموز QR مفقودة من الاستيراد. لم يتم العثور على الرموز التالية:\n\n%s\n\nيمكنك الاستمرار في استيراد هذا التصدير الجزئي ولكننا نوصي بإعادة المحاولة باستخدام جميع رموز QR حتى لا تخاطر بفقدان الوصول إلى أي رموز. • رمز QR %d + + استيراد %d رموز على أي حال + استيراد رمز %d على أي حال + استيراد رمزين على أي حال + استيراد %d رموز على أي حال + استيراد %d رموز على أي حال + استيراد %d رموز على أي حال + فشل استيراد تصدير Google Authenticator يحتوي التصدير على معلومات عن دُفعة غير ذات صلة. حاول استيراد دفعة واحدة في كل مرة. نتيجة لذلك، لا يمكن استيراد أي رموز @@ -410,6 +434,7 @@ تعذرت معالجة الارتباط العميق غير قادر على قراءة ومعالجة رمز QR من الملف: %s. غير قادر على معالجة النص المُشارك ك OTP + غير قادر على قراءة ومعالجة بعض رموز QR. سيتم استيراد %1$d/%2$d فقط من المدخلات. تعذّر توليد كود QR اختر صورة اختر أيقونة @@ -440,7 +465,19 @@ يعتمد Aegis على وقت النظام لتوليد الأكواد الصحيحة. انحراف بمقادر بضعة ثواني يمكن أن يؤدي إلى أكواد خاطئة. يبدوا أن جهازك غير معيّن إلى مزامنة الوقت تلقائيًا. هل ترغب بفعل ذلك الآن؟ إيقاف تحذيري. أنا أعرف ما أفعله. تم العثور على كود QR لا علاقة له. حاول إعادة تشغيل الماسح. + + تم مسح %1$d/%2$d رموز QR + تم مسح %1$d/%2$d رمز QR + تم مسح %1$d/%2$d رموز QR + تم مسح %1$d/%2$d رموز QR + تم مسح %1$d/%2$d رموز QR + تم مسح %1$d/%2$d رموز QR + + انتظرت رمز QR #%1$d، ولكن مسحت #%2$d بدلًا منه النسخ الاحتياطي للمخزن فشل مؤخرًا + فشلت محاولة النسخ الاحتياطي للمخزون باستخدام %1$s بسبب حدوث خطأ. تمت محاولة النسخ الاحتياطي %2$s. الرجاء التحقق من إعدادات النسخ الاحتياطي للتأكد من أن النسخ الاحتياطي يمكن أن يكتمل بنجاح. + + فشلت محاولة النسخ الاحتياطي الأخيرة للمخزون باستخدام %1$s لأن Aegis لم يكن لديه الإذن قراءة وجهة النسخ الاحتياطي. تمت محاولة النسخ الاحتياطي %2$s. يمكن أن يحدث هذا الخطأ إذا قمت بنقل/إعادة تسمية وجهة النسخ الاحتياطي أو إذا قمت للتو باستعادة Aegis من نسخة احتياطية. الرجاء إعادة إعداد وجهة النسخ الإحتياطي. النسخ الاحتياطية التلقائية المضنة في Aegis نظام النسخ الاحتياطي السحابي للأندرويد أحدث نسخة احتياطية قديمة (%s) @@ -521,6 +558,7 @@ يرجى توفير نسخة من /data/data/com.blizzard.messenger/shared_prefs/com.blizzard.messenger.authenticator_preferences.xml، الموجود في دليل التخزين الداخلي لـ Battle.net Authenticator. توفير نسخة من /data/data/com.duosecurity.duomobile/files/duokit/accounts.json، الموجودة في دليل التخزين الداخلي لـ DUO. قم بتوفير ملف تصدير Ente Auth. حاليا فقط الملفات غير المشفرة مدعومة. + FreeOTP 2: توفير ملف احتياطي.\nFreeOTP 1.x: توفير نسخة من /data/data/org.fedorahosted.freeotp/shared_prefs/tokens.xml، الموجود في دليل التخزين الداخلي لـ FreeOTP. توفير ملف تصدير FreeOTP +. توافق مع FreeOTP 2 هناك عدد من المشاكل في FreeOTP 2 التي يمكن أن تؤدي إلى وجود نسخ احتياطية فاسدة. سوف يحاول درع إنقاذ أكبر عدد ممكن من الإدخالات، ولكن من الممكن أن يفشل البعض أو حتى الجميع في الاستيراد. @@ -528,6 +566,7 @@ توفير نسخة من/data/data/com.azure.authenticator/databases/PhoneFactor، الموجود في دليل التخزين الداخلي لـ Microsoft Authenticator. توفير مِلَفّ نصي عادي مع Google Authenticator URI في كل سطر. لا يتم دعم Steam v3.0 والإصدارات الأحدث. توفير نسخة من/data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json، الموجود في دليل التخزين الداخلي لـ Steam. + جهّز ملف تصدير Stratum تم الحصول عليه من خلال الإعدادات -> النسخ الاحتياطي -> النسخ الاحتياطي للملف المشفر (موصى به). توفير مِلَفّ تصدير TOTP Authenticator. توفير مِلَفّ تصدير WinAuth. تعيين أيقونات diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml index 7398978f..80348f4a 100644 --- a/app/src/main/res/values-bg-rBG/strings.xml +++ b/app/src/main/res/values-bg-rBG/strings.xml @@ -513,6 +513,7 @@ Изберете копие на файла /data/data/com.azure.authenticator/databases/PhoneFactor, който се намира в папката с данни на Microsoft Authenticator. Изберете чист текстов файл с Google Authenticator URI, по един на ред. Поддържат се файлове на Steam v3.0 и по-нови издания.\n\nИзберете копие на файла /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json, който се намира в папката с данни на Steam. + Изберете файл с резервно копие на Stratum, получен от Настройки → Резервно копие → Резервно копие в шифрован файл (препотъчително). Изберете изнесен файл от TOTP Authenticator. Изберете изнесен файл от WinAuth. Задаване на икони diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index cdb7e264..e56d7070 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -227,6 +227,8 @@ Si us plau, tria un mètode d\'autenticació Xifrant la caixa forta Exporta la caixa forta + Optimitzant icona + Optimitzant icones %1$d/%2$d S\'està llegint el fitxer Demanant accés root Anàlisi del codi QR @@ -511,6 +513,7 @@ Subministra una còpia de /data/data/com.azure.authenticator/databases/PhoneFactor, que està a l\'emmagatzematge intern del teu dispositiu, al directori del Microsoft Authenticator. Subministra un fitxer de text pla amb una URI de Google Authenticator a cada línia. Steam v3.0 i posteriors no són compatibles. Proporcioneu una còpia de /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json, que es troba al directori d\'emmagatzematge intern de Steam. + Proveeix un fitxer exportat de Stratum, aconseguit a Settings > Back up > Back up to encrypted file (recommended). Subministra un fitxer exportat del TOTP Authenticator. Subministra un fitxer exportat del WinAuth. Assignar icones diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 79c7a16f..49efbcab 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -539,6 +539,7 @@ Dodejte kopii /data/data/com.azure.authenticator/databases/PhoneFactor, která se nachází v interním úložišti Microsoft Authenticator. Dodejte prostý textový soubor Google Authenticator URI na každý řádek. Steam v3.0 a novější nejsou podporovány. Dodejte kopii souboru /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json umístěného v interním úložném adresáři aplikace Steam. + Dodejte exportovaný soubor Stratum získaný přes Nastavení -> Záloha -> Exportovat do šifrovaného souboru (doporučeno). Dodejte soubor exportu TOTP. Dodejte soubor exportu WinAuth. Přiřadit ikony diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da-rDK/strings.xml index d53c5040..e37baaf5 100644 --- a/app/src/main/res/values-da-rDK/strings.xml +++ b/app/src/main/res/values-da-rDK/strings.xml @@ -513,6 +513,7 @@ Levér en kopi af /data/data/com.azure.authenticator/databases/PhoneFactor, der er placeret i den interne lagermappe i Microsoft Authenticator. Levér en almindelig tekstfil med en Google Authenticator URI på hver linje. Steam v3.0 og nyere understøttes ikke. Levér en kopi af /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json fra den interne lagermappe i Steam. + Benyt en Stratum-eksportfil genereret via Indstillinger -> Sikkerhedskopiering -> Sikkerhedskopiering til krypteret fil (anbefalet). Levér en TOTP Authenticator eksportfil. Levér en WinAuth eksportfil. Tildel ikoner diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index 828fc4c0..bae3fa7f 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -227,6 +227,8 @@ Bitte wähle eine Authentifizierungsmethode aus Verschlüsselung der Datenbank Exportieren der Datenbank + Symbol wird optimiert + Symbol %1$d/%2$d wird optimiert Datei wird gelesen Root-Zugriff wird angefordert QR-Code wird analysiert @@ -513,6 +515,7 @@ Gib eine Kopie von /data/data/com.azure.authenticator/databases/PhoneFactor an, die sich im internen Speicherverzeichnis von Microsoft Authenticator befindet. Gib eine Klartextdatei an, die in jeder Zeile eine Google-Authenticator-URI enthält. Steam v3.0 und neuer wird nicht unterstützt. Gib eine Kopie von /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json an, die sich im internen Speicherverzeichnis von Steam befindet. + Gib eine Stratum-Exportdatei an, die du über Einstellungen -> Sicherung -> Als verschlüsselte Datei sichern (empfohlen) erhältst. Gib eine TOTP-Authenticator-Exportdatei an. Gib eine WinAuth-Exportdatei an. Symbole zuweisen diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el-rGR/strings.xml index 244447c8..d681bed0 100644 --- a/app/src/main/res/values-el-rGR/strings.xml +++ b/app/src/main/res/values-el-rGR/strings.xml @@ -227,6 +227,8 @@ Παρακαλώ επιλέξτε μέθοδο ελέγχου ταυτότητας Κρυπτογράφηση κρύπτης Εξαγωγή της κρύπτης + Βελτιστοποίηση εικονιδίου + Βελτιστοποίηση εικονιδίων %1$d/%2$d Ανάγνωση αρχείου Αίτηση πρόσβασης root Ανάλυση κωδικού QR @@ -512,6 +514,7 @@ Παρέχεi ένα αντίγραφο του /data/data/com.azure.authenticator/databases/PhoneFactor , που βρίσκεται στον κατάλογο εσωτερικής αποθήκευσης του Microsoft Authenticator. Παρέχεi ένα αρχείο απλού κειμένου με ένα URI Επαληθευτή Google σε κάθε γραμμή. Το Steam v3.0 και νεότερα δεν υποστηρίζονται. Παρέχετε αντίγραφο του /data/data/com.valvesoftware. ndroid.steam.community/files/Steamguard-*.json, που βρίσκεται στον εσωτερικό κατάλογο αποθήκευσης του Steam. + Παροχή ενός αρχείου εξαγωγής Stratum που λαμβάνεται μέσω Ρυθμίσεις -> Αντίγραφα ασφαλείας -> Δημιουργία αντιγράφου ασφαλείας σε κρυπτογραφημένο αρχείο (συνιστάται). Παρέχετε ένα αρχείο εξαγωγής TOTP Authenticator. Παρέχετε ένα αρχείο εξαγωγής WinAuth. Αντιστοίχιση εικονιδίων diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 0566e604..5afcd9f1 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -22,7 +22,7 @@ Android Copias de seguridad automáticas Comportamiento - Personaliza la funcionalidad y cómo se interactua con la lista de claves. + Personaliza la funcionalidad y cómo se interactúa con la lista de claves. Apariencia Ajusta el esquema de colores, idioma y otros parámetros relacionados con el aspecto de la aplicación. Seguridad @@ -34,7 +34,7 @@ Copias de seguridad Configura copias de seguridad automáticas en una carpeta local o activa el sistema de copia de seguridad en la nube de Android. Paquetes de iconos - Gestiona e importa tus paquetes de iconos + Gestiona e importa tus paquetes de iconos. Tema Colores dinámicos Colorear la interfaz con el mismo esquema de colores de tu tema de Android @@ -43,7 +43,7 @@ Mostrar iconos Mostrar iconos al lado de cada clave Agrupación de los dígitos del código - Elige el número de dígitos por los que agrupar los códigos + Elige el número de dígitos por los que agrupar los códigos, dejando un espacio entre sí Mostrar el nombre de la cuenta Ver siguiente clave Generar y mostrar la siguiente clave antes de tiempo @@ -227,6 +227,8 @@ Elige una forma de autenticarte Cifrando la bóveda Exportando la bóveda + Optimizando el icono + Optimizando iconos: %1$d de %2$d Leyendo archivo Solicitando acceso a la raíz Analizando código QR @@ -276,9 +278,9 @@ Aún no se han realizado copias de seguridad Las copias de seguridad se cifran usando una contraseña separada configurada en la configuración de seguridad Tu dispositivo parece no tener DocumentsUI. Es un componente del sistema importante y necesario para elegir y crear archivos. Si utilizaste una herramienta para desinstalar (o hacer «debloat» de) aplicaciones que vienen de fábrica es posible que la hayas eliminado accidentalmente, tendrás que volverla a instalarla. - Se ha producido un error tratando de importar un paquete de iconos + Se ha producido un error al intentar importar un paquete de iconos El paquete de iconos a importar ya existe. ¿Quieres reemplazarlo? - Se ha producido un error tratando de eliminar un paquete de iconos + Se ha producido un error al intentar borrar un paquete de iconos %d icono %d iconos @@ -321,7 +323,7 @@ Algunos código QR de importación no están. Faltan los siguientes códigos:\n\n%s\n\nPuedes seguir adelante con esta importación parcial, pero te recomendamos volver a probar otra vez a escanear todos los códigos QR para evitar que pierdas el acceso a alguno de ellos. • código QR %d - Aún así quieres seguir con la importación de este código + Seguir con la importación de este código Seguir con la importación de estos %d códigos Ha fallado la importación de lo exportado de Google Authenticator @@ -334,8 +336,8 @@ ¿Seguro que quieres borrar este grupo? Sus elementos se moverán automáticamente a «Sin grupo». Eliminar grupos no utilizados ¿Seguro que quieres borrar todos los grupos que estén vacíos y no tengan ninguna clave dentro? - Eliminar paquete de iconos - ¿Está seguro de que desea eliminar este paquete de iconos? Las entradas que usen iconos de este paquete no se verán afectadas. + Borrar paquete de iconos + ¿Seguro que quieres borrar este paquete de iconos? Las claves que ya utilicen algún icono de este paquete no se verán afectadas. Más detalles Mostrar detalles del error Bloquear @@ -362,7 +364,7 @@ Nota Restablecer Resaltar códigos al pulsar - Resalta temporalmente cada código temporal que toques sobre los demás para que sea más fácil de distinguir + Resalta temporalmente cada clave que toques sobre las demás para que sea más fácil de distinguir Minimizar al copiar Minimiza la aplicación tras copiar claves Copiar claves en el portapapeles @@ -408,11 +410,11 @@ Novedades Código fuente, problemas e información Licencia - Aegis Authenticator está licenciado bajo GPLv3 + Aegis Authenticator se distribuye bajo los términos de la licencia GPLv3 Licencias de terceros Licencias de las bibliotecas de terceros usadas por Aegis Países Bajos - Escribir un correo + Contacta por correo electrónico Visita nuestra web Soporte Valorar @@ -451,8 +453,8 @@ No hay ninguna clave Todavía no hay ningún grupo; añade uno en la pantalla de editar claves No se encontraron grupos - Aún no se ha importado ningún paquete de iconos. Pulse el signo + para importar uno. Consejo: pruebe aegis-icons. - Sin paquetes de iconos + Aún no se ha importado ningún paquete de iconos. Pulsa «+» para importar uno. Consejo: te recomendamos que pruebes aegis-icons. + No parece haber ningún paquete de iconos Seleccione un icono Sin categorizar Hecho @@ -513,6 +515,7 @@ Suministre una copia de /data/data/com.azure.authenticator/databases/PhoneFactor, localizado en el directorio de almacenamiento interno de Microsoft Authenticator. Suministre un archivo de texto plano con una URI de Google Authenticator en cada línea. Steam v3.0 y posteriores no son compatibles. Proporcione una copia de /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json, ubicado en el directorio de almacenamiento interno de Steam. + Suministra un archivo de exportación de Stratum obtenido a través de Configuración -> Copias de seguridad -> Copia de seguridad en archivo cifrado (recomendado). Suministre un archivo exportado de TOTP Authenticator. Suministre un archivo exportado de WinAuth. Asignar iconos @@ -522,11 +525,11 @@ Grupos Resaltar el buscador al inicio Enfoca la búsqueda inmediatamente después de abrir la aplicación. - Mitades - Sin agrupación - Grupos de 2 - Grupos de 3 - Grupos de 4 + En dos mitades + Sin agrupar + En grupos de dos + En grupos de tres + En grupos de cuatro Nunca Un toque Dos toques diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml index 3b3fcfc0..d26a0912 100644 --- a/app/src/main/res/values-fr-rFR/strings.xml +++ b/app/src/main/res/values-fr-rFR/strings.xml @@ -513,6 +513,7 @@ Fournir une copie de /data/data/com.azure.authenticator/databases/PhoneFactor, situé dans le répertoire de stockage interne de Microsoft Authenticator. Fournir un fichier texte brut avec une URI Google Authenticator sur chaque ligne. Steam 3.0 et plus récents ne sont pas pris en charge. Fournissez une copie de /data/data/com.valvesoftware. ndroid.steam.community/files/Steamguard-*.json, situé dans le répertoire de stockage interne de Steam. + Fournir un export Stratum obtenu via Paramètres -> Sauvegarde -> Sauvegarder en tant que fichier chiffré (recommandé). Fournir un export TOTP Authenticator. Fournir un export WinAuth. Association des icônes diff --git a/app/src/main/res/values-fy-rNL/strings.xml b/app/src/main/res/values-fy-rNL/strings.xml index a512cd75..fedf028c 100644 --- a/app/src/main/res/values-fy-rNL/strings.xml +++ b/app/src/main/res/values-fy-rNL/strings.xml @@ -513,6 +513,7 @@ Leverje in kopy oan fan /data/data/com.azure.authenticator/databases/PhoneFactor, pleatst yn de ynterne ûnthâldmap fan Microsoft Authenticator. Leverje in tekstbestân oan mei in Google Authenticator-URI op elke rigel. Steam v3.0 en nijer wurde net stipe. Soargje foar in kopy fan /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json, te finen yn de ynterne ûnthâldmap fan Steam. + Leverje in Stratum-eksportbestân oan, ûntfongen fia Ynstellingen -> Reservekopy -> Reservekopy nei fersifere bestân (oanrekommandearre). Leverje in TOTP-autentikator-eksportbestân oan. Leverje in WinAuth-eksportbestân oan. Piktogrammen tawize diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index bea2a8d7..f08ba155 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -358,7 +358,7 @@ Itt kezelheti és törölheti a csoportokat Használati számláló visszaállítása Minden bejegyzés használati számlálójának visszaállítása - Biztos, hogy visszaállítja a széf összes bejegyzésének használati számlálóját 0-ra? + Biztos, hogy visszaállítja a széf összes bejegyzésének használati számlálóját nullára? Megjegyzés Törlés Tokenek kiemelése koppintáskor @@ -513,6 +513,7 @@ Adja meg a /data/data/com.azure.authenticator/databases/PhoneFactor másolatát, mely a Microsoft Authenticator belső háttértáron levő mappájában található. Adjon meg egy szöveges fájlt, melynek minden sorában Google Hitelesítő URI található. A Steam v3.0 és újabb verziói nem támogatottak. Adja hozzá a /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json mappából, mely a Steam belső háttértáron levő mappája. + Adjon meg egy Stratum-exportálási fájlt, amelyet a Beállítások > Biztonsági mentés > Biztonsági mentés titkosított fájlba (ajánlott) menüpontban lehet előállítani. Adjon meg egy TOTP Autheticator exportfájlt. Adjon meg egy WinAuth exportfájlt. Ikonok hozzárendelése diff --git a/app/src/main/res/values-lv-rLV/strings.xml b/app/src/main/res/values-lv-rLV/strings.xml index 6973b8bf..ace39b21 100644 --- a/app/src/main/res/values-lv-rLV/strings.xml +++ b/app/src/main/res/values-lv-rLV/strings.xml @@ -526,6 +526,7 @@ Jāiesniedz /data/data/com.azure.authenticator/databases/PhoneFactor kopija, kas atrodas iekšējās krātuves Microsoft Authenticator mapē. Jāiesniedz vienkārša teksta datne, kuras katra līnija satur vienu Google Authenticator URI. Steam v3.0 un jaunāks netiek atbalstīts. Jāiesniedz /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json kopija, kas atrodas iekšējās krātuves Steam mapē. + Jāiesniedz Stratum izgūšanas datne, kas ir iegūstama Iestatījumi -> Rezerves kopijas -> Dublēt šifrētā datnē (ieteicams). Jāiesniedz TOTP Authenticator izgūšanas datne. Jāiesniedz WinAuth izgūšanas datne. Piešķirt ikonas diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml index a395701e..4bb6353b 100644 --- a/app/src/main/res/values-nl-rNL/strings.xml +++ b/app/src/main/res/values-nl-rNL/strings.xml @@ -513,6 +513,7 @@ Lever een kopie aan van /data/data/com.azure.authenticator/databases/PhoneFactor, geplaatst in de interne opslagmap van Microsoft Authenticator. Lever een tekstbestand aan met een Google Authenticator URI op elke regel. Steam v3.0 en nieuwer worden niet ondersteund. Zorg voor een kopie van /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json, te vinden in de interne opslagmap van Steam. + Lever een Stratum-exportbestand aan verkregen via Instellingen -> Back-up -> Back-up naar versleuteld bestand (aanbevolen). Lever een TOTP Authenticator-exportbestand aan. Lever een WinAuth-exportbestand aan. Pictogrammen toewijzen diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml index 5229310d..4aa0a8c0 100644 --- a/app/src/main/res/values-pl-rPL/strings.xml +++ b/app/src/main/res/values-pl-rPL/strings.xml @@ -233,6 +233,8 @@ Wybierz metodę uwierzytelnienia Szyfrowanie sejfu Eksportowanie sejfu + Optymalizacja ikony + Optymalizacja ikon %1$d/%2$d Odczytywanie pliku Żądanie dostępu do roota Analizowanie kodu QR @@ -541,6 +543,7 @@ Steam v3.0 i nowsze nie są wspierane. Dostarcz kopię /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json, zlokalizowanego w wewnętrznym katalogu Steam. + Dostarcz plik eksportu Stratum uzyskany przez Ustawienia -> Kopia zapasowa -> Kopia zapasowa do zaszyfrowanego pliku (zalecana). Dostarcz plik eksportowy TOTP Authenticator. Dostarcz plik eksportowy WinAuth. Przypisz ikony diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 3ec74df7..1ec1953e 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -227,6 +227,8 @@ Por favor selecione um método de autenticação Criptografando o cofre Exportando o cofre + Otimizando ícone + Otimizando ícones %1$d/%2$d Lendo arquivo Solicitando acesso root Analisando QR code @@ -514,6 +516,7 @@ Por favor, configure o local de backup. Fornecer uma cópia de /data/data/com.azure.authenticator/databases/PhoneFactor, localizado no diretório de armazenamento interno do Microsoft Authenticator. Fornecer um arquivo de texto simples com um URI do Google Authenticator em cada linha. Steam v3.0 e mais recentes não são suportados. Forneça uma cópia de /data/data/com.valvesoftware. ndroid.steam.community/files/Steamguard-*.json, localizado no diretório de armazenamento interno do Steam. + Forneça um arquivo de exportação do Stratum obtido através das Configurações -> Backup -> Fazer backup para arquivo criptografado (recomendado). Fornecer um arquivo de exportação de Autenticador TOTP. Fornecer um arquivo de exportação do WinAuth. Atribuir ícones diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml index c9e52ed7..a2d7ba4a 100644 --- a/app/src/main/res/values-ru-rRU/strings.xml +++ b/app/src/main/res/values-ru-rRU/strings.xml @@ -540,6 +540,7 @@ Необходим текстовый файл с URI Google Authenticator в каждой строке. Steam v3.0 и новее не поддерживаются. Необходима копия файла /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json, расположенного в папке «Steam» во внутренней памяти. + Необходим файл экспорта Stratum, полученный через «Настройки» → «Резервное копирование» → «Резервное копирование в зашифрованный файл (рекомендуется)». Необходим файл экспорта TOTP Authenticator. Необходим файл экспорта WinAuth. Назначить значки diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index fc530014..29baf265 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -227,6 +227,8 @@ Vänligen välj en autentiseringsmetod Krypterar valvet Exporterar valvet + Optimerar ikon + Optimerar ikoner %1$d/%2$d Läser fil Begär rotåtkomst Analyserar rutkod @@ -294,7 +296,7 @@ Välj önskad kontonamnsplacering Välj önskat visningsläge Välj önskat kopieringsbeteende - Ett fel uppstod när filen skulle analyseras + Ett fel uppstod när filen skulle tolkas Fel: Filen hittades inte Ett fel uppstod när filen skulle läsas Fel: Appen är inte installerad @@ -513,6 +515,7 @@ Tillhandahåll en kopia av /data/data/com.azure.authenticator/databases/PhoneFactor, som finns i den interna lagringskatalogen för Microsoft Authenticator. Tillhandahåll en klartextfil med en Google Authenticator-URI per rad. Steam v3.0 och senare stöds inte. Tillhandahåll en kopia av /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json, som finns i den interna lagringskatalogen för Steam. + Tillhandahåll en exportfil från Stratum som har erhållits genom Inställningar -> Säkerhetskopiera -> Säkerhetskopiera till krypterad fil (rekommenderas). Tillhandahåll en exportfil från TOTP Authenticator. Tillhandahåll en exportfil från WinAuth. Tilldela ikoner diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml index 72f5d93e..76c66bdb 100644 --- a/app/src/main/res/values-vi-rVN/strings.xml +++ b/app/src/main/res/values-vi-rVN/strings.xml @@ -46,7 +46,7 @@ Chọn số lượng chữ số để gộp mã Hiện tên tài khoản Hiện mã kế tiếp - Tạo và hiỆn mã tiếp theo trước thời hạn + Hiện mã mới trước thời hạn Nhấp nháy khi mã sắp hết hạn Thay đổi màu sắc của mã và nhấp nháy khi mã sắp hết hạn Thay đổi màu sắc của mã khi mã sắp hết hạn @@ -63,17 +63,17 @@ Nhắc nhở sao lưu Hiện lời nhắc sao lưu kho của bạn trong trường hợp bạn chưa sao lưu các thay đổi mới nhất. Tắt nhắc nhở sao lưu - Tắt lời nhắc này có nghĩa là Aegis sẽ không cho bạn biết liệu bạn có những thay đổi chưa được sao lưu hay không. Điều này khiến bạn có nguy cơ mất quyền truy cập vào token của mình. Bạn có chắc muốn tắt lời nhắc? + Tắt lời nhắc này có nghĩa là Aegis sẽ không cho bạn biết liệu bạn có những thay đổi chưa được sao lưu hay không. Điều này khiến bạn có nguy cơ mất quyền truy cập vào mã của mình. Bạn có chắc muốn tắt lời nhắc? Chiến lược sao lưu - Giữ một số phiên bản - Sao lưu đơn + Nhiều bản sao + Một bản sao Chiến lược sao lưu được chọn không đáng tin cậy và không được khuyến khích. Một lỗi sao lưu duy nhất có thể dẫn đến mất bản sao lưu duy nhất của bạn. Chọn chiến lược sao lưu Vị trí sao lưu Các bản sao lưu sẽ được lưu vào Bản sao lưu sẽ được lưu vào - Bật sao lưu - Bật sao lưu thủ công + Thực hiện sao lưu + Sao lưu ngay cho tôi Số lượng phiên bản tối đa \u221E @@ -81,7 +81,7 @@ Không giới hạn số bản sao lưu Nhập từ ứng dụng - Nhập token từ một ứng dụng (yêu cầu truy cập root) + Nhập mã từ một ứng dụng (yêu cầu truy cập root) Xuất Xuất kho Nhắc mật khẩu @@ -97,7 +97,7 @@ Chặn chụp ảnh màn hình trong ứng dụng. Nhấn để hiện Mã số được ẩn, nhấn vào thì mới hiện. - Thời gian chờ nhấn + Thời hạn hiển thị mã Tự động khóa Khi %s Tắt @@ -314,11 +314,11 @@ Một số mã QR bị thiếu trong quá trình nhập. Không tìm thấy các mã sau:\n\n%s\n\nBạn có thể tiếp tục nhập bản xuất này nhưng chúng tôi khuyên bạn nên thử lại với tất cả các mã QR để không có nguy cơ mất quyền truy cập vào bất kỳ token nào. • Mã QR %d - Vẫn cứ nhập %d token + Vẫn cứ nhập %d mã Quá trình xuất Google Authenticator thất bại Bản xuất chứa thông tin về một batch không liên quan. Hãy thử nhập 1 batch mỗi lần. - Do đó, không thể nhập token nào + Do đó, không thể nhập mã nào Đang mở khóa kho Đổi tên nhóm Nếu một mục không thuộc bất kỳ nhóm nào, nó sẽ ở trong \"Chưa có nhóm\". @@ -354,13 +354,13 @@ Chú thích Xóa Làm nổi bật token khi nhấn vào - Làm cho các token dễ phân biệt với nhau hơn + Làm cho các mã dễ phân biệt với nhau hơn Thu nhỏ khi sao chép - Thu nhỏ ứng dụng sau khi sao chép một token - Sao chép token vào bộ nhớ tạm + Thu nhỏ ứng dụng sau khi sao chép một mã + Sao chép mã vào bộ nhớ tạm Hành vi tìm kiếm - Đóng băng token khi nhấn vào - Tạm dừng làm mới tự động các token bằng cách nhấn vào chúng. + Đóng băng mã khi nhấn vào + Không tự động hiện mã mới khi đã nhấn vào mã. Nhập mật khẩu để bật bàn phím mã PIN. Lưu ý rằng việc này chỉ được nếu mật khẩu của bạn chỉ chứa các chữ số Lỗi khi bật bàn phím mã PIN Không thể đặt bàn phím mã PIN. Mật khẩu của bạn phải chỉ chứa các chữ số. @@ -378,7 +378,7 @@ Dịch vụ chưa rõ Tên tài khoản không xác định - Aegis không thể nhập %d token. Các token đó sẽ bị bỏ qua. Hãy nhấn \'Chi tiết\' để xem thêm thông tin về các lỗi. + Aegis không thể nhập %d mã. Các mã đó sẽ bị bỏ qua. Nhấn \'Chi tiết\' để xem thêm thông tin về lỗi. Không thể xử lý deep link Không thể đọc và xử lý mã QR từ tập tin: %s. @@ -437,7 +437,7 @@ Không hiện cảnh báo này nữa Cảnh báo này xuất hiện vì gần đây bạn đã xuất một bản sao chưa được mã hóa của kho. Để giữ an toàn mã xác thực của bạn, chúng tôi khuyên bạn nên xóa tập tin này ngay khi bạn không còn cần đến nữa. Đổi camera - Chưa có mã nào. Hãy bắt đầu thêm bằng cách nhấn vào ký hiệu dấu cộng ở góc dưới bên phải + Chưa có mã nào. Thêm mã mới bằng cách nhấn vào dấu cộng ở góc dưới bên phải Chưa có mục nào Chưa có nhãn nào. Hãy thêm các nhãn khi chỉnh sửa một mục Chưa có nhãn nào @@ -455,7 +455,7 @@ Không thể sao chép vào bộ nhớ tạm Đã sao chép vào bộ nhớ tạm Quét mã QR này bằng ứng dụng xác minh mà bạn muốn truyền mục này đến - Quét các mã QR này bằng Aegis hoặc Google Authenticator.\n\nDo hạn chế của ứng dụng Google Authenticator, chỉ token TOTP & HOTP sử dụng SHA1 và tạo mã gồm 6 chữ số dùng được + Quét các mã QR này bằng Aegis hoặc Google Authenticator.\n\nDo hạn chế của ứng dụng Google Authenticator, chỉ mã TOTP & HOTP 6 chữ số sử dụng SHA1 là dùng được Rất yếu Yếu Khá @@ -501,6 +501,7 @@ Cung cấp một bản sao của /data/data/com.azure.authenticator/databases/PhoneFactor, nằm trong thư mục bộ nhớ trong của Microsoft Authenticator. Cung cấp một tập tin văn bản thuần có một URI Google Authenticator trên mỗi dòng. Không hỗ trợ Steam v3.0 trở lên. Cung cấp một bản sao /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json, nằm trong thư mục lưu trữ nội bộ của Steam. + Cung cấp tập tin xuất Stratum có được thông qua Cài đặt -> Sao lưu -> Sao lưu tập tin mã hóa (đề xuất). Cung cấp một tập tin xuất TOTP Authenticator. Cung cấp một tập tin xuất WinAuth. Gán biểu tượng diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 5629658c..01aad813 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -499,6 +499,7 @@ 提供 /data/data/com.azure.authenticator/databases/PhoneFactor 的一个副本,位于 Microsoft Authenticator 的内部存储目录。 提供一个每一行都有一个 Google Authenticator URI 的纯文本文件。 不支持 Steam v3.0 和更新版本。提供 /data/data/com.valvesoftware.android.steam.community/files/Steamguard-*.json的副本, 位于Steam 内部存储目录。 + 提供一个用如下方式获取的 Stratum 导出文件:设置 -> 备份 -> 备份到加密文件(推荐) 提供一个 TOTP 身份验证器导出文件。 提供 WinAuth 导出文件。 分配图标 From 9ab949a59e75079897b80c89cf388b8e4993b5b8 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Sun, 12 Jan 2025 19:01:02 +0100 Subject: [PATCH 21/44] Release v3.3.4 --- app/build.gradle | 4 ++-- app/src/main/assets/changelog.html | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c1edd235..dab8aa72 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,8 +28,8 @@ android { applicationId "${packageName}" minSdkVersion 21 targetSdkVersion 35 - versionCode 76 - versionName "3.3.3" + versionCode 77 + versionName "3.3.4" multiDexEnabled true buildConfigField "String", "GIT_HASH", "\"${getGitHash()}\"" buildConfigField "String", "GIT_BRANCH", "\"${getGitBranch()}\"" diff --git a/app/src/main/assets/changelog.html b/app/src/main/assets/changelog.html index f829c697..eb588572 100644 --- a/app/src/main/assets/changelog.html +++ b/app/src/main/assets/changelog.html @@ -31,6 +31,11 @@
      +

      Version 3.3.4

      +

      Fixes

      +
        +
      • Icons are now resized to 512x512 to reduce the size of the vault file and to reduce the chance of encountering out of memory conditions
      • +

      Version 3.3.3

      Fixes

        From a4812c530d1d3a915a074b8f376143d20188dbfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Wed, 22 Jan 2025 18:33:54 +0100 Subject: [PATCH 22/44] Fix obstructing snackbar padding --- .../aegis/ui/ImportEntriesActivity.java | 36 ++++++++++++++++--- .../res/layout/activity_import_entries.xml | 1 - 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java index 9a5cec40..da04bc3c 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/ImportEntriesActivity.java @@ -52,6 +52,7 @@ import java.util.stream.Collectors; public class ImportEntriesActivity extends AegisActivity { private View _view; private Menu _menu; + private RecyclerView _entriesView; private ImportEntriesAdapter _adapter; private FabScrollHelper _fabScrollHelper; @@ -74,8 +75,8 @@ public class ImportEntriesActivity extends AegisActivity { bar.setDisplayHomeAsUpEnabled(true); _adapter = new ImportEntriesAdapter(); - RecyclerView entriesView = findViewById(R.id.list_entries); - entriesView.addOnScrollListener(new RecyclerView.OnScrollListener() { + _entriesView = findViewById(R.id.list_entries); + _entriesView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); @@ -84,9 +85,9 @@ public class ImportEntriesActivity extends AegisActivity { }); LinearLayoutManager layoutManager = new LinearLayoutManager(this); - entriesView.setLayoutManager(layoutManager); - entriesView.setAdapter(_adapter); - entriesView.setNestedScrollingEnabled(false); + _entriesView.setLayoutManager(layoutManager); + _entriesView.setAdapter(_adapter); + _entriesView.setNestedScrollingEnabled(false); FloatingActionButton fab = findViewById(R.id.fab); fab.setOnClickListener(v -> { @@ -358,6 +359,31 @@ public class ImportEntriesActivity extends AegisActivity { _adapter.setCheckboxStates(duplicateEntries, false); Snackbar snackbar = Snackbar.make(_view, getResources().getQuantityString(R.plurals.import_duplicate_toast, duplicateEntries.size(), duplicateEntries.size()), Snackbar.LENGTH_INDEFINITE); + snackbar.addCallback(new Snackbar.Callback() { + @Override + public void onShown(Snackbar sb) { + int snackbarHeight = sb.getView().getHeight(); + + _entriesView.setPadding( + _entriesView.getPaddingLeft(), + _entriesView.getPaddingTop(), + _entriesView.getPaddingRight(), + _entriesView.getPaddingBottom() + snackbarHeight * 2 + ); + } + + @Override + public void onDismissed(Snackbar sb, int event) { + int snackbarHeight = sb.getView().getHeight(); + + _entriesView.setPadding( + _entriesView.getPaddingLeft(), + _entriesView.getPaddingTop(), + _entriesView.getPaddingRight(), + _entriesView.getPaddingBottom() - snackbarHeight * 2 + ); + } + }); snackbar.setAction(R.string.undo, new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/app/src/main/res/layout/activity_import_entries.xml b/app/src/main/res/layout/activity_import_entries.xml index da32516c..deba9ac1 100644 --- a/app/src/main/res/layout/activity_import_entries.xml +++ b/app/src/main/res/layout/activity_import_entries.xml @@ -23,7 +23,6 @@ android:id="@+id/list_entries" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingBottom="60dp" android:clipToPadding="false" android:scrollbars="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> From 3d50ab1b653e57f5478810ac3a9097e8b9809b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Wed, 22 Jan 2025 22:06:57 +0100 Subject: [PATCH 23/44] Improve color contrast on hidden codes --- .../java/com/beemdevelopment/aegis/ui/views/EntryHolder.java | 5 ++++- app/src/main/res/values/attrs.xml | 1 + app/src/main/res/values/themes.xml | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryHolder.java b/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryHolder.java index ba86e9cd..cca83dfd 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryHolder.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryHolder.java @@ -369,9 +369,11 @@ public class EntryHolder extends RecyclerView.ViewHolder { public void hideCode() { String code = getOtp(); String hiddenText = code.replaceAll("\\S", Character.toString(HIDDEN_CHAR)); + stopExpirationAnimation(); + updateTextViewWithDots(_profileCode, hiddenText, code); updateTextViewWithDots(_nextProfileCode, hiddenText, code); - stopExpirationAnimation(); + _hidden = true; } @@ -384,6 +386,7 @@ public class EntryHolder extends RecyclerView.ViewHolder { float dotsWidth = paint.measureText(hiddenCode); float scaleFactor = codeWidth / dotsWidth; scaleFactor = (float)(Math.round(scaleFactor * 10.0) / 10.0); + textView.setTextColor(MaterialColors.getColor(textView, R.attr.colorCodeHidden)); // If scale is higher or equal to 0.8, do nothing and proceed with the normal text rendering if (scaleFactor >= 0.8) { diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 0c24c596..8baea4f4 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -8,6 +8,7 @@ + diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 7ae582e9..d135ec24 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -62,6 +62,7 @@ @color/aegis_theme_light_success @color/aegis_theme_light_onSurfaceDim ?attr/colorPrimary + ?attr/colorOutlineVariant ?attr/colorSurfaceVariant ?attr/colorOnSurfaceVariant @@ -132,6 +133,7 @@ @color/aegis_theme_dark_success @color/aegis_theme_dark_onSurfaceDim ?attr/colorPrimary + ?attr/colorOutlineVariant ?attr/colorSurfaceVariant ?attr/colorOnSurfaceVariant @@ -159,6 +161,7 @@ #000000 #000000 @android:color/white + #2F2F2F @android:color/white @@ -179,6 +182,7 @@ #000000 #000000 @android:color/white + #2F2F2F @android:color/white From e8d712ec7189282dbd5aaeaacf0b506ef1cd9636 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Fri, 24 Jan 2025 14:34:41 +0100 Subject: [PATCH 24/44] Flush temporary export file before starting ExportTask The previous logic was not an issue because FileOutputStream is unbuffered, but still, this is more correct. --- .../preferences/ImportExportPreferencesFragment.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/ImportExportPreferencesFragment.java b/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/ImportExportPreferencesFragment.java index f544bf6f..b995b235 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/ImportExportPreferencesFragment.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/ImportExportPreferencesFragment.java @@ -518,11 +518,10 @@ public class ImportExportPreferencesFragment extends PreferencesFragment { file = File.createTempFile(VaultRepository.FILENAME_PREFIX_EXPORT + "-", ".json", getExportCacheDir()); outStream = new FileOutputStream(file); cb.exportVault(outStream); - - new ExportTask(requireContext(), new ExportResultListener()).execute(getLifecycle(), new ExportTask.Params(file, uri)); } catch (VaultRepositoryException | IOException e) { e.printStackTrace(); Dialogs.showErrorDialog(requireContext(), R.string.exporting_vault_error, e); + return; } finally { try { if (outStream != null) { @@ -532,6 +531,8 @@ public class ImportExportPreferencesFragment extends PreferencesFragment { e.printStackTrace(); } } + + new ExportTask(requireContext(), new ExportResultListener()).execute(getLifecycle(), new ExportTask.Params(file, uri)); }, _exportFilter); _exportFilter = null; } From 78ee38ba7d60794944f7ee463c468e22dbbd7fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Sun, 1 Dec 2024 23:08:05 +0100 Subject: [PATCH 25/44] Add ability to multiselect groups --- .../beemdevelopment/aegis/Preferences.java | 4 ++++ .../aegis/ui/MainActivity.java | 23 ++++++++----------- app/src/main/res/layout/activity_main.xml | 3 +-- app/src/main/res/values/strings.xml | 2 ++ app/src/main/res/xml/preferences_behavior.xml | 7 ++++++ 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/beemdevelopment/aegis/Preferences.java b/app/src/main/java/com/beemdevelopment/aegis/Preferences.java index 95f3ed4c..6e86f4f7 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/Preferences.java +++ b/app/src/main/java/com/beemdevelopment/aegis/Preferences.java @@ -86,6 +86,10 @@ public class Preferences { return _prefs.getBoolean("pref_tap_to_reveal", false); } + public boolean isGroupMultiselectEnabled() { + return _prefs.getBoolean("pref_groups_multiselect", false); + } + public boolean isEntryHighlightEnabled() { return _prefs.getBoolean("pref_highlight_entry", false); } diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java index 1dc5cbd5..29ac2c69 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java @@ -274,6 +274,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene private void initializeGroups() { _groupChip.removeAllViews(); + _groupChip.setSingleSelection(!_prefs.isGroupMultiselectEnabled()); for (VaultGroup group : _groups) { addChipTo(_groupChip, new VaultGroupModel(group)); @@ -313,29 +314,24 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene } chip.setOnCheckedChangeListener((group1, isChecked) -> { - Set groupFilter = new HashSet<>(); if (_actionMode != null) { _actionMode.finish(); } setSaveChipVisibility(true); - if (!isChecked) { - group1.setChecked(false); + // Reset group filter if last checked group gets unchecked + if (!isChecked && _groupFilter.size() == 1) { + Set groupFilter = new HashSet<>(); + + chipGroup.clearCheck(); _groupFilter = groupFilter; _entryListView.setGroupFilter(groupFilter); return; } - Object chipTag = group1.getTag(); - if (chipTag == GroupPlaceholderType.NO_GROUP) { - groupFilter.add(null); - } else { - groupFilter = getGroupFilter(chipGroup); - } - - _groupFilter = groupFilter; - _entryListView.setGroupFilter(groupFilter); + _groupFilter = getGroupFilter(chipGroup); + _entryListView.setGroupFilter(_groupFilter); }); chipGroup.addView(chip); @@ -368,8 +364,10 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene private static Set getGroupFilter(ChipGroup chipGroup) { return chipGroup.getCheckedChipIds().stream() + .filter(Objects::nonNull) .map(i -> { Chip chip = chipGroup.findViewById(i); + if (chip.getTag() instanceof VaultGroupModel) { VaultGroupModel group = (VaultGroupModel) chip.getTag(); return group.getUUID(); @@ -377,7 +375,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene return null; }) - .filter(Objects::nonNull) .collect(Collectors.toSet()); } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 7a288e1e..b2ca2d00 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -39,8 +39,7 @@ android:id="@+id/groupChipGroup" android:layout_width="match_parent" android:layout_height="wrap_content" - app:selectionRequired="true" - app:singleSelection="true"/> + app:selectionRequired="true"/> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2725c77f..b2ec52ff 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -373,6 +373,8 @@ Highlight tokens when tapped Make tokens easier to distinguish from each other by temporarily highlighting them when tapped + Multiselect groups + Allow the selection of multiple groups at the same time Minimize on copy Minimize the app after copying a token Copy tokens to the clipboard diff --git a/app/src/main/res/xml/preferences_behavior.xml b/app/src/main/res/xml/preferences_behavior.xml index ac2fa0d2..46f636f4 100644 --- a/app/src/main/res/xml/preferences_behavior.xml +++ b/app/src/main/res/xml/preferences_behavior.xml @@ -26,6 +26,13 @@ android:title="@string/pref_copy_behavior_title" app:iconSpaceReserved="false"/> + + Date: Mon, 24 Feb 2025 13:41:42 +0100 Subject: [PATCH 26/44] Update divider decoration when filter/sort changes This fixes an issue where the item decoration may be wrong in some cases. For example, adding a new entry to the bottom of the list may not update the decoration of the item that was previously the last one in the list. To reproduce, use this vault: https://alexbakker.me/u/mov4455gp5.json. Start without a group filter, apply sorting based on Issuer (A to Z) and enable group multiselect. Then: - Tap the "Test" chip - Tap the "Test2" chip - Tap the "No group" chip - Notice that the offset between the last 2 entries looks wrong: https://alexbakker.me/u/nedcyiro2q.png Probably introduced in 9131cae944f354c95873aa1c257e87b0c9b1f210. --- .../main/java/com/beemdevelopment/aegis/ui/MainActivity.java | 2 +- .../com/beemdevelopment/aegis/ui/views/EntryListView.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java index 0a06c0e8..f1b27f21 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java @@ -220,8 +220,8 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene _entryListView.setPauseFocused(_prefs.isPauseFocusedEnabled()); _entryListView.setTapToReveal(_prefs.isTapToRevealEnabled()); _entryListView.setTapToRevealTime(_prefs.getTapToRevealTime()); - _entryListView.setSortCategory(_prefs.getCurrentSortCategory(), false); _entryListView.setViewMode(_prefs.getCurrentViewMode()); + _entryListView.setSortCategory(_prefs.getCurrentSortCategory(), false); _entryListView.setCopyBehavior(_prefs.getCopyBehavior()); _entryListView.setSearchBehaviorMask(_prefs.getSearchBehaviorMask()); _prefGroupFilter = _prefs.getGroupFilter(); diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryListView.java b/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryListView.java index 3d359290..ff6ff97a 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryListView.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/views/EntryListView.java @@ -200,6 +200,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { _adapter.setGroupFilter(groups); _touchCallback.setIsLongPressDragEnabled(_adapter.isDragAndDropAllowed()); updateEmptyState(); + updateDividerDecoration(); } public void setIsLongPressDragEnabled(boolean enabled) { @@ -232,6 +233,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { public void setSortCategory(SortCategory sortCategory, boolean apply) { _adapter.setSortCategory(sortCategory, apply); _touchCallback.setIsLongPressDragEnabled(_adapter.isDragAndDropAllowed()); + updateDividerDecoration(); } public void setUsageCounts(Map usageCounts) { @@ -253,8 +255,8 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { public void setSearchFilter(String search) { _adapter.setSearchFilter(search); _touchCallback.setIsLongPressDragEnabled(_adapter.isDragAndDropAllowed()); - updateEmptyState(); + updateDividerDecoration(); } public void setSelectedEntry(VaultEntry entry) { From fbfdd50069db6ec720b3a3d20bb1eced9dd3b6dd Mon Sep 17 00:00:00 2001 From: jahway603 Date: Tue, 15 Apr 2025 18:54:46 -0400 Subject: [PATCH 27/44] [FAQ] clarified about which password to use when importing your vault to resolve Issue #1636 --- FAQ.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/FAQ.md b/FAQ.md index 815490aa..6d514574 100644 --- a/FAQ.md +++ b/FAQ.md @@ -86,6 +86,14 @@ Another common setup is to configure Aegis to back up to a folder on local storage of your device and then have a separate app (like [Syncthing](https://syncthing.net/)) sync that folder anywhere you want. +## Encrypted Backups + +### Why do I not get prompted to enter an encryption password when exporting? + +Aegis uses the same password you have configured to encrypt your vault as the +password which is used when exporting and importing your vault; so when prompted, +you will enter that when importing your vault. + ## Importing ### When importing from Authenticator Plus, an error is shown claiming that Accounts.txt is missing From c81e08bf1feb72e48f105abdca56c9f24ae5caa4 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Wed, 23 Apr 2025 15:51:49 +0200 Subject: [PATCH 28/44] Fall back to default values in the FreeOTP importer --- .../aegis/importers/FreeOtpImporter.java | 6 +++--- .../aegis/importers/DatabaseImporterTest.java | 9 +++++++++ .../aegis/importers/freeotp_v2_null_algo.xml | Bin 0 -> 1066 bytes 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 app/src/test/resources/com/beemdevelopment/aegis/importers/freeotp_v2_null_algo.xml diff --git a/app/src/main/java/com/beemdevelopment/aegis/importers/FreeOtpImporter.java b/app/src/main/java/com/beemdevelopment/aegis/importers/FreeOtpImporter.java index 8b96299b..0266ca95 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/importers/FreeOtpImporter.java +++ b/app/src/main/java/com/beemdevelopment/aegis/importers/FreeOtpImporter.java @@ -298,8 +298,8 @@ public class FreeOtpImporter extends DatabaseImporter { private static VaultEntry convertEntry(JSONObject obj) throws DatabaseImporterEntryException { try { String type = obj.getString("type").toLowerCase(Locale.ROOT); - String algo = obj.getString("algo"); - int digits = obj.getInt("digits"); + String algo = obj.optString("algo", OtpInfo.DEFAULT_ALGORITHM); + int digits = obj.optInt("digits", OtpInfo.DEFAULT_DIGITS); byte[] secret = toBytes(obj.getJSONArray("secret")); String issuer = obj.getString("issuerExt"); @@ -308,7 +308,7 @@ public class FreeOtpImporter extends DatabaseImporter { OtpInfo info; switch (type) { case "totp": - int period = obj.getInt("period"); + int period = obj.optInt("period", TotpInfo.DEFAULT_PERIOD); if (issuer.equals("Steam")) { info = new SteamInfo(secret, algo, digits, period); } else { diff --git a/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java b/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java index 4742eabd..1457d118 100644 --- a/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java +++ b/app/src/test/java/com/beemdevelopment/aegis/importers/DatabaseImporterTest.java @@ -257,6 +257,15 @@ public class DatabaseImporterTest { checkImportedEntries(entries); } + @Test + public void testImportFreeOtpV2NullAlgo() throws IOException, DatabaseImporterException, OtpInfoException { + List entries = importEncrypted(FreeOtpImporter.class, "freeotp_v2_null_algo.xml", encryptedState -> { + final char[] password = "test".toCharArray(); + return ((FreeOtpImporter.EncryptedState) encryptedState).decrypt(password); + }); + checkImportedEntries(entries); + } + @Test public void testImportFreeOtpPlus() throws IOException, DatabaseImporterException, OtpInfoException { List entries = importPlain(FreeOtpPlusImporter.class, "freeotp_plus.json"); diff --git a/app/src/test/resources/com/beemdevelopment/aegis/importers/freeotp_v2_null_algo.xml b/app/src/test/resources/com/beemdevelopment/aegis/importers/freeotp_v2_null_algo.xml new file mode 100644 index 0000000000000000000000000000000000000000..dc890c5c66d0c0ba93b80a9e815c512863d94c7c GIT binary patch literal 1066 zcma)*O>Wab7=}%&Qp%1E2N+nPnbu>EJ$5#wv?;BsLZoJgD=~?kCe%NXJ*A1F+=xpc zPQaEsa0lMc4ivE>QsVLVKi~7_%TH&gshww^%xANIXJ`5TnQ5k%X1=rglAJzo&j^%W=ad>gFG7OLg@+`H zi}Ca$O7eLKdyF83cVF|6`|dRjGBC9%GMm*64FWGJQCYM_M(88DZ5wi>VQ$YH<4Wmr z^yn;}&tc&*Y)cNS+pKJ_e^!|B)!C6u*qW`a^Xh+=DJ-R1r@vyern$@N{=#ChCs|oB zzA>Gbf0=SK%5p?pnx-ldVwdv_ufzAl0X5w#OoQuPWJ|lXyJE#repA&mJ1r11cyn=b z>fPgQGie|_R4Dr8xL(d}mLiMwkklbX27nUJ2b>h%c?l-51R9Mc2O*CL8nM8tuzH}< zn_c>_Mnnsg@QlbzXNA23eS4Ok=A;Qi4`LFE09X(K%E;q@E3x;OvIsu12s7vb1$+90ZI iq*GjpMuIj28V}b~vfG>+bM3Y?utYe(L`Z$TUi<>?SPG*6 literal 0 HcmV?d00001 From afa1fbd3ae8ef36b266a4032be1c75abac0ffcb8 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Wed, 23 Apr 2025 16:20:34 +0200 Subject: [PATCH 29/44] Specify country code for the Portuguese translation --- app/src/main/res/values/arrays.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 17ac962e..bf4c1c64 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -100,7 +100,7 @@ lt fa pl - pt + pt_PT pt_BR ro ru From 03c00d51ba1f7f4dbea151bda33c96253489ccfd Mon Sep 17 00:00:00 2001 From: mimi89999 Date: Wed, 19 Mar 2025 09:43:56 +0100 Subject: [PATCH 30/44] Add Crowdin config file and update crowdin-cli Co-authored-by: Alexander Bakker --- .crowdin/config.example.yml | 10 ---------- .github/workflows/crowdin.yml | 14 ++++---------- crowdin.yml | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 20 deletions(-) delete mode 100644 .crowdin/config.example.yml create mode 100644 crowdin.yml diff --git a/.crowdin/config.example.yml b/.crowdin/config.example.yml deleted file mode 100644 index 4ef788a3..00000000 --- a/.crowdin/config.example.yml +++ /dev/null @@ -1,10 +0,0 @@ -project_id: "372633" -api_token: "" -base_path: "../app/src/main" -base_url: "https://api.crowdin.com" -preserve_hierarchy: true - -files: -- source: "res/values/strings.xml" - dest: "strings.xml" - translation: "res/values-%android_code%/%original_file_name%" diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index e0fd559c..e7898362 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -13,19 +13,13 @@ jobs: - uses: actions/checkout@v4 - name: Install crowdin-cli run: | - wget https://github.com/crowdin/crowdin-cli/releases/download/3.7.2/crowdin-cli.zip - echo "ee9f838b819ccedc33c9b2537055e5ba7d7934561b24df1e1a6274cbd6e27f2d crowdin-cli.zip" | sha256sum -c + wget https://github.com/crowdin/crowdin-cli/releases/download/4.6.1/crowdin-cli.zip + echo "7afd70de3a747ac631a5bad7866008163ae1d50c4606b5773f0b90a5481ffde2 crowdin-cli.zip" | sha256sum -c unzip crowdin-cli.zip -d crowdin-cli - name: Upload to Crowdin env: - CROWDIN_TOKEN: "${{ secrets.CROWDIN_TOKEN }}" + CROWDIN_PERSONAL_TOKEN: "${{ secrets.CROWDIN_TOKEN }}" run: | - java -jar ./crowdin-cli/3.7.2/crowdin-cli.jar upload sources \ + java -jar ./crowdin-cli/4.6.1/crowdin-cli.jar upload sources \ --no-progress \ - --token "$CROWDIN_TOKEN" \ - --project-id 372633 \ - --base-path app/src/main \ - --source res/values/strings.xml \ - --translation "res/values-%android_code%/%original_file_name%" \ - --dest strings.xml \ --branch master diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 00000000..59912b50 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,14 @@ +project_id: "372633" +preserve_hierarchy: true +base_path: "app/src/main" +base_url: "https://api.crowdin.com" +api_token_env: "CROWDIN_PERSONAL_TOKEN" +files: + - type: "android" + source: "res/values/strings.xml" + dest: "strings.xml" + translation: "res/values-%android_code%/%original_file_name%" + - type: "android" + source: "res/values-v29/strings.xml" + dest: "strings-v29.xml" + translation: "res/values-%android_code%-v29/%original_file_name%" From 3818f9408d8ae1831cfee1a8bdd53c1572f1321a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Sch=C3=A4ttgen?= Date: Mon, 24 Feb 2025 19:39:41 +0100 Subject: [PATCH 31/44] Add brightness slider for transfer activity --- .../aegis/ui/TransferEntriesActivity.java | 31 ++++++++++++-- .../main/res/layout/activity_share_entry.xml | 42 ++++++++++++------- app/src/main/res/values/strings.xml | 1 + 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/beemdevelopment/aegis/ui/TransferEntriesActivity.java b/app/src/main/java/com/beemdevelopment/aegis/ui/TransferEntriesActivity.java index a4deae57..a0559d7a 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/TransferEntriesActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/TransferEntriesActivity.java @@ -10,6 +10,7 @@ import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.os.PersistableBundle; +import android.provider.Settings; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -47,6 +48,8 @@ public class TransferEntriesActivity extends AegisActivity { private Button _previousButton; private Button _copyButton; private int _currentEntryCount = 1; + private float _deviceBrightness; + private boolean _isMaxBrightnessSet = false; @Override protected void onCreate(Bundle savedInstanceState) { @@ -146,13 +149,33 @@ public class TransferEntriesActivity extends AegisActivity { _qrImage.getViewTreeObserver().removeOnGlobalLayoutListener(this); } }); + + _deviceBrightness = getSystemBrightness(); + _qrImage.setOnClickListener(v -> { + if (!_isMaxBrightnessSet) { + setBrightness(1f); + _isMaxBrightnessSet = true; + } else { + setBrightness(_deviceBrightness); + _isMaxBrightnessSet = false; + } + }); } - @Override - public void onAttachedToWindow() { - // Max brightness to make the QR codes easier to scan + private float getSystemBrightness() { + int brightness = 0; + try { + brightness = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS); + } catch (Settings.SettingNotFoundException e) { + e.printStackTrace(); + } + + return brightness / 255f; + } + + private void setBrightness(float brightnessAmount) { WindowManager.LayoutParams attrs = getWindow().getAttributes(); - attrs.screenBrightness = 1.0f; + attrs.screenBrightness = brightnessAmount; getWindow().setAttributes(attrs); } diff --git a/app/src/main/res/layout/activity_share_entry.xml b/app/src/main/res/layout/activity_share_entry.xml index 3050c056..455f3356 100644 --- a/app/src/main/res/layout/activity_share_entry.xml +++ b/app/src/main/res/layout/activity_share_entry.xml @@ -25,8 +25,8 @@ android:id="@+id/layoutShareEntry" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingHorizontal="30dp" - android:layout_marginTop="?attr/actionBarSize"> + android:layout_marginTop="?attr/actionBarSize" + android:paddingHorizontal="30dp"> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.3" + app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Aegis.ImageView.Rounded" /> + app:layout_constraintTop_toBottomOf="@+id/ivQrCode" + tools:text="Issuer" /> + app:layout_constraintTop_toBottomOf="@+id/tvIssuer" + tools:text="Accountname" />