Skip to content

Commit

Permalink
Merge pull request #1468 from michaelschattgen/feature/add-search-beh…
Browse files Browse the repository at this point in the history
…avior

Add preference to change search behavior
  • Loading branch information
alexbakker committed Sep 6, 2024
2 parents 7472e32 + 3425256 commit 3bc3448
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 1 deletion.
27 changes: 27 additions & 0 deletions app/src/main/java/com/beemdevelopment/aegis/Preferences.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ public class Preferences {
public static final int AUTO_LOCK_ON_BACK_BUTTON = 1 << 1;
public static final int AUTO_LOCK_ON_MINIMIZE = 1 << 2;
public static final int AUTO_LOCK_ON_DEVICE_LOCK = 1 << 3;

public static final int SEARCH_IN_ISSUER = 1 << 0;
public static final int SEARCH_IN_NAME = 1 << 1;
public static final int SEARCH_IN_NOTE = 1 << 2;
public static final int SEARCH_IN_GROUPS = 1 << 3;

public static final int BACKUPS_VERSIONS_INFINITE = -1;

public static final int[] AUTO_LOCK_SETTINGS = {
Expand All @@ -41,6 +47,13 @@ public class Preferences {
AUTO_LOCK_ON_DEVICE_LOCK
};

public static final int[] SEARCH_BEHAVIOR_SETTINGS = {
SEARCH_IN_ISSUER,
SEARCH_IN_NAME,
SEARCH_IN_NOTE,
SEARCH_IN_GROUPS
};

private SharedPreferences _prefs;

public Preferences(Context context) {
Expand Down Expand Up @@ -163,6 +176,20 @@ private int getAutoLockMask() {
return _prefs.getInt("pref_auto_lock_mask", def);
}

public int getSearchBehaviorMask() {
final int def = SEARCH_IN_ISSUER | SEARCH_IN_NAME;

return _prefs.getInt("pref_search_behavior_mask", def);
}

public boolean isSearchBehaviorTypeEnabled(int searchBehaviorType) {
return (getSearchBehaviorMask() & searchBehaviorType) == searchBehaviorType;
}

public void setSearchBehaviorMask(int searchBehavior) {
_prefs.edit().putInt("pref_search_behavior_mask", searchBehavior).apply();
}

public boolean isAutoLockEnabled() {
return getAutoLockMask() != AUTO_LOCK_OFF;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ protected void onCreate(Bundle savedInstanceState) {
_entryListView.setSortCategory(_prefs.getCurrentSortCategory(), false);
_entryListView.setViewMode(_prefs.getCurrentViewMode());
_entryListView.setCopyBehavior(_prefs.getCopyBehavior());
_entryListView.setSearchBehaviorMask(_prefs.getSearchBehaviorMask());
_entryListView.setPrefGroupFilter(_prefs.getGroupFilter());

FloatingActionButton fab = findViewById(R.id.fab);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.beemdevelopment.aegis.ui.fragments.preferences;

import android.os.Bundle;
import android.widget.Button;

import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;

import com.beemdevelopment.aegis.CopyBehavior;
import com.beemdevelopment.aegis.Preferences;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.ui.dialogs.Dialogs;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
Expand All @@ -16,6 +18,51 @@ public class BehaviorPreferencesFragment extends PreferencesFragment {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences_behavior);

Preference currentSearchBehaviorPreference = requirePreference("pref_search_behavior");
currentSearchBehaviorPreference.setSummary(getSearchBehaviorSummary());
currentSearchBehaviorPreference.setOnPreferenceClickListener((preference) -> {
final int[] items = Preferences.SEARCH_BEHAVIOR_SETTINGS;
final String[] textItems = getResources().getStringArray(R.array.pref_search_behavior_types);
final boolean[] checkedItems = new boolean[items.length];
for (int i = 0; i < items.length; i++) {
checkedItems[i] = _prefs.isSearchBehaviorTypeEnabled(items[i]);
}

MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.pref_search_behavior_prompt)
.setMultiChoiceItems(textItems, checkedItems, (dialog, index, isChecked) -> {
checkedItems[index] = isChecked;

boolean containsAtLeastOneCheckedItem = false;
for(boolean b: checkedItems) {
if (b) {
containsAtLeastOneCheckedItem = true;
break;
}
}

AlertDialog alertDialog = (AlertDialog) dialog;
Button positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);

positiveButton.setEnabled(containsAtLeastOneCheckedItem);
})
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
int searchBehavior = 0;
for (int i = 0; i < checkedItems.length; i++) {
if (checkedItems[i]) {
searchBehavior |= items[i];
}
}

_prefs.setSearchBehaviorMask(searchBehavior);
currentSearchBehaviorPreference.setSummary(getSearchBehaviorSummary());
})
.setNegativeButton(android.R.string.cancel, null);

Dialogs.showSecureDialog(builder.create());
return true;
});

int currentCopyBehavior = _prefs.getCopyBehavior().ordinal();
Preference copyBehaviorPreference = requirePreference("pref_copy_behavior");
copyBehaviorPreference.setSummary(String.format("%s: %s", getString(R.string.selected), getResources().getStringArray(R.array.copy_behavior_titles)[currentCopyBehavior]));
Expand Down Expand Up @@ -45,4 +92,22 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
return true;
});
}

