Skip to content

Commit

Permalink
Add ability to multiselect groups
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelschattgen committed Dec 22, 2024
1 parent 337cb74 commit 6df4336
Show file tree
Hide file tree
Showing 31 changed files with 217 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-app-workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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()}\""
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/assets/changelog.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@
</head>
<body>
<div></div>
<h3>Version 3.3.2</h3>
<h4>New</h4>
<ul>
<li>Find entries by searching in multiple fields simultaneously</li>
</ul>
<h4>Fixes</h4>
<ul>
<li>Entries would not actually be added to the Aegis vault in some cases when importing from Google Authenticator export QR codes</li>
<li>The lock button was sometimes shown for unencrypted vaults</li>
<li>The sort category menu item did not always reflect the current sorting</li>
<li>The next code was not always easy to read because its color had low contrast with the background</li>
<li>Entry selection was not cancelled when changing the group filter</li>
</ul>
<h3>Version 3.3.1</h3>
<h4>Fixes</h4>
<ul>
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/beemdevelopment/aegis/Preferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ public boolean isTapToRevealEnabled() {
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);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

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;
Expand All @@ -16,6 +16,7 @@
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;
Expand Down Expand Up @@ -173,9 +174,12 @@ public Result convert() {

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);
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/java/com/beemdevelopment/aegis/ui/AboutActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@

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 {
Expand All @@ -39,6 +43,7 @@ protected void onCreate(Bundle savedInstanceState) {

setContentView(R.layout.activity_about);
setSupportActionBar(findViewById(R.id.toolbar));
ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout));

if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Expand Down Expand Up @@ -90,6 +95,17 @@ protected void onCreate(Bundle savedInstanceState) {
.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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
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;
Expand Down Expand Up @@ -61,6 +62,7 @@ protected void onCreate(Bundle savedInstanceState) {

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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
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;
Expand Down Expand Up @@ -164,6 +165,7 @@ protected void onCreate(Bundle savedInstanceState) {
}
setContentView(R.layout.activity_edit_entry);
setSupportActionBar(findViewById(R.id.toolbar));
ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout));

_groups = _vaultManager.getVault().getGroups();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
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;

Expand All @@ -39,6 +40,7 @@ protected void onCreate(Bundle savedInstanceState) {
}
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
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;
Expand Down Expand Up @@ -58,6 +59,7 @@ protected void onCreate(Bundle savedInstanceState) {
}
setContentView(R.layout.activity_import_entries);
setSupportActionBar(findViewById(R.id.toolbar));
ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout));

_view = findViewById(R.id.importEntriesRootView);

Expand Down
37 changes: 25 additions & 12 deletions app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
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;
Expand Down Expand Up @@ -183,6 +184,7 @@ protected void onCreate(Bundle savedInstanceState) {
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;
Expand Down Expand Up @@ -280,6 +282,8 @@ private void initializeGroups() {
GroupPlaceholderType placeholderType = GroupPlaceholderType.NO_GROUP;
addChipTo(_groupChip, new VaultGroupModel(this, placeholderType));
addSaveChip(_groupChip);

_groupChip.setSingleSelection(!_prefs.isGroupMultiselectEnabled());
}

private Set<UUID> cleanGroupFilter(Set<UUID> groupFilter) {
Expand Down Expand Up @@ -311,25 +315,24 @@ private void addChipTo(ChipGroup chipGroup, VaultGroupModel group) {
}

chip.setOnCheckedChangeListener((group1, isChecked) -> {
Set<UUID> groupFilter = new HashSet<>();
if (_actionMode != null) {
_actionMode.finish();
}

setSaveChipVisibility(true);

if (!isChecked) {
// Reset group filter if last checked group gets unchecked
if (!isChecked && _groupFilter.size() == 1) {
Set<UUID> groupFilter = new HashSet<>();

group1.setChecked(false);
_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);
Expand Down Expand Up @@ -362,6 +365,7 @@ private void setSaveChipVisibility(boolean visible) {

private static Set<UUID> getGroupFilter(ChipGroup chipGroup) {
return chipGroup.getCheckedChipIds().stream()
.filter(Objects::nonNull)
.map(i -> {
Chip chip = chipGroup.findViewById(i);
if (chip.getTag() instanceof VaultGroupModel) {
Expand All @@ -371,7 +375,6 @@ private static Set<UUID> getGroupFilter(ChipGroup chipGroup) {

return null;
})
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}

Expand Down Expand Up @@ -685,6 +688,10 @@ private void importScannedEntries(List<VaultEntry> entries) {
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();
}
Expand Down Expand Up @@ -920,6 +927,9 @@ public boolean onCreateOptionsMenu(Menu menu) {
_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);
Expand All @@ -930,6 +940,7 @@ public boolean onCreateOptionsMenu(Menu menu) {
_searchView.setOnCloseListener(() -> {
boolean enabled = _submittedSearchQuery != null;
_searchViewBackPressHandler.setEnabled(enabled);
_groupChip.setVisibility(_groups.isEmpty() ? View.GONE : View.VISIBLE);
return false;
});

Expand Down Expand Up @@ -963,6 +974,7 @@ public boolean onQueryTextChange(String s) {
});
_searchView.setOnSearchClickListener(v -> {
String query = _submittedSearchQuery != null ? _submittedSearchQuery : _pendingSearchQuery;
_groupChip.setVisibility(View.GONE);
_searchView.setQuery(query, false);
});

Expand Down Expand Up @@ -1028,6 +1040,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
}

private void collapseSearchView() {
_groupChip.setVisibility(_groups.isEmpty() ? View.GONE : View.VISIBLE);
_searchView.setQuery(null, false);
_searchView.setIconified(true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
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 {
Expand All @@ -27,6 +28,7 @@ protected void onCreate(Bundle savedInstanceState) {
}
setContentView(R.layout.activity_preferences);
setSupportActionBar(findViewById(R.id.toolbar));
ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout));
getSupportFragmentManager()
.registerFragmentLifecycleCallbacks(new FragmentResumeListener(), true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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;
Expand Down Expand Up @@ -56,6 +57,7 @@ public void onCreate(Bundle savedInstanceState) {
}
setContentView(R.layout.activity_scanner);
setSupportActionBar(findViewById(R.id.toolbar));
ViewHelper.setupAppBarInsets(findViewById(R.id.app_bar_layout));

_entries = new ArrayList<>();
_lenses = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
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;
Expand Down Expand Up @@ -55,6 +56,7 @@ protected void onCreate(Bundle savedInstanceState) {
}
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);
Expand Down
Loading

0 comments on commit 6df4336

Please sign in to comment.