Skip to content

Commit

Permalink
Use DiffUtil for the RecyclerView of the entry list
Browse files Browse the repository at this point in the history
Gets rid of all of the custom logic we had for notifying the
RecyclerView about changes in the entry list. This will allow for more
simplifications in the future around non-persisted changes to state in
the entry list.

A neat side effect is that any filtering/ordering changes in the entry
list are now also animated: https://alexbakker.me/u/4a4ie5yzpj.mp4

This touches the fundamentals of the entry list, so lots of careful
testing required.
  • Loading branch information
alexbakker committed Sep 25, 2024
1 parent 08d900c commit 9131cae
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 348 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull Recycle
int swipeFlags = 0;
if (adapter.isPositionFooter(position)
|| adapter.isPositionErrorCard(position)
|| adapter.getEntryAtPos(position) != _selectedEntry
|| adapter.getEntryAtPosition(position) != _selectedEntry
|| !isLongPressDragEnabled()) {
return makeMovementFlags(0, swipeFlags);
}
Expand Down
73 changes: 31 additions & 42 deletions app/src/main/java/com/beemdevelopment/aegis/ui/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
if (activityResult.getResultCode() != RESULT_OK || activityResult.getData() == null) {
return;
}
onAssignIconsResult(activityResult.getData());
onAssignIconsResult();
});

private final ActivityResultLauncher<Intent> preferenceResultLauncher =
Expand All @@ -160,7 +160,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
if (activityResult.getResultCode() != RESULT_OK || activityResult.getData() == null) {
return;
}
onEditEntryResult(activityResult.getData());
onEditEntryResult();
});

private final ActivityResultLauncher<Intent> addEntryResultLauncher =
Expand Down Expand Up @@ -255,13 +255,13 @@ public void setGroups(Collection<VaultGroup> groups) {
_prefGroupFilter = null;
if (!groupFilter.isEmpty()) {
_groupFilter = groupFilter;
_entryListView.setGroupFilter(groupFilter, false);
_entryListView.setGroupFilter(groupFilter);
}
} else if (_groupFilter != null) {
Set<UUID> groupFilter = cleanGroupFilter(_groupFilter);
if (!_groupFilter.equals(groupFilter)) {
_groupFilter = groupFilter;
_entryListView.setGroupFilter(groupFilter, true);
_entryListView.setGroupFilter(groupFilter);
}
}

Expand Down Expand Up @@ -316,7 +316,7 @@ private void addChipTo(ChipGroup chipGroup, VaultGroupModel group) {
if (!isChecked) {
group1.setChecked(false);
_groupFilter = groupFilter;
_entryListView.setGroupFilter(groupFilter, false);
_entryListView.setGroupFilter(groupFilter);
return;
}

Expand All @@ -328,7 +328,7 @@ private void addChipTo(ChipGroup chipGroup, VaultGroupModel group) {
}

_groupFilter = groupFilter;
_entryListView.setGroupFilter(groupFilter, false);
_entryListView.setGroupFilter(groupFilter);
});

chipGroup.addView(chip);
Expand Down Expand Up @@ -573,31 +573,20 @@ private void onAddEntryResult(Intent data) {
if (_loaded) {
UUID entryUUID = (UUID) data.getSerializableExtra("entryUUID");
VaultEntry entry = _vaultManager.getVault().getEntryByUUID(entryUUID);
_entryListView.addEntry(entry, true);
_entryListView.setEntries(_vaultManager.getVault().getEntries());
_entryListView.onEntryAdded(entry);
}
}

private void onEditEntryResult(Intent data) {
private void onEditEntryResult() {
if (_loaded) {
UUID entryUUID = (UUID) data.getSerializableExtra("entryUUID");

if (data.getBooleanExtra("delete", false)) {
_entryListView.removeEntry(entryUUID);
} else {
VaultEntry entry = _vaultManager.getVault().getEntryByUUID(entryUUID);
_entryListView.replaceEntry(entryUUID, entry);
}
_entryListView.setEntries(_vaultManager.getVault().getEntries());
}
}

private void onAssignIconsResult(Intent data) {
private void onAssignIconsResult() {
if (_loaded) {
ArrayList<UUID> entryUUIDs = (ArrayList<UUID>) data.getSerializableExtra("entryUUIDs");

for (UUID entryUUID: entryUUIDs) {
VaultEntry entry = _vaultManager.getVault().getEntryByUUID(entryUUID);
_entryListView.replaceEntry(entryUUID, entry);
}
_entryListView.setEntries(_vaultManager.getVault().getEntries());
}
}

Expand Down Expand Up @@ -695,14 +684,11 @@ 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);
_entryListView.addEntry(entry);
}