private String getSearchBehaviorSummary() {
final int[] settings = Preferences.SEARCH_BEHAVIOR_SETTINGS;
final String[] descriptions = getResources().getStringArray(R.array.pref_search_behavior_types);

StringBuilder builder = new StringBuilder();
for (int i = 0; i < settings.length; i++) {
if (_prefs.isSearchBehaviorTypeEnabled(settings[i])) {
if (builder.length() != 0) {
builder.append(", ");
}

builder.append(descriptions[i].toLowerCase());
}
}

return getString(R.string.pref_search_behavior_summary, builder.toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.beemdevelopment.aegis.ui.models.ErrorCardInfo;
import com.beemdevelopment.aegis.util.CollectionUtils;
import com.beemdevelopment.aegis.vault.VaultEntry;
import com.beemdevelopment.aegis.vault.VaultGroup;

import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -51,6 +52,7 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
private List<VaultEntry> _entries;
private List<VaultEntry> _shownEntries;
private List<VaultEntry> _selectedEntries;
private Collection<VaultGroup> _groups;
private Map<UUID, Integer> _usageCounts;
private Map<UUID, Long> _lastUsedTimestamps;
private VaultEntry _focusedEntry;
Expand All @@ -64,6 +66,7 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
private boolean _tapToReveal;
private int _tapToRevealTime;
private CopyBehavior _copyBehavior;
private int _searchBehaviorMask;
private Set<UUID> _groupFilter;
private SortCategory _sortCategory;
private ViewMode _viewMode;
Expand Down Expand Up @@ -130,6 +133,8 @@ public void setTempHighlightEntry(boolean highlightEntry) {

public void setCopyBehavior(CopyBehavior copyBehavior) { _copyBehavior = copyBehavior; }

public void setSearchBehaviorMask(int searchBehaviorMask) { _searchBehaviorMask = searchBehaviorMask; }

public void setPauseFocused(boolean pauseFocused) {
_pauseFocused = pauseFocused;
}
Expand Down Expand Up @@ -308,6 +313,7 @@ private boolean isEntryFiltered(VaultEntry entry) {
Set<UUID> groups = entry.getGroups();
String issuer = entry.getIssuer().toLowerCase();
String name = entry.getName().toLowerCase();
String note = entry.getNote().toLowerCase();

if (!_groupFilter.isEmpty()) {
if (groups.isEmpty() && !_groupFilter.contains(null)) {
Expand All @@ -322,7 +328,17 @@ private boolean isEntryFiltered(VaultEntry entry) {
return false;
}

return !issuer.contains(_searchFilter) && !name.contains(_searchFilter);
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));
}

private boolean doesAnyGroupMatchSearchFilter(Set<UUID> entryGroupUUIDs, String searchFilter) {
return _groups.stream()
.filter(group -> entryGroupUUIDs.contains(group.getUUID()))
.map(VaultGroup::getName)
.anyMatch(groupName -> groupName.toLowerCase().contains(searchFilter.toLowerCase()));
}

public void refresh(boolean hard) {
Expand Down Expand Up @@ -411,6 +427,8 @@ public void setViewMode(ViewMode viewMode) {

public Map<UUID, Integer> getUsageCounts() { return _usageCounts; }

public void setGroups(Collection<VaultGroup> groups) { _groups = groups; }

public void setLastUsedTimestamps(Map<UUID, Long> lastUsedTimestamps) { _lastUsedTimestamps = lastUsedTimestamps; }

public Map<UUID, Long> getLastUsedTimestamps() { return _lastUsedTimestamps; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ public void setCopyBehavior(CopyBehavior copyBehavior) {
_adapter.setCopyBehavior(copyBehavior);
}

public void setSearchBehaviorMask(int searchBehaviorMask) {
_adapter.setSearchBehaviorMask(searchBehaviorMask);
}

public List<VaultEntry> selectAllEntries() {
return _adapter.selectAllEntries();
}
Expand Down Expand Up @@ -599,6 +603,7 @@ private void setShowProgress(boolean showProgress) {

public void setGroups(Collection<VaultGroup> groups) {
_groups = groups;
_adapter.setGroups(groups);
_groupChip.setVisibility(_groups.isEmpty() ? View.GONE : View.VISIBLE);
updateDividerDecoration();

Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@
<item>@string/pref_auto_lock_type_device_lock</item>
</string-array>

<string-array name="pref_search_behavior_types">
<item>@string/pref_search_behavior_type_issuer</item>
<item>@string/pref_search_behavior_type_name</item>
<item>@string/pref_search_behavior_type_note</item>
<item>@string/pref_search_behavior_type_groups</item>
</string-array>

<string-array name="export_formats">
<item>@string/export_format_aegis</item>
<item>@string/export_format_html</item>
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@
<string name="pref_encryption_summary">Encrypt the vault and unlock it with a password or biometrics</string>
<string name="pref_biometrics_title">Biometric unlock</string>
<string name="pref_biometrics_summary">Allow biometric authentication to unlock the vault</string>
<string name="pref_search_behavior_summary">Search through: %s</string>
<string name="pref_search_behavior_prompt">Search in any of the following fields</string>
<string name="pref_search_behavior_type_name">Name</string>
<string name="pref_search_behavior_type_issuer">Issuer</string>
<string name="pref_search_behavior_type_note">Note</string>
<string name="pref_search_behavior_type_groups">Groups</string>
<string name="pref_set_password_title">Change password</string>
<string name="pref_set_password_summary">Set a new password which you will need to unlock your vault</string>

Expand Down Expand Up @@ -351,6 +357,7 @@
<string name="pref_minimize_on_copy_title">Minimize on copy</string>
<string name="pref_minimize_on_copy_summary">Minimize the app after copying a token</string>
<string name="pref_copy_behavior_title">Copy tokens to the clipboard</string>
<string name="pref_search_behavior_title">Search behavior</string>
<string name="pref_pause_entry_title">Freeze tokens when tapped</string>
<string name="pref_pause_entry_summary">Pause automatic refresh of tokens by tapping them. Tokens will not update as long as they are focused. Requires \"Highlight tokens when tapped\" or \"Tap to reveal\".</string>

Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/xml/preferences_behavior.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
android:title="@string/pref_focus_search"
android:summary="@string/pref_focus_search_summary"
app:iconSpaceReserved="false"/>
<Preference
android:defaultValue="false"
android:key="pref_search_behavior"
android:title="@string/pref_search_behavior_title"
app:iconSpaceReserved="false"/>
<androidx.preference.SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_minimize_on_copy"
Expand Down

0 comments on commit 3bc3448

Please sign in to comment.