mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-21 14:29:13 +00:00
Add ability to sort based on last used timestamp
This commit is contained in:
parent
dfd720b406
commit
9bae4d6bbc
11 changed files with 130 additions and 3 deletions
|
@ -235,10 +235,51 @@ public class Preferences {
|
|||
setUsageCount(usageCounts);
|
||||
}
|
||||
|
||||
public long getLastUsedTimestamp(UUID uuid) {
|
||||
Map<UUID, Long> timestamps = getLastUsedTimestamps();
|
||||
if (timestamps != null && timestamps.size() > 0){
|
||||
Long timestamp = timestamps.get(uuid);
|
||||
return timestamp != null ? timestamp : 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void clearUsageCount() {
|
||||
_prefs.edit().remove("pref_usage_count").apply();
|
||||
}
|
||||
|
||||
public Map<UUID, Long> getLastUsedTimestamps() {
|
||||
Map<UUID, Long> lastUsedTimestamps = new HashMap<>();
|
||||
String lastUsedTimestamp = _prefs.getString("pref_last_used_timestamps", "");
|
||||
try {
|
||||
JSONArray arr = new JSONArray(lastUsedTimestamp);
|
||||
for (int i = 0; i < arr.length(); i++) {
|
||||
JSONObject json = arr.getJSONObject(i);
|
||||
lastUsedTimestamps.put(UUID.fromString(json.getString("uuid")), json.getLong("timestamp"));
|
||||
}
|
||||
} catch (JSONException ignored) {
|
||||
}
|
||||
|
||||
return lastUsedTimestamps;
|
||||
}
|
||||
|
||||
public void setLastUsedTimestamps(Map<UUID, Long> lastUsedTimestamps) {
|
||||
JSONArray lastUsedTimestampJson = new JSONArray();
|
||||
for (Map.Entry<UUID, Long> entry : lastUsedTimestamps.entrySet()) {
|
||||
JSONObject entryJson = new JSONObject();
|
||||
try {
|
||||
entryJson.put("uuid", entry.getKey());
|
||||
entryJson.put("timestamp", entry.getValue());
|
||||
lastUsedTimestampJson.put(entryJson);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
_prefs.edit().putString("pref_last_used_timestamps", lastUsedTimestampJson.toString()).apply();
|
||||
}
|
||||
|
||||
public Map<UUID, Integer> getUsageCounts() {
|
||||
Map<UUID, Integer> usageCounts = new HashMap<>();
|
||||
String usageCount = _prefs.getString("pref_usage_count", "");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.beemdevelopment.aegis;
|
||||
|
||||
import com.beemdevelopment.aegis.helpers.comparators.LastUsedComparator;
|
||||
import com.beemdevelopment.aegis.helpers.comparators.UsageCountComparator;
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
import com.beemdevelopment.aegis.helpers.comparators.AccountNameComparator;
|
||||
|
@ -14,7 +15,8 @@ public enum SortCategory {
|
|||
ACCOUNT_REVERSED,
|
||||
ISSUER,
|
||||
ISSUER_REVERSED,
|
||||
USAGE_COUNT;
|
||||
USAGE_COUNT,
|
||||
LAST_USED;
|
||||
|
||||
private static SortCategory[] _values;
|
||||
|
||||
|
@ -45,6 +47,8 @@ public enum SortCategory {
|
|||
case USAGE_COUNT:
|
||||
comparator = Collections.reverseOrder(new UsageCountComparator());
|
||||
break;
|
||||
case LAST_USED:
|
||||
comparator = Collections.reverseOrder(new LastUsedComparator());
|
||||
}
|
||||
|
||||
return comparator;
|
||||
|
@ -64,6 +68,8 @@ public enum SortCategory {
|
|||
return R.id.menu_sort_alphabetically_reverse;
|
||||
case USAGE_COUNT:
|
||||
return R.id.menu_sort_usage_count;
|
||||
case LAST_USED:
|
||||
return R.id.menu_sort_last_used;
|
||||
default:
|
||||
return R.id.menu_sort_custom;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.beemdevelopment.aegis.helpers.comparators;
|
||||
|
||||
import com.beemdevelopment.aegis.vault.VaultEntry;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class LastUsedComparator implements Comparator<VaultEntry> {
|
||||
@Override
|
||||
public int compare(VaultEntry a, VaultEntry b) {
|
||||
return Long.compare(a.getLastUsedTimestamp(), b.getLastUsedTimestamp());
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ import android.widget.AutoCompleteTextView;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
|
@ -75,10 +76,12 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -113,6 +116,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
private LinearLayout _textPinLayout;
|
||||
private TextInputEditText _textUsageCount;
|
||||
private TextInputEditText _textNote;
|
||||
private TextView _textLastUsed;
|
||||
|
||||
private AutoCompleteTextView _dropdownType;
|
||||
private AutoCompleteTextView _dropdownAlgo;
|
||||
|
@ -200,6 +204,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
_textPinLayout = findViewById(R.id.layout_pin);
|
||||
_textUsageCount = findViewById(R.id.text_usage_count);
|
||||
_textNote = findViewById(R.id.text_note);
|
||||
_textLastUsed = findViewById(R.id.text_last_used);
|
||||
_dropdownType = findViewById(R.id.dropdown_type);
|
||||
DropdownHelper.fillDropdown(this, _dropdownType, R.array.otp_types_array);
|
||||
_dropdownAlgoLayout = findViewById(R.id.dropdown_algo_layout);
|
||||
|
@ -378,6 +383,7 @@ public class EditEntryActivity extends AegisActivity {
|
|||
});
|
||||
|
||||
_textUsageCount.setText(_prefs.getUsageCount(entryUUID).toString());
|
||||
setLastUsedTimestamp(_prefs.getLastUsedTimestamp(entryUUID));
|
||||
}
|
||||
|
||||
private void updateAdvancedFieldStatus(String otpType) {
|
||||
|
@ -608,6 +614,16 @@ public class EditEntryActivity extends AegisActivity {
|
|||
saveAndFinish(entry, false);
|
||||
}
|
||||
|
||||
private void setLastUsedTimestamp(long timestamp) {
|
||||
String readableDate = getString(R.string.last_used_never);
|
||||
if (timestamp != 0) {
|
||||
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.getDefault());
|
||||
readableDate = dateFormat.format(new Date(timestamp));
|
||||
}
|
||||
|
||||
_textLastUsed.setText(String.format("%s: %s", getString(R.string.last_used), readableDate));
|
||||
}
|
||||
|
||||
private void deleteAndFinish(VaultEntry entry) {
|
||||
_vaultManager.getVault().removeEntry(entry);
|
||||
saveAndFinish(entry, true);
|
||||
|
|
|
@ -241,6 +241,11 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
_prefs.setUsageCount(usageMap);
|
||||
}
|
||||
|
||||
Map<UUID, Long> lastUsedMap = _entryListView.getLastUsedTimestamps();
|
||||
if (lastUsedMap != null) {
|
||||
_prefs.setLastUsedTimestamps(lastUsedMap);
|
||||
}
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
@ -696,6 +701,8 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
// update the usage counts in case they are edited outside of the EntryListView
|
||||
_entryListView.setUsageCounts(_prefs.getUsageCounts());
|
||||
|
||||
_entryListView.setLastUsedTimestamps(_prefs.getLastUsedTimestamps());
|
||||
|
||||
// refresh all codes to prevent showing old ones
|
||||
_entryListView.refresh(false);
|
||||
} else {
|
||||
|
@ -825,6 +832,8 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
sortCategory = SortCategory.ACCOUNT_REVERSED;
|
||||
} else if (subItemId == R.id.menu_sort_usage_count) {
|
||||
sortCategory = SortCategory.USAGE_COUNT;
|
||||
} else if (subItemId == R.id.menu_sort_last_used) {
|
||||
sortCategory = SortCategory.LAST_USED;
|
||||
} else {
|
||||
sortCategory = SortCategory.CUSTOM;
|
||||
}
|
||||
|
@ -847,6 +856,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
|
|||
private void loadEntries() {
|
||||
if (!_loaded) {
|
||||
_entryListView.setUsageCounts(_prefs.getUsageCounts());
|
||||
_entryListView.setLastUsedTimestamps(_prefs.getLastUsedTimestamps());
|
||||
_entryListView.addEntries(_vaultManager.getVault().getEntries());
|
||||
_entryListView.runEntriesAnimation();
|
||||
_loaded = true;
|
||||
|
|
|
@ -37,6 +37,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -51,6 +52,7 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
|||
private List<VaultEntry> _shownEntries;
|
||||
private List<VaultEntry> _selectedEntries;
|
||||
private Map<UUID, Integer> _usageCounts;
|
||||
private Map<UUID, Long> _lastUsedTimestamps;
|
||||
private VaultEntry _focusedEntry;
|
||||
private VaultEntry _clickedEntry;
|
||||
private Preferences.CodeGrouping _codeGroupSize;
|
||||
|
@ -190,6 +192,7 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
|||
public void addEntries(Collection<VaultEntry> entries) {
|
||||
for (VaultEntry entry: entries) {
|
||||
entry.setUsageCount(_usageCounts.containsKey(entry.getUUID()) ? _usageCounts.get(entry.getUUID()) : 0);
|
||||
entry.setLastUsedTimestamp(_lastUsedTimestamps.containsKey(entry.getUUID()) ? _lastUsedTimestamps.get(entry.getUUID()) : 0);
|
||||
}
|
||||
|
||||
_entries.addAll(entries);
|
||||
|
@ -407,6 +410,10 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
|||
|
||||
public Map<UUID, Integer> getUsageCounts() { return _usageCounts; }
|
||||
|
||||
public void setLastUsedTimestamps(Map<UUID, Long> lastUsedTimestamps) { _lastUsedTimestamps = lastUsedTimestamps; }
|
||||
|
||||
public Map<UUID, Long> getLastUsedTimestamps() { return _lastUsedTimestamps; }
|
||||
|
||||
public int getShownFavoritesCount() {
|
||||
return (int) _shownEntries.stream().filter(VaultEntry::isFavorite).count();
|
||||
}
|
||||
|
@ -805,6 +812,8 @@ public class EntryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
|||
int usageCount = _usageCounts.get(entry.getUUID());
|
||||
_usageCounts.put(entry.getUUID(), ++usageCount);
|
||||
}
|
||||
|
||||
_lastUsedTimestamps.put(entry.getUUID(), new Date().getTime());
|
||||
}
|
||||
|
||||
public boolean isDragAndDropAllowed() {
|
||||
|
|
|
@ -223,6 +223,14 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
|||
return _adapter.getUsageCounts();
|
||||
}
|
||||
|
||||
public void setLastUsedTimestamps(Map<UUID, Long> lastUsedTimestamps) {
|
||||
_adapter.setLastUsedTimestamps(lastUsedTimestamps);
|
||||
}
|
||||
|
||||
public Map<UUID, Long> getLastUsedTimestamps() {
|
||||
return _adapter.getLastUsedTimestamps();
|
||||
}
|
||||
|
||||
public void setSearchFilter(String search) {
|
||||
_adapter.setSearchFilter(search);
|
||||
_touchCallback.setIsLongPressDragEnabled(_adapter.isDragAndDropAllowed());
|
||||
|
|
|
@ -23,6 +23,7 @@ public class VaultEntry extends UUIDMap.Value {
|
|||
private VaultEntryIcon _icon;
|
||||
private boolean _isFavorite;
|
||||
private int _usageCount;
|
||||
private long _lastUsedTimestamp;
|
||||
private String _note = "";
|
||||
private String _oldGroup;
|
||||
private Set<UUID> _groups = new TreeSet<>();
|
||||
|
@ -135,6 +136,10 @@ public class VaultEntry extends UUIDMap.Value {
|
|||
return _usageCount;
|
||||
}
|
||||
|
||||
public long getLastUsedTimestamp() {
|
||||
return _lastUsedTimestamp;
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
return _note;
|
||||
}
|
||||
|
@ -143,8 +148,6 @@ public class VaultEntry extends UUIDMap.Value {
|
|||
return _isFavorite;
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
public void setName(String name) {
|
||||
_name = name;
|
||||
}
|
||||
|
@ -187,6 +190,8 @@ public class VaultEntry extends UUIDMap.Value {
|
|||
_usageCount = usageCount;
|
||||
}
|
||||
|
||||
public void setLastUsedTimestamp(long lastUsedTimestamp) { _lastUsedTimestamp = lastUsedTimestamp; }
|
||||
|
||||
public void setNote(String note) {
|
||||
_note = note;
|
||||
}
|
||||
|
|
|
@ -376,8 +376,22 @@
|
|||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/text_last_used"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_gravity="bottom|center"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
<item
|
||||
android:id="@+id/menu_sort_usage_count"
|
||||
android:title="@string/sort_usage_count"/>
|
||||
<item
|
||||
android:id="@+id/menu_sort_last_used"
|
||||
android:title="@string/sort_last_used"/>
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
|
|
|
@ -303,7 +303,10 @@
|
|||
<string name="sort_alphabetically_name">Account (A to Z)</string>
|
||||
<string name="sort_alphabetically_name_reverse">Account (Z to A)</string>
|
||||
<string name="sort_usage_count">Usage count</string>
|
||||
<string name="sort_last_used">Last used</string>
|
||||
<string name="sort_custom">Custom</string>
|
||||
<string name="last_used">Last used</string>
|
||||
<string name="last_used_never">never</string>
|
||||
<string name="new_group">New group…</string>
|
||||
<string name="group">Group</string>
|
||||
<string name="group_name_hint">Group name</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue