From 7c0b22920d44a068b69777f8ba6d09a76af10f99 Mon Sep 17 00:00:00 2001 From: Alexander Bakker Date: Tue, 1 Nov 2022 20:43:27 +0100 Subject: [PATCH] Fix minor entry margin issues Accidentally introduced with the entry pinning feature This also moves the favorite field to the vault instead of shared preference in order to avoid some complexity --- .../beemdevelopment/aegis/Preferences.java | 21 ------- .../SimpleItemTouchHelperCallback.java | 6 +- .../comparators/FavoriteComparator.java | 2 +- .../aegis/ui/MainActivity.java | 23 +++---- .../aegis/ui/views/EntryAdapter.java | 42 +++---------- .../aegis/ui/views/EntryHolder.java | 2 +- .../aegis/ui/views/EntryListView.java | 60 ++++++++++++------- .../aegis/vault/VaultEntry.java | 13 ++-- 8 files changed, 63 insertions(+), 106 deletions(-) diff --git a/app/src/main/java/com/beemdevelopment/aegis/Preferences.java b/app/src/main/java/com/beemdevelopment/aegis/Preferences.java index 9d7effbb..6d41e410 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/Preferences.java +++ b/app/src/main/java/com/beemdevelopment/aegis/Preferences.java @@ -235,27 +235,6 @@ public class Preferences { _prefs.edit().putString("pref_usage_count", usageCountJson.toString()).apply(); } - public List getFavorites() { - List favorites = new ArrayList<>(); - Set favoritesStringSet = _prefs.getStringSet("pref_favorites", null); - if(favoritesStringSet != null) { - for (String favorite : favoritesStringSet) { - favorites.add(UUID.fromString(favorite)); - } - } - - return favorites; - } - - public void setFavorites(List favorites) { - Set favoritesHashSet = new HashSet(); - for (UUID favorite : favorites) { - favoritesHashSet.add(favorite.toString()); - } - - _prefs.edit().putStringSet("pref_favorites", favoritesHashSet).apply(); - } - public int getTimeout() { return _prefs.getInt("pref_timeout", -1); } diff --git a/app/src/main/java/com/beemdevelopment/aegis/helpers/SimpleItemTouchHelperCallback.java b/app/src/main/java/com/beemdevelopment/aegis/helpers/SimpleItemTouchHelperCallback.java index 4ac8c79e..8aac5597 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/helpers/SimpleItemTouchHelperCallback.java +++ b/app/src/main/java/com/beemdevelopment/aegis/helpers/SimpleItemTouchHelperCallback.java @@ -33,7 +33,7 @@ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { return; } - if (!entry.getIsFavorited()) { + if (!entry.isFavorite()) { _selectedEntry = entry; } } @@ -65,7 +65,7 @@ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { - if(target.getAdapterPosition() < _adapter.getFavorites().size()){ + if (target.getAdapterPosition() < _adapter.getShownFavoritesCount()){ return false; } _adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); @@ -87,6 +87,4 @@ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { _positionChanged = false; } } - - } diff --git a/app/src/main/java/com/beemdevelopment/aegis/helpers/comparators/FavoriteComparator.java b/app/src/main/java/com/beemdevelopment/aegis/helpers/comparators/FavoriteComparator.java index 095c4008..fc16f009 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/helpers/comparators/FavoriteComparator.java +++ b/app/src/main/java/com/beemdevelopment/aegis/helpers/comparators/FavoriteComparator.java @@ -7,6 +7,6 @@ import java.util.Comparator; public class FavoriteComparator implements Comparator { @Override public int compare(VaultEntry a, VaultEntry b) { - return -1 * Boolean.compare(a.getIsFavorited(), b.getIsFavorited()); + return -1 * Boolean.compare(a.isFavorite(), b.isFavorite()); } } \ No newline at end of file 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 95a4419e..3930c20c 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java +++ b/app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java @@ -176,15 +176,10 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene @Override protected void onPause() { Map usageMap = _entryListView.getUsageCounts(); - List favoritesList = _entryListView.getFavorites(); if (usageMap != null) { _prefs.setUsageCount(usageMap); } - if (favoritesList != null) { - _prefs.setFavorites(favoritesList); - } - super.onPause(); } @@ -779,7 +774,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene private void loadEntries() { if (!_loaded) { _entryListView.setUsageCounts(_prefs.getUsageCounts()); - _entryListView.setFavorites(_prefs.getFavorites()); _entryListView.addEntries(_vaultManager.getVault().getEntries()); _entryListView.runEntriesAnimation(); _loaded = true; @@ -893,7 +887,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene MenuItem toggleFavoriteMenuItem = _actionMode.getMenu().findItem(R.id.action_toggle_favorite); if (_selectedEntries.size() == 1){ - if (_selectedEntries.get(0).getIsFavorited()) { + if (_selectedEntries.get(0).isFavorite()) { toggleFavoriteMenuItem.setIcon(R.drawable.ic_set_favorite); toggleFavoriteMenuItem.setTitle(R.string.unfavorite); } else { @@ -906,10 +900,6 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene } } - private void toggleFavorite(VaultEntry entry) { - _entryListView.toggleFavoriteState(entry); - } - @Override public void onLongEntryClick(VaultEntry entry) { if (!_selectedEntries.isEmpty()) { @@ -1062,7 +1052,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - if(_selectedEntries.size() == 0) { + if (_selectedEntries.size() == 0) { mode.finish(); return true; } @@ -1078,10 +1068,13 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene return true; case R.id.action_toggle_favorite: - for (VaultEntry entry : _selectedEntries) { - toggleFavorite(entry); - } + for (VaultEntry entry : _selectedEntries) { + entry.setIsFavorite(!entry.isFavorite()); + _entryListView.replaceEntry(entry.getUUID(), entry); + } + _entryListView.refresh(true); + saveAndBackupVault(); mode.finish(); return 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 26e4f520..6ddb1eb1 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 @@ -42,7 +42,6 @@ public class EntryAdapter extends RecyclerView.Adapter private List _shownEntries; private List _selectedEntries; private Map _usageCounts; - private List _favorites; private VaultEntry _focusedEntry; private Preferences.CodeGrouping _codeGroupSize; private boolean _showAccountName; @@ -113,17 +112,6 @@ public class EntryAdapter extends RecyclerView.Adapter _pauseFocused = pauseFocused; } - public void toggleFavoriteState(VaultEntry entry) { - if (_favorites.contains(entry.getUUID())) { - _favorites.remove(entry.getUUID()); - } else { - _favorites.add(entry.getUUID()); - } - - entry.setIsFavorited(_favorites.contains(entry.getUUID())); - updateShownEntries(); - } - public VaultEntry getEntryAt(int position) { return _shownEntries.get(position); } @@ -139,7 +127,7 @@ public class EntryAdapter extends RecyclerView.Adapter if (comparator != null) { // insert the entry in the correct order // note: this assumes that _shownEntries has already been sorted - for (int i = _favorites.size(); i < _shownEntries.size(); i++) { + for (int i = getShownFavoritesCount(); i < _shownEntries.size(); i++) { if (comparator.compare(_shownEntries.get(i), entry) > 0) { _shownEntries.add(i, entry); notifyItemInserted(i); @@ -169,7 +157,6 @@ public class EntryAdapter extends RecyclerView.Adapter public void addEntries(Collection entries) { for (VaultEntry entry: entries) { entry.setUsageCount(_usageCounts.containsKey(entry.getUUID()) ? _usageCounts.get(entry.getUUID()) : 0); - entry.setIsFavorited(_favorites.contains(entry.getUUID())); } _entries.addAll(entries); @@ -180,10 +167,6 @@ public class EntryAdapter extends RecyclerView.Adapter public void removeEntry(VaultEntry entry) { _entries.remove(entry); - if (_favorites.contains(entry.getUUID())) { - removeFavorite(entry); - } - if (_shownEntries.contains(entry)) { int position = _shownEntries.indexOf(entry); _shownEntries.remove(position); @@ -270,7 +253,7 @@ public class EntryAdapter extends RecyclerView.Adapter public void refresh(boolean hard) { if (hard) { - notifyDataSetChanged(); + updateShownEntries(); } else { for (EntryHolder holder : _holders) { holder.refresh(); @@ -336,19 +319,8 @@ public class EntryAdapter extends RecyclerView.Adapter public Map getUsageCounts() { return _usageCounts; } - public void setFavorites(List favorites) { _favorites = favorites; } - - public List getFavorites() { return _favorites; } - - public void removeFavorite(VaultEntry entry) { - int position = -1; - for (int i = 0; i < _favorites.size(); i++) { - if (_favorites.get(i).equals(entry.getUUID())) { - position = i; - } - } - - _favorites.remove(position); + public int getShownFavoritesCount() { + return (int) _shownEntries.stream().filter(VaultEntry::isFavorite).count(); } public void setGroups(TreeSet groups) { @@ -485,7 +457,7 @@ public class EntryAdapter extends RecyclerView.Adapter boolean dragEnabled = _selectedEntries.size() == 0 || _selectedEntries.size() == 1 && _selectedEntries.get(0) == entryHolder.getEntry(); - if (dragEnabled && isDragAndDropAllowed() && !entryHolder.getEntry().getIsFavorited()) { + if (dragEnabled && isDragAndDropAllowed() && !entryHolder.getEntry().isFavorite()) { _view.startDrag(_dragHandleHolder); } @@ -500,7 +472,7 @@ public class EntryAdapter extends RecyclerView.Adapter && _selectedEntries.size() == 1 && _selectedEntries.get(0) == entryHolder.getEntry() && isDragAndDropAllowed() - && !entryHolder.getEntry().getIsFavorited()) { + && !entryHolder.getEntry().isFavorite()) { _view.startDrag(_dragHandleHolder); return true; } @@ -644,7 +616,7 @@ public class EntryAdapter extends RecyclerView.Adapter return; } - if (_selectedEntries.size() == 1 && _dragHandleHolder == null && !_selectedEntries.get(0).getIsFavorited()) { + if (_selectedEntries.size() == 1 && _dragHandleHolder == null && !_selectedEntries.get(0).isFavorite()) { // Find and enable dragging for the single selected EntryHolder // Not nice but this is the best method I could find for (int i = 0; i < _holders.size(); i++) { 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 f31f5e0e..50300aea 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 @@ -116,7 +116,7 @@ public class EntryHolder extends RecyclerView.ViewHolder { _selectedHandler.removeCallbacksAndMessages(null); _animationHandler.removeCallbacksAndMessages(null); - _favoriteIndicator.setVisibility(_entry.getIsFavorited() ? View.VISIBLE : View.INVISIBLE); + _favoriteIndicator.setVisibility(_entry.isFavorite() ? View.VISIBLE : View.INVISIBLE); // only show the progress bar if there is no uniform period and the entry type is TotpInfo setShowProgress(showProgress); 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 93ef8096..c982daaa 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 @@ -1,5 +1,7 @@ package com.beemdevelopment.aegis.ui.views; +import static androidx.recyclerview.widget.RecyclerView.NO_POSITION; + import android.annotation.SuppressLint; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -197,12 +199,6 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { return _adapter.getUsageCounts(); } - public void setFavorites(List favorites) { - _adapter.setFavorites(favorites); - } - - public List getFavorites() { return _adapter.getFavorites(); } - public void setSearchFilter(String search) { _adapter.setSearchFilter(search); _touchCallback.setIsLongPressDragEnabled(_adapter.isDragAndDropAllowed()); @@ -356,10 +352,6 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { } } - public void toggleFavoriteState(VaultEntry entry) { - _adapter.toggleFavoriteState(entry); - } - public void tempHighlightEntry(VaultEntry entry) { _adapter.setTempHighlightEntry(true); @@ -540,7 +532,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { } private class VerticalSpaceItemDecoration extends RecyclerView.ItemDecoration { - private int _height; + private final int _height; private VerticalSpaceItemDecoration(float dp) { // convert dp to pixels @@ -549,27 +541,49 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener { @Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { - if (parent.getChildAdapterPosition(view) == 0 && (_groups == null || _groups.isEmpty())) { - // the first item should also have a top margin + int adapterPosition = parent.getChildAdapterPosition(view); + if (adapterPosition == NO_POSITION) { + return; + } + + // The footer always has a top and bottom margin + final int defaultMargin = MetricsHelper.convertDpToPixels(requireContext(), 20); + if (_adapter.isPositionFooter(adapterPosition)) { + outRect.top = defaultMargin; + outRect.bottom = defaultMargin; + return; + } + + // The first entry should have a top margin, but only if the group chip is not shown + if (adapterPosition == 0 && (_groups == null || _groups.isEmpty())) { outRect.top = _height; } - int adapterPosition = parent.getChildAdapterPosition(view); - if (adapterPosition == -1) { - return; + // Only non-favorite entries have a bottom margin, except for the final favorite and non-favorite entry + int totalFavorites = _adapter.getShownFavoritesCount(); + if (totalFavorites == 0 + || (adapterPosition < _adapter.getEntriesCount() && !_adapter.getEntryAt(adapterPosition).isFavorite()) + || totalFavorites == adapterPosition + 1) { + outRect.bottom = _height; } - if (adapterPosition < _adapter.getEntriesCount() && _adapter.getEntryAt(adapterPosition).getIsFavorited()) { - if (_adapter.getFavorites().size() == parent.getChildAdapterPosition(view) + 1) { - outRect.bottom = MetricsHelper.convertDpToPixels(requireContext(), 20); - return; + if (totalFavorites > 0) { + // If this entry is the last favorite entry in the list, it should always have + // a bottom margin, regardless of the view mode + if (adapterPosition == totalFavorites - 1) { + outRect.bottom = defaultMargin; } - outRect.bottom = 0; - return; + // If this is the first non-favorite entry, it should have a top margin + if (adapterPosition == totalFavorites) { + outRect.top = _height; + } } - outRect.top = _height; + // The last entry should never have a bottom margin + if (_adapter.getEntriesCount() == adapterPosition + 1) { + outRect.bottom = 0; + } } } 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 4aca13a3..9ad2d70b 100644 --- a/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntry.java +++ b/app/src/main/java/com/beemdevelopment/aegis/vault/VaultEntry.java @@ -17,8 +17,6 @@ import java.util.Arrays; import java.util.Objects; import java.util.UUID; -import javax.annotation.Nonnull; - public class VaultEntry extends UUIDMap.Value { private String _name = ""; private String _issuer = ""; @@ -26,7 +24,7 @@ public class VaultEntry extends UUIDMap.Value { private OtpInfo _info; private byte[] _icon; private IconType _iconType = IconType.INVALID; - private boolean _isFavorited; + private boolean _isFavorite; private int _usageCount; private String _note = ""; @@ -67,6 +65,7 @@ public class VaultEntry extends UUIDMap.Value { obj.put("issuer", _issuer); obj.put("group", _group); obj.put("note", _note); + obj.put("favorite", _isFavorite); obj.put("icon", _icon == null ? JSONObject.NULL : Base64.encode(_icon)); obj.put("icon_mime", _icon == null ? null : _iconType.toMimeType()); obj.put("info", _info.toJson()); @@ -93,6 +92,7 @@ public class VaultEntry extends UUIDMap.Value { entry.setIssuer(obj.getString("issuer")); entry.setGroup(obj.optString("group", null)); entry.setNote(obj.optString("note", "")); + entry.setIsFavorite(obj.optBoolean("favorite", false)); Object icon = obj.get("icon"); if (icon != JSONObject.NULL) { @@ -143,7 +143,7 @@ public class VaultEntry extends UUIDMap.Value { public String getNote() { return _note; } - public boolean getIsFavorited() { return _isFavorited; }; + public boolean isFavorite() { return _isFavorite; }; public void setName(String name) { _name = name; @@ -174,7 +174,7 @@ public class VaultEntry extends UUIDMap.Value { public void setNote(String note) { _note = note; } - public void setIsFavorited(boolean isFavorited) { _isFavorited = isFavorited; } + public void setIsFavorite(boolean isFavorite) { _isFavorite = isFavorite; } @Override public boolean equals(Object o) { @@ -198,7 +198,8 @@ public class VaultEntry extends UUIDMap.Value { && getInfo().equals(entry.getInfo()) && Arrays.equals(getIcon(), entry.getIcon()) && getIconType().equals(entry.getIconType()) - && getNote().equals(entry.getNote()); + && getNote().equals(entry.getNote()) + && isFavorite() == entry.isFavorite(); } /**