diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5fc7589d..34ac790f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -54,5 +54,10 @@ android:label="Manage key slots" android:theme="@style/AppTheme.TransparentActionBar"> + + diff --git a/app/src/main/java/me/impy/aegis/db/DatabaseManager.java b/app/src/main/java/me/impy/aegis/db/DatabaseManager.java index 8699dbe1..eb7bc900 100644 --- a/app/src/main/java/me/impy/aegis/db/DatabaseManager.java +++ b/app/src/main/java/me/impy/aegis/db/DatabaseManager.java @@ -172,6 +172,17 @@ public class DatabaseManager { return groups; } + public void removeGroup(String groupName) { + TreeSet groups = new TreeSet<>(Collator.getInstance()); + for (DatabaseEntry entry : getEntries()) { + String group = entry.getGroup(); + if (group != null && group.equals(groupName)) { + entry.setGroup(null); + _db.replaceEntry(entry); + } + } + } + public DatabaseFileCredentials getCredentials() { assertState(false, true); return _creds; diff --git a/app/src/main/java/me/impy/aegis/ui/GroupManagerActivity.java b/app/src/main/java/me/impy/aegis/ui/GroupManagerActivity.java new file mode 100644 index 00000000..56fe99c0 --- /dev/null +++ b/app/src/main/java/me/impy/aegis/ui/GroupManagerActivity.java @@ -0,0 +1,58 @@ +package me.impy.aegis.ui; + +import android.os.Bundle; + +import java.util.TreeSet; + +import androidx.appcompat.app.ActionBar; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import me.impy.aegis.AegisApplication; +import me.impy.aegis.R; +import me.impy.aegis.db.DatabaseFileCredentials; +import me.impy.aegis.db.DatabaseManager; +import me.impy.aegis.db.slots.Slot; +import me.impy.aegis.ui.views.GroupAdapter; +import me.impy.aegis.ui.views.SlotAdapter; + +public class GroupManagerActivity extends AegisActivity implements GroupAdapter.Listener { + private AegisApplication _app; + private DatabaseManager _db; + private GroupAdapter _adapter; + + TreeSet groups; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_groups); + + _app = (AegisApplication) getApplication(); + _db = _app.getDatabaseManager(); + + groups = _db.getGroups(); + + ActionBar bar = getSupportActionBar(); + bar.setHomeAsUpIndicator(R.drawable.ic_close); + bar.setDisplayHomeAsUpEnabled(true); + + // set up the recycler view + _adapter = new GroupAdapter(this); + RecyclerView slotsView = findViewById(R.id.list_slots); + LinearLayoutManager layoutManager = new LinearLayoutManager(this); + slotsView.setLayoutManager(layoutManager); + slotsView.setAdapter(_adapter); + slotsView.setNestedScrollingEnabled(false); + + // load the slots and masterKey + for (String group : groups) { + _adapter.addGroup(group); + } + } + + @Override + public void onRemoveGroup(String group) { + _db.removeGroup(group); + groups.remove(group); + } +} diff --git a/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java b/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java index 1141cc5d..9190c95b 100644 --- a/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java +++ b/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java @@ -67,6 +67,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat { private SwitchPreference _fingerprintPreference; private Preference _setPasswordPreference; private Preference _slotsPreference; + private Preference _groupsPreference; @Override public void onCreatePreferencesFix(Bundle savedInstanceState, String rootKey) { @@ -208,6 +209,15 @@ public class PreferencesFragment extends PreferenceFragmentCompat { } }); + _groupsPreference = findPreference("pref_groups"); + _groupsPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + Intent intent = new Intent(getActivity(), GroupManagerActivity.class); + startActivity(intent); + return true; + } + }); updateEncryptionPreferences(); } diff --git a/app/src/main/java/me/impy/aegis/ui/views/GroupAdapter.java b/app/src/main/java/me/impy/aegis/ui/views/GroupAdapter.java new file mode 100644 index 00000000..460f231b --- /dev/null +++ b/app/src/main/java/me/impy/aegis/ui/views/GroupAdapter.java @@ -0,0 +1,62 @@ +package me.impy.aegis.ui.views; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import java.util.ArrayList; + +import androidx.recyclerview.widget.RecyclerView; +import me.impy.aegis.R; +import me.impy.aegis.db.slots.Slot; + +public class GroupAdapter extends RecyclerView.Adapter { + private GroupAdapter.Listener _listener; + private ArrayList _groups; + + public GroupAdapter(GroupAdapter.Listener listener) { + _listener = listener; + _groups = new ArrayList<>(); + } + + public void addGroup(String group) { + _groups.add(group); + + int position = getItemCount() - 1; + if (position == 0) { + notifyDataSetChanged(); + } else { + notifyItemInserted(position); + } + } + + public void removeGroup(String group) { + int position = _groups.indexOf(group); + _groups.remove(position); + notifyItemRemoved(position); + } + + @Override + public GroupHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_slot, parent, false); + return new GroupHolder(view); + } + + @Override + public void onBindViewHolder(GroupHolder holder, int position) { + holder.setData(_groups.get(position)); + holder.setOnDeleteClickListener(v -> { + int position12 = holder.getAdapterPosition(); + _listener.onRemoveGroup(_groups.get(position12)); + }); + } + + @Override + public int getItemCount() { + return _groups.size(); + } + + public interface Listener { + void onRemoveGroup(String group); + } +} diff --git a/app/src/main/java/me/impy/aegis/ui/views/GroupHolder.java b/app/src/main/java/me/impy/aegis/ui/views/GroupHolder.java new file mode 100644 index 00000000..175897ec --- /dev/null +++ b/app/src/main/java/me/impy/aegis/ui/views/GroupHolder.java @@ -0,0 +1,35 @@ +package me.impy.aegis.ui.views; + +import androidx.recyclerview.widget.RecyclerView; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import me.impy.aegis.R; +import me.impy.aegis.crypto.KeyStoreHandle; +import me.impy.aegis.crypto.KeyStoreHandleException; +import me.impy.aegis.db.slots.FingerprintSlot; +import me.impy.aegis.db.slots.PasswordSlot; +import me.impy.aegis.db.slots.RawSlot; +import me.impy.aegis.db.slots.Slot; +import me.impy.aegis.helpers.FingerprintHelper; + +public class GroupHolder extends RecyclerView.ViewHolder { + private TextView _slotName; + private ImageView _buttonDelete; + + public GroupHolder(final View view) { + super(view); + _slotName = view.findViewById(R.id.text_slot_name); + _buttonDelete = view.findViewById(R.id.button_delete); + } + + public void setData(String groupName) { + _slotName.setText(groupName); + } + + public void setOnDeleteClickListener(View.OnClickListener listener) { + _buttonDelete.setOnClickListener(listener); + } +} diff --git a/app/src/main/res/layout/activity_groups.xml b/app/src/main/res/layout/activity_groups.xml new file mode 100644 index 00000000..862af3ab --- /dev/null +++ b/app/src/main/res/layout/activity_groups.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/card_group.xml b/app/src/main/res/layout/card_group.xml new file mode 100644 index 00000000..f44fb884 --- /dev/null +++ b/app/src/main/res/layout/card_group.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 47f46827..0143797b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -142,4 +142,6 @@ New group... Enter a group name Group name + Edit groups + Manage and delete your groups here diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index cd846caf..92cc1a04 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -20,6 +20,12 @@ android:title="@string/pref_account_name_title" android:summary="@string/pref_account_name_summary" app:iconSpaceReserved="false"/> + +