mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-20 13:59:14 +00:00
Add the option to highlight entries when tapped
This adds an option to highlight tapped entries, so that it's easier to distinguisch between the one you're trying to enter into a website and the other ones. Only one entry can be highlighted at a time. Perhaps it would make sense to change our tap to reveal functionality to behave the same, so that the two features are nicely in sync. I can address that in a separate PR if we decide to do so.
This commit is contained in:
parent
5e7697039a
commit
51a0a16afb
8 changed files with 123 additions and 24 deletions
|
@ -19,7 +19,13 @@ public class Preferences {
|
|||
return _prefs.getBoolean("pref_tap_to_reveal", false);
|
||||
}
|
||||
|
||||
public boolean isSearchAccountNameEnabled() { return _prefs.getBoolean("pref_search_names", false); }
|
||||
public boolean isSearchAccountNameEnabled() {
|
||||
return _prefs.getBoolean("pref_search_names", false);
|
||||
}
|
||||
|
||||
public boolean isEntryHighlightEnabled() {
|
||||
return _prefs.getBoolean("pref_highlight_entry", false);
|
||||
}
|
||||
|
||||
public boolean isSecureScreenEnabled() {
|
||||
// screen security should be enabled by default, but not for debug builds
|
||||
|
|
|
@ -102,6 +102,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
_entryListView.setListener(this);
|
||||
_entryListView.setShowAccountName(getPreferences().isAccountNameVisible());
|
||||
_entryListView.setSearchAccountName(getPreferences().isSearchAccountNameEnabled());
|
||||
_entryListView.setHighlightEntry(getPreferences().isEntryHighlightEnabled());
|
||||
_entryListView.setTapToReveal(getPreferences().isTapToRevealEnabled());
|
||||
_entryListView.setTapToRevealTime(getPreferences().getTapToRevealTime());
|
||||
_entryListView.setSortCategory(getPreferences().getCurrentSortCategory(), false);
|
||||
|
@ -218,11 +219,13 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
} else if (data.getBooleanExtra("needsRefresh", false)) {
|
||||
boolean showAccountName = getPreferences().isAccountNameVisible();
|
||||
boolean searchAccountName = getPreferences().isSearchAccountNameEnabled();
|
||||
boolean highlightEntry = getPreferences().isEntryHighlightEnabled();
|
||||
boolean tapToReveal = getPreferences().isTapToRevealEnabled();
|
||||
int tapToRevealTime = getPreferences().getTapToRevealTime();
|
||||
ViewMode viewMode = getPreferences().getCurrentViewMode();
|
||||
_entryListView.setShowAccountName(showAccountName);
|
||||
_entryListView.setSearchAccountName(searchAccountName);
|
||||
_entryListView.setHighlightEntry(highlightEntry);
|
||||
_entryListView.setTapToReveal(tapToReveal);
|
||||
_entryListView.setTapToRevealTime(tapToRevealTime);
|
||||
_entryListView.setViewMode(viewMode);
|
||||
|
|
|
@ -207,6 +207,12 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
return true;
|
||||
});
|
||||
|
||||
Preference entryHighlightPreference = findPreference("pref_highlight_entry");
|
||||
entryHighlightPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
_result.putExtra("needsRefresh", true);
|
||||
return true;
|
||||
});
|
||||
|
||||
Preference tapToRevealPreference = findPreference("pref_tap_to_reveal");
|
||||
tapToRevealPreference.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
_result.putExtra("needsRefresh", true);
|
||||
|
@ -348,7 +354,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated (Bundle savedInstanceState) {
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
updateEncryptionPreferences();
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package com.beemdevelopment.aegis.ui.views;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.beemdevelopment.aegis.R;
|
||||
import com.beemdevelopment.aegis.SortCategory;
|
||||
import com.beemdevelopment.aegis.ViewMode;
|
||||
|
@ -19,15 +22,15 @@ import java.util.Collections;
|
|||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements ItemTouchHelperAdapter {
|
||||
private EntryListView _view;
|
||||
private List<DatabaseEntry> _entries;
|
||||
private List<DatabaseEntry> _shownEntries;
|
||||
private DatabaseEntry _selectedEntry;
|
||||
private DatabaseEntry _highlightedEntry;
|
||||
private boolean _showAccountName;
|
||||
private boolean _searchAccountName;
|
||||
private boolean _highlightEntry;
|
||||
private boolean _tapToReveal;
|
||||
private int _tapToRevealTime;
|
||||
private String _groupFilter;
|
||||
|
@ -35,6 +38,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
private ViewMode _viewMode;
|
||||
private String _searchFilter;
|
||||
private boolean _isPeriodUniform = true;
|
||||
private Handler _dimHandler;
|
||||
|
||||
// keeps track of the viewholders that are currently bound
|
||||
private List<EntryHolder> _holders;
|
||||
|
@ -43,6 +47,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
_entries = new ArrayList<>();
|
||||
_shownEntries = new ArrayList<>();
|
||||
_holders = new ArrayList<>();
|
||||
_dimHandler = new Handler();
|
||||
_view = view;
|
||||
}
|
||||
|
||||
|
@ -65,7 +70,13 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
_tapToRevealTime = number;
|
||||
}
|
||||
|
||||
public void setSearchAccountName(boolean searchAccountName) { _searchAccountName = searchAccountName; }
|
||||
public void setSearchAccountName(boolean searchAccountName) {
|
||||
_searchAccountName = searchAccountName;
|
||||
}
|
||||
|
||||
public void setHighlightEntry(boolean highlightEntry) {
|
||||
_highlightEntry = highlightEntry;
|
||||
}
|
||||
|
||||
public DatabaseEntry getEntryAt(int position) {
|
||||
return _shownEntries.get(position);
|
||||
|
@ -293,19 +304,34 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
DatabaseEntry entry = _shownEntries.get(position);
|
||||
holder.setFocused(entry == _selectedEntry);
|
||||
|
||||
boolean dimmed = _highlightedEntry != null && _highlightedEntry != entry;
|
||||
boolean showProgress = !isPeriodUniform() && entry.getInfo() instanceof TotpInfo;
|
||||
holder.setData(entry, _showAccountName, showProgress, _tapToReveal);
|
||||
holder.setData(entry, _showAccountName, showProgress, _tapToReveal, dimmed);
|
||||
holder.setTapToRevealTime(_tapToRevealTime);
|
||||
holder.loadIcon(_view);
|
||||
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int position = holder.getAdapterPosition();
|
||||
if (_tapToReveal && holder.isCodeHidden() && _selectedEntry == null) {
|
||||
holder.revealCode();
|
||||
} else {
|
||||
_view.onEntryClick(_shownEntries.get(position));
|
||||
boolean handled = false;
|
||||
|
||||
if (_selectedEntry == null) {
|
||||
if (_tapToReveal && holder.isCodeHidden()) {
|
||||
holder.revealCode();
|
||||
}
|
||||
|
||||
if (_highlightEntry) {
|
||||
if (_highlightedEntry == entry) {
|
||||
resetHighlight();
|
||||
handled = true;
|
||||
} else {
|
||||
highlightEntry(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
_view.onEntryClick(entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -384,9 +410,34 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
return period;
|
||||
}
|
||||
|
||||
private void highlightEntry(DatabaseEntry entry) {
|
||||
_highlightedEntry = entry;
|
||||
_dimHandler.removeCallbacksAndMessages(null);
|
||||
|
||||
for (EntryHolder holder : _holders) {
|
||||
if (holder.getEntry() != _highlightedEntry) {
|
||||
holder.dim();
|
||||
} else {
|
||||
holder.highlight();
|
||||
}
|
||||
}
|
||||
|
||||
_dimHandler.postDelayed(this::resetHighlight, _tapToRevealTime * 1000);
|
||||
}
|
||||
|
||||
private void resetHighlight() {
|
||||
_highlightedEntry = null;
|
||||
|
||||
for (EntryHolder holder : _holders) {
|
||||
holder.highlight();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSelectedEntry(DatabaseEntry entry) {
|
||||
if (entry == null) {
|
||||
notifyItemChanged(_shownEntries.indexOf(_selectedEntry));
|
||||
} else if (_highlightEntry) {
|
||||
resetHighlight();
|
||||
}
|
||||
|
||||
_selectedEntry = entry;
|
||||
|
|
|
@ -6,6 +6,9 @@ import android.view.View;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.beemdevelopment.aegis.R;
|
||||
import com.beemdevelopment.aegis.db.DatabaseEntry;
|
||||
|
@ -19,10 +22,10 @@ import com.beemdevelopment.aegis.otp.TotpInfo;
|
|||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class EntryHolder extends RecyclerView.ViewHolder {
|
||||
private static final float DEFAULT_ALPHA = 1.0f;
|
||||
private static final float DIMMED_ALPHA = 0.2f;
|
||||
|
||||
private TextView _profileName;
|
||||
private TextView _profileCode;
|
||||
private TextView _profileIssuer;
|
||||
|
@ -74,7 +77,7 @@ public class EntryHolder extends RecyclerView.ViewHolder {
|
|||
_hiddenHandler = new Handler();
|
||||
}
|
||||
|
||||
public void setData(DatabaseEntry entry, boolean showAccountName, boolean showProgress, boolean hidden) {
|
||||
public void setData(DatabaseEntry entry, boolean showAccountName, boolean showProgress, boolean hidden, boolean dimmed) {
|
||||
_entry = entry;
|
||||
_hidden = hidden;
|
||||
|
||||
|
@ -98,6 +101,12 @@ public class EntryHolder extends RecyclerView.ViewHolder {
|
|||
} else {
|
||||
refreshCode();
|
||||
}
|
||||
|
||||
itemView.setAlpha(dimmed ? DIMMED_ALPHA : DEFAULT_ALPHA);
|
||||
}
|
||||
|
||||
public DatabaseEntry getEntry() {
|
||||
return _entry;
|
||||
}
|
||||
|
||||
public void loadIcon(Fragment fragment) {
|
||||
|
@ -191,6 +200,18 @@ public class EntryHolder extends RecyclerView.ViewHolder {
|
|||
_hidden = false;
|
||||
}
|
||||
|
||||
public void dim() {
|
||||
animateAlphaTo(DIMMED_ALPHA);
|
||||
}
|
||||
|
||||
public void highlight() {
|
||||
animateAlphaTo(DEFAULT_ALPHA);
|
||||
}
|
||||
|
||||
private void animateAlphaTo(float alpha) {
|
||||
itemView.animate().alpha(alpha).setDuration(200).start();
|
||||
}
|
||||
|
||||
private void hideCode() {
|
||||
_profileCode.setText(R.string.tap_to_reveal);
|
||||
_hidden = true;
|
||||
|
|
|
@ -10,6 +10,15 @@ import android.view.animation.AnimationUtils;
|
|||
import android.view.animation.LayoutAnimationController;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.beemdevelopment.aegis.R;
|
||||
import com.beemdevelopment.aegis.SortCategory;
|
||||
import com.beemdevelopment.aegis.ViewMode;
|
||||
|
@ -27,15 +36,6 @@ import com.bumptech.glide.util.ViewPreloadSizeProvider;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
||||
private EntryAdapter _adapter;
|
||||
private Listener _listener;
|
||||
|
@ -215,6 +215,10 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
|||
_adapter.setSearchAccountName(searchAccountName);
|
||||
}
|
||||
|
||||
public void setHighlightEntry(boolean highlightEntry) {
|
||||
_adapter.setHighlightEntry(highlightEntry);
|
||||
}
|
||||
|
||||
public void setTapToReveal(boolean tapToReveal) {
|
||||
_adapter.setTapToReveal(tapToReveal);
|
||||
}
|
||||
|
|
|
@ -160,6 +160,8 @@
|
|||
<string name="preference_manage_groups_summary">Manage and delete your groups here</string>
|
||||
<string name="pref_search_name_title">Search in account names</string>
|
||||
<string name="pref_search_name_summary">Include account name matches in the search results</string>
|
||||
<string name="pref_highlight_entry_title">Highlight tokens when tapped</string>
|
||||
<string name="pref_highlight_entry_summary">Make tokens easier to distinguish from each other by temporarily highlighting them when tapped</string>
|
||||
<string name="tap_to_reveal">Hidden</string>
|
||||
<string name="selected">Selected</string>
|
||||
<string name="dark_theme_title">Dark theme</string>
|
||||
|
|
|
@ -51,6 +51,12 @@
|
|||
android:title="@string/pref_search_name_title"
|
||||
android:summary="@string/pref_search_name_summary"
|
||||
app:iconSpaceReserved="false"/>
|
||||
<androidx.preference.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="pref_highlight_entry"
|
||||
android:title="@string/pref_highlight_entry_title"
|
||||
android:summary="@string/pref_highlight_entry_summary"
|
||||
app:iconSpaceReserved="false"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
|
Loading…
Add table
Reference in a new issue