Add ability to reorder groups

This commit is contained in:
Michael Schättgen 2024-09-11 12:24:50 +02:00
parent 0046e8827e
commit d40e619cab
4 changed files with 53 additions and 40 deletions

View file

@ -7,6 +7,7 @@ import android.view.View;
import androidx.activity.OnBackPressedCallback; import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@ -14,13 +15,9 @@ import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.ui.dialogs.Dialogs; import com.beemdevelopment.aegis.ui.dialogs.Dialogs;
import com.beemdevelopment.aegis.ui.views.GroupAdapter; import com.beemdevelopment.aegis.ui.views.GroupAdapter;
import com.beemdevelopment.aegis.util.Cloner; import com.beemdevelopment.aegis.util.Cloner;
import com.beemdevelopment.aegis.vault.VaultEntryException;
import com.beemdevelopment.aegis.vault.VaultGroup; import com.beemdevelopment.aegis.vault.VaultGroup;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -30,7 +27,6 @@ import java.util.UUID;
public class GroupManagerActivity extends AegisActivity implements GroupAdapter.Listener { public class GroupManagerActivity extends AegisActivity implements GroupAdapter.Listener {
private GroupAdapter _adapter; private GroupAdapter _adapter;
private HashSet<UUID> _removedGroups; private HashSet<UUID> _removedGroups;
private HashSet<VaultGroup> _renamedGroups;
private RecyclerView _groupsView; private RecyclerView _groupsView;
private View _emptyStateView; private View _emptyStateView;
private BackPressHandler _backPressHandler; private BackPressHandler _backPressHandler;
@ -51,32 +47,45 @@ public class GroupManagerActivity extends AegisActivity implements GroupAdapter.
getOnBackPressedDispatcher().addCallback(this, _backPressHandler); getOnBackPressedDispatcher().addCallback(this, _backPressHandler);
_removedGroups = new HashSet<>(); _removedGroups = new HashSet<>();
_renamedGroups = new HashSet<>();
if (savedInstanceState != null) { if (savedInstanceState != null) {
List<String> removedGroups = savedInstanceState.getStringArrayList("removedGroups"); List<String> removedGroups = savedInstanceState.getStringArrayList("removedGroups");
List<String> renamedGroups = savedInstanceState.getStringArrayList("renamedGroups");
if (removedGroups != null) { if (removedGroups != null) {
for (String uuid : removedGroups) { for (String uuid : removedGroups) {
_removedGroups.add(UUID.fromString(uuid)); _removedGroups.add(UUID.fromString(uuid));
} }
} }
if (renamedGroups != null) {
for (String groupObject : renamedGroups) {
try {
_renamedGroups.add(VaultGroup.fromJson(new JSONObject(groupObject)));
} catch (VaultEntryException | JSONException ignored) {
// This is intentionally ignored since the json object is valid
}
} }
ItemTouchHelper touchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(
@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolder) {
return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0);
} }
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
int draggedItemIndex = viewHolder.getBindingAdapterPosition();
int targetIndex = target.getBindingAdapterPosition();
_adapter.onItemMove(draggedItemIndex, targetIndex);
return true;
} }
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { }
});
_adapter = new GroupAdapter(this); _adapter = new GroupAdapter(this);
_groupsView = findViewById(R.id.list_groups); _groupsView = findViewById(R.id.list_groups);
LinearLayoutManager layoutManager = new LinearLayoutManager(this); LinearLayoutManager layoutManager = new LinearLayoutManager(this);
_groupsView.setLayoutManager(layoutManager); _groupsView.setLayoutManager(layoutManager);
_groupsView.setAdapter(_adapter); _groupsView.setAdapter(_adapter);
_groupsView.setNestedScrollingEnabled(false); _groupsView.setNestedScrollingEnabled(false);
touchHelper.attachToRecyclerView(_groupsView);
for (VaultGroup group : _vaultManager.getVault().getGroups()) { for (VaultGroup group : _vaultManager.getVault().getGroups()) {
if (!_removedGroups.contains(group.getUUID())) { if (!_removedGroups.contains(group.getUUID())) {
@ -84,11 +93,6 @@ public class GroupManagerActivity extends AegisActivity implements GroupAdapter.
} }
} }
for(VaultGroup group: _renamedGroups) {
_adapter.replaceGroup(group.getUUID(), group);
}
_emptyStateView = findViewById(R.id.vEmptyList); _emptyStateView = findViewById(R.id.vEmptyList);
updateEmptyState(); updateEmptyState();
} }
@ -100,12 +104,7 @@ public class GroupManagerActivity extends AegisActivity implements GroupAdapter.
for (UUID uuid : _removedGroups) { for (UUID uuid : _removedGroups) {
removed.add(uuid.toString()); removed.add(uuid.toString());
} }
ArrayList<String> renamed = new ArrayList<>();
for (VaultGroup group : _renamedGroups) {
renamed.add(group.toJson().toString());
}
outState.putStringArrayList("renamedGroups", renamed);
outState.putStringArrayList("removedGroups", removed); outState.putStringArrayList("removedGroups", removed);
} }
@ -116,7 +115,6 @@ public class GroupManagerActivity extends AegisActivity implements GroupAdapter.
if (!newGroupName.isEmpty()) { if (!newGroupName.isEmpty()) {
VaultGroup newGroup = Cloner.clone(group); VaultGroup newGroup = Cloner.clone(group);
newGroup.setName(newGroupName); newGroup.setName(newGroupName);
_renamedGroups.add(newGroup);
_adapter.replaceGroup(group.getUUID(), newGroup); _adapter.replaceGroup(group.getUUID(), newGroup);
_backPressHandler.setEnabled(true); _backPressHandler.setEnabled(true);
} }
@ -166,23 +164,16 @@ public class GroupManagerActivity extends AegisActivity implements GroupAdapter.
for (UUID uuid : _removedGroups) { for (UUID uuid : _removedGroups) {
_vaultManager.getVault().removeGroup(uuid); _vaultManager.getVault().removeGroup(uuid);
} }
saveAndBackupVault();
}
if (!_renamedGroups.isEmpty()) {
_renamedGroups.removeIf(group -> _removedGroups.contains(group.getUUID()));
for (VaultGroup renamedGroup : _renamedGroups) {
_vaultManager.getVault().renameGroup(renamedGroup);
} }
_vaultManager.getVault().replaceGroups(_adapter.getGroups());
saveAndBackupVault(); saveAndBackupVault();
}
finish(); finish();
} }
private void discardAndFinish() { private void discardAndFinish() {
if (_removedGroups.isEmpty() && _renamedGroups.isEmpty()) { if (_removedGroups.isEmpty()) {
finish(); finish();
return; return;
} }

View file

@ -7,12 +7,14 @@ import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.beemdevelopment.aegis.R; import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.helpers.ItemTouchHelperAdapter;
import com.beemdevelopment.aegis.util.CollectionUtils;
import com.beemdevelopment.aegis.vault.VaultGroup; import com.beemdevelopment.aegis.vault.VaultGroup;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.UUID; import java.util.UUID;
public class GroupAdapter extends RecyclerView.Adapter<GroupHolder> { public class GroupAdapter extends RecyclerView.Adapter<GroupHolder> implements ItemTouchHelperAdapter {
private GroupAdapter.Listener _listener; private GroupAdapter.Listener _listener;
private ArrayList<VaultGroup> _groups; private ArrayList<VaultGroup> _groups;
@ -32,6 +34,10 @@ public class GroupAdapter extends RecyclerView.Adapter<GroupHolder> {
} }
} }
public ArrayList<VaultGroup> getGroups() {
return _groups;
}
public void replaceGroup(UUID uuid, VaultGroup newGroup) { public void replaceGroup(UUID uuid, VaultGroup newGroup) {
VaultGroup oldGroup = getGroupByUUID(uuid); VaultGroup oldGroup = getGroupByUUID(uuid);
int position = _groups.indexOf(oldGroup); int position = _groups.indexOf(oldGroup);
@ -64,6 +70,18 @@ public class GroupAdapter extends RecyclerView.Adapter<GroupHolder> {
}); });
} }
@Override
public void onItemMove(int firstPosition, int secondPosition) {
CollectionUtils.move(_groups, firstPosition, secondPosition);
notifyItemMoved(firstPosition, secondPosition);
}
@Override
public void onItemDismiss(int position) { }
@Override
public void onItemDrop(int position) { }
private VaultGroup getGroupByUUID(UUID uuid) { private VaultGroup getGroupByUUID(UUID uuid) {
for (VaultGroup group : _groups) { for (VaultGroup group : _groups) {
if (group.getUUID().equals(uuid)) { if (group.getUUID().equals(uuid)) {

View file

@ -291,8 +291,11 @@ public class VaultRepository {
removeGroup(group); removeGroup(group);
} }
public void renameGroup(VaultGroup renamedGroup) { public void replaceGroups(Collection<VaultGroup> groups) {
_vault.getGroups().replace(renamedGroup); _vault.getGroups().wipe();
for (VaultGroup group : groups) {
_vault.getGroups().add(group);
}
} }
public void removeGroup(VaultGroup group) { public void removeGroup(VaultGroup group) {

View file

@ -3,6 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/colorBackground"
android:orientation="horizontal"> android:orientation="horizontal">
<LinearLayout <LinearLayout