if (saveAndBackupVault()) {
Toast.makeText(this, getResources().getQuantityString(R.plurals.added_new_entries, entries.size(), entries.size()), Toast.LENGTH_LONG).show();
}

_entryListView.setEntries(_vaultManager.getVault().getEntries());
}
}

Expand Down Expand Up @@ -925,15 +911,6 @@ protected void onStart() {
updateErrorCard();
}

private void deleteEntries(List<VaultEntry> entries) {
for (VaultEntry entry: entries) {
VaultEntry oldEntry = _vaultManager.getVault().removeEntry(entry);
_entryListView.removeEntry(oldEntry);
}

saveAndBackupVault();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
_menu = menu;
Expand Down Expand Up @@ -1063,7 +1040,7 @@ private void loadEntries() {
setGroups(_vaultManager.getVault().getUsedGroups());
_entryListView.setUsageCounts(_prefs.getUsageCounts());
_entryListView.setLastUsedTimestamps(_prefs.getLastUsedTimestamps());
_entryListView.addEntries(_vaultManager.getVault().getEntries());
_entryListView.setEntries(_vaultManager.getVault().getEntries());
if (!_isRecreated) {
_entryListView.runEntriesAnimation();
}
Expand Down Expand Up @@ -1291,6 +1268,13 @@ public void onLocked(boolean userInitiated) {
}
}

@Override
protected boolean saveAndBackupVault() {
boolean res = super.saveAndBackupVault();
updateErrorCard();
return res;
}

@SuppressLint("InlinedApi")
private void copyEntryCode(VaultEntry entry) {
String otp;
Expand Down Expand Up @@ -1387,12 +1371,13 @@ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
mode.finish();
} else if (itemId == R.id.action_toggle_favorite) {
for (VaultEntry entry : _selectedEntries) {
entry.setIsFavorite(!entry.isFavorite());
_entryListView.replaceEntry(entry.getUUID(), entry);
_vaultManager.getVault().editEntry(entry, newEntry -> {
newEntry.setIsFavorite(!newEntry.isFavorite());
});
}
_entryListView.refresh(true);

saveAndBackupVault();
_entryListView.setEntries(_vaultManager.getVault().getEntries());
mode.finish();
} else if (itemId == R.id.action_share_qr) {
Intent intent = new Intent(getBaseContext(), TransferEntriesActivity.class);
Expand All @@ -1410,8 +1395,12 @@ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
mode.finish();
} else if (itemId == R.id.action_delete) {
Dialogs.showDeleteEntriesDialog(MainActivity.this, _selectedEntries, (d, which) -> {
deleteEntries(_selectedEntries);
for (VaultEntry entry : _selectedEntries) {
_vaultManager.getVault().removeEntry(entry);
}
saveAndBackupVault();
_entryListView.setGroups(_vaultManager.getVault().getUsedGroups());
_entryListView.setEntries(_vaultManager.getVault().getEntries());
mode.finish();
});
} else if (itemId == R.id.action_select_all) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import android.view.View;

import com.google.common.hash.HashCode;

import java.util.Objects;

public class ErrorCardInfo {
private final String _message;
private final View.OnClickListener _listener;
Expand All @@ -18,4 +22,23 @@ public String getMessage() {
public View.OnClickListener getListener() {
return _listener;
}

@Override
public int hashCode() {
return HashCode.fromString(_message).asInt();
}

@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof ErrorCardInfo)) {
return false;
}

// This equality check purposefully ignores the onclick listener
ErrorCardInfo info = (ErrorCardInfo) o;
return Objects.equals(getMessage(), info.getMessage());
}
}
Loading

0 comments on commit 9131cae

Please sign in to comment.