Merge pull request #467 from Ullas-Aithal/feature/443
Added 'Most Used' sort option #443
This commit is contained in:
commit
b2b8b582bc
8 changed files with 84 additions and 5 deletions
|
@ -512,6 +512,9 @@ public class MainActivity extends BaseActivity
|
||||||
} else if (mode == SortMode.LAST_USED) {
|
} else if (mode == SortMode.LAST_USED) {
|
||||||
sortMenu.setIcon(R.drawable.ic_sort_inverted_time_white);
|
sortMenu.setIcon(R.drawable.ic_sort_inverted_time_white);
|
||||||
menu.findItem(R.id.menu_sort_last_used).setChecked(true);
|
menu.findItem(R.id.menu_sort_last_used).setChecked(true);
|
||||||
|
} else if (mode == SortMode.MOST_USED) {
|
||||||
|
sortMenu.setIcon(R.drawable.ic_sort_inverted_time_white);
|
||||||
|
menu.findItem(R.id.menu_sort_most_used).setChecked(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,6 +612,16 @@ public class MainActivity extends BaseActivity
|
||||||
}
|
}
|
||||||
if (! settings.getLastUsedDialogShown())
|
if (! settings.getLastUsedDialogShown())
|
||||||
showLastUsedDialog();
|
showLastUsedDialog();
|
||||||
|
} else if (id == R.id.menu_sort_most_used) {
|
||||||
|
item.setChecked(true);
|
||||||
|
sortMenu.setIcon(R.drawable.ic_sort_inverted_time_white);
|
||||||
|
saveSortMode(SortMode.MOST_USED);
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.setSortMode(SortMode.MOST_USED);
|
||||||
|
touchHelperCallback.setDragEnabled(false);
|
||||||
|
}
|
||||||
|
if (! settings.getMostUsedDialogShown())
|
||||||
|
showMostUsedDialog();
|
||||||
} else if (tagsToggle.onOptionsItemSelected(item)) {
|
} else if (tagsToggle.onOptionsItemSelected(item)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -630,6 +643,20 @@ public class MainActivity extends BaseActivity
|
||||||
.create()
|
.create()
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
private void showMostUsedDialog() {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setTitle(R.string.dialog_title_manual_entry)
|
||||||
|
.setTitle(R.string.dialog_title_most_used)
|
||||||
|
.setMessage(R.string.dialog_msg_most_used)
|
||||||
|
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
|
settings.setMostUsedDialogShown(true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create()
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void setupDrawer() {
|
private void setupDrawer() {
|
||||||
tagsDrawerListView = findViewById(R.id.tags_list_in_drawer);
|
tagsDrawerListView = findViewById(R.id.tags_list_in_drawer);
|
||||||
|
|
|
@ -60,6 +60,7 @@ public class Entry {
|
||||||
private static final String JSON_TAGS = "tags";
|
private static final String JSON_TAGS = "tags";
|
||||||
private static final String JSON_THUMBNAIL = "thumbnail";
|
private static final String JSON_THUMBNAIL = "thumbnail";
|
||||||
private static final String JSON_LAST_USED = "last_used";
|
private static final String JSON_LAST_USED = "last_used";
|
||||||
|
private static final String JSON_USED_FREQUENCY = "used_frequency";
|
||||||
|
|
||||||
private OTPType type = OTPType.TOTP;
|
private OTPType type = OTPType.TOTP;
|
||||||
private int period = TokenCalculator.TOTP_DEFAULT_PERIOD;
|
private int period = TokenCalculator.TOTP_DEFAULT_PERIOD;
|
||||||
|
@ -74,6 +75,7 @@ public class Entry {
|
||||||
private Runnable hideTask = null;
|
private Runnable hideTask = null;
|
||||||
private long last_update = 0;
|
private long last_update = 0;
|
||||||
private long last_used = 0;
|
private long last_used = 0;
|
||||||
|
private long used_frequency = 0;
|
||||||
public List<String> tags = new ArrayList<>();
|
public List<String> tags = new ArrayList<>();
|
||||||
private EntryThumbnail.EntryThumbnails thumbnail = EntryThumbnail.EntryThumbnails.Default;
|
private EntryThumbnail.EntryThumbnails thumbnail = EntryThumbnail.EntryThumbnails.Default;
|
||||||
private static final int COLOR_DEFAULT = 0;
|
private static final int COLOR_DEFAULT = 0;
|
||||||
|
@ -240,6 +242,12 @@ public class Entry {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
this.last_used = 0;
|
this.last_used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.used_frequency = jsonObj.getLong(JSON_USED_FREQUENCY);
|
||||||
|
} catch (Exception e) {
|
||||||
|
this.used_frequency = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject toJSON() throws JSONException {
|
public JSONObject toJSON() throws JSONException {
|
||||||
|
@ -252,6 +260,7 @@ public class Entry {
|
||||||
jsonObj.put(JSON_ALGORITHM, algorithm.toString());
|
jsonObj.put(JSON_ALGORITHM, algorithm.toString());
|
||||||
jsonObj.put(JSON_THUMBNAIL, getThumbnail().name());
|
jsonObj.put(JSON_THUMBNAIL, getThumbnail().name());
|
||||||
jsonObj.put(JSON_LAST_USED, getLastUsed());
|
jsonObj.put(JSON_LAST_USED, getLastUsed());
|
||||||
|
jsonObj.put(JSON_USED_FREQUENCY, getUsedFrequency() );
|
||||||
|
|
||||||
if (type == OTPType.TOTP)
|
if (type == OTPType.TOTP)
|
||||||
jsonObj.put(JSON_PERIOD, getPeriod());
|
jsonObj.put(JSON_PERIOD, getPeriod());
|
||||||
|
@ -373,6 +382,14 @@ public class Entry {
|
||||||
this.last_used = value;
|
this.last_used = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getUsedFrequency() {
|
||||||
|
return used_frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsedFrequency(long value) {
|
||||||
|
this.used_frequency = value;
|
||||||
|
}
|
||||||
|
|
||||||
public String getCurrentOTP() {
|
public String getCurrentOTP() {
|
||||||
return currentOTP;
|
return currentOTP;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class Constants {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SortMode {
|
public enum SortMode {
|
||||||
UNSORTED, LABEL, LAST_USED
|
UNSORTED, LABEL, LAST_USED, MOST_USED
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum BackupType {
|
public enum BackupType {
|
||||||
|
|
|
@ -530,6 +530,13 @@ public class Settings {
|
||||||
public void setLastUsedDialogShown(boolean value) {
|
public void setLastUsedDialogShown(boolean value) {
|
||||||
setBoolean(R.string.settings_key_last_used_dialog_shown, value);
|
setBoolean(R.string.settings_key_last_used_dialog_shown, value);
|
||||||
}
|
}
|
||||||
|
public boolean getMostUsedDialogShown() {
|
||||||
|
return getBoolean(R.string.settings_key_most_used_dialog_shown, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMostUsedDialogShown(boolean value) {
|
||||||
|
setBoolean(R.string.settings_key_most_used_dialog_shown, value);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getNewBackupFormatDialogShown() {
|
public boolean getNewBackupFormatDialogShown() {
|
||||||
return getBoolean(R.string.settings_key_new_backup_format_dialog_shown, false);
|
return getBoolean(R.string.settings_key_new_backup_format_dialog_shown, false);
|
||||||
|
|
|
@ -270,7 +270,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
||||||
@Override
|
@Override
|
||||||
public void onCopyButtonClicked(String text, int position) {
|
public void onCopyButtonClicked(String text, int position) {
|
||||||
copyToClipboard(text);
|
copyToClipboard(text);
|
||||||
updateLastUsed(position, getRealIndex(position));
|
updateLastUsedAndFrequency(position, getRealIndex(position));
|
||||||
if(context != null && settings.isMinimizeAppOnCopyEnabled()) {
|
if(context != null && settings.isMinimizeAppOnCopyEnabled()) {
|
||||||
((MainActivity)context).moveTaskToBack(true);
|
((MainActivity)context).moveTaskToBack(true);
|
||||||
}
|
}
|
||||||
|
@ -339,7 +339,7 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
||||||
entries.get(realIndex).setHideTask(null);
|
entries.get(realIndex).setHideTask(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean updateNeeded = updateLastUsed(pos, realIndex);
|
boolean updateNeeded = updateLastUsedAndFrequency(pos, realIndex);
|
||||||
|
|
||||||
if (pos >= 0) {
|
if (pos >= 0) {
|
||||||
displayedEntries.get(pos).setVisible(false);
|
displayedEntries.get(pos).setVisible(false);
|
||||||
|
@ -390,19 +390,28 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean updateLastUsed(int position, int realIndex) {
|
private boolean updateLastUsedAndFrequency(int position, int realIndex) {
|
||||||
long timeStamp = System.currentTimeMillis();
|
long timeStamp = System.currentTimeMillis();
|
||||||
|
long entryUsedFrequency = entries.get(realIndex).getUsedFrequency();
|
||||||
|
|
||||||
if (position >= 0)
|
if (position >= 0) {
|
||||||
|
long displayEntryUsedFrequency = displayedEntries.get(position).getUsedFrequency();
|
||||||
displayedEntries.get(position).setLastUsed(timeStamp);
|
displayedEntries.get(position).setLastUsed(timeStamp);
|
||||||
|
displayedEntries.get(position).setUsedFrequency(displayEntryUsedFrequency + 1);
|
||||||
|
}
|
||||||
|
|
||||||
entries.get(realIndex).setLastUsed(timeStamp);
|
entries.get(realIndex).setLastUsed(timeStamp);
|
||||||
|
entries.get(realIndex).setUsedFrequency(entryUsedFrequency + 1);
|
||||||
saveEntries(settings.getAutoBackupEncryptedFullEnabled());
|
saveEntries(settings.getAutoBackupEncryptedFullEnabled());
|
||||||
|
|
||||||
if (sortMode == SortMode.LAST_USED) {
|
if (sortMode == SortMode.LAST_USED) {
|
||||||
displayedEntries = sortEntries(displayedEntries);
|
displayedEntries = sortEntries(displayedEntries);
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
return false;
|
return false;
|
||||||
|
} else if (sortMode == SortMode.MOST_USED) {
|
||||||
|
displayedEntries = sortEntries(displayedEntries);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -728,6 +737,8 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
||||||
Collections.sort(sorted, new LabelComparator());
|
Collections.sort(sorted, new LabelComparator());
|
||||||
} else if (sortMode == SortMode.LAST_USED) {
|
} else if (sortMode == SortMode.LAST_USED) {
|
||||||
Collections.sort(sorted, new LastUsedComparator());
|
Collections.sort(sorted, new LastUsedComparator());
|
||||||
|
} else if (sortMode == SortMode.MOST_USED) {
|
||||||
|
Collections.sort(sorted, new MostUsedComparator());
|
||||||
}
|
}
|
||||||
|
|
||||||
return sorted;
|
return sorted;
|
||||||
|
@ -822,6 +833,13 @@ public class EntriesCardAdapter extends RecyclerView.Adapter<EntryViewHolder>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class MostUsedComparator implements Comparator<Entry> {
|
||||||
|
@Override
|
||||||
|
public int compare(Entry o1, Entry o2) {
|
||||||
|
return Long.compare(o2.getUsedFrequency(), o1.getUsedFrequency());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
void onMoveEventStart();
|
void onMoveEventStart();
|
||||||
void onMoveEventStop();
|
void onMoveEventStop();
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_sort_last_used"
|
android:id="@+id/menu_sort_last_used"
|
||||||
android:title="@string/menu_sort_last_used" />
|
android:title="@string/menu_sort_last_used" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_sort_most_used"
|
||||||
|
android:title="@string/menu_sort_most_used" />
|
||||||
</group>
|
</group>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
<string name="settings_key_clear_keystore" translatable="false">pref_clear_keystore</string>
|
<string name="settings_key_clear_keystore" translatable="false">pref_clear_keystore</string>
|
||||||
|
|
||||||
<string name="settings_key_last_used_dialog_shown" translatable="false">pref_last_used_dialog_shown</string>
|
<string name="settings_key_last_used_dialog_shown" translatable="false">pref_last_used_dialog_shown</string>
|
||||||
|
<string name="settings_key_most_used_dialog_shown" translatable="false">pref_most_used_dialog_shown</string>
|
||||||
|
|
||||||
<!-- Default values -->
|
<!-- Default values -->
|
||||||
<integer name="settings_default_tap_to_reveal_timeout">30</integer>
|
<integer name="settings_default_tap_to_reveal_timeout">30</integer>
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
<string name="menu_sort_none">Unsorted</string>
|
<string name="menu_sort_none">Unsorted</string>
|
||||||
<string name="menu_sort_label">Label</string>
|
<string name="menu_sort_label">Label</string>
|
||||||
<string name="menu_sort_last_used">Last used</string>
|
<string name="menu_sort_last_used">Last used</string>
|
||||||
|
<string name="menu_sort_most_used">Most used</string>
|
||||||
|
|
||||||
<string name="menu_popup_edit_issuer">Edit issuer</string>
|
<string name="menu_popup_edit_issuer">Edit issuer</string>
|
||||||
<string name="menu_popup_edit_label">Edit label</string>
|
<string name="menu_popup_edit_label">Edit label</string>
|
||||||
|
@ -77,6 +78,7 @@
|
||||||
<string name="dialog_title_rename">Rename</string>
|
<string name="dialog_title_rename">Rename</string>
|
||||||
<string name="dialog_title_counter">Counter</string>
|
<string name="dialog_title_counter">Counter</string>
|
||||||
<string name="dialog_title_last_used">Last used</string>
|
<string name="dialog_title_last_used">Last used</string>
|
||||||
|
<string name="dialog_title_most_used">Most used</string>
|
||||||
<string name="dialog_title_keystore_error">KeyStore error</string>
|
<string name="dialog_title_keystore_error">KeyStore error</string>
|
||||||
|
|
||||||
<string name="dialog_title_enter_password">Enter password</string>
|
<string name="dialog_title_enter_password">Enter password</string>
|
||||||
|
@ -91,6 +93,10 @@
|
||||||
you have to have \"tap to reveal\" enabled or use the copy button.\n\nThis message will not
|
you have to have \"tap to reveal\" enabled or use the copy button.\n\nThis message will not
|
||||||
be shown again.</string>
|
be shown again.</string>
|
||||||
|
|
||||||
|
<string name="dialog_msg_most_used">In order for andOTP to recognize which token was used the most
|
||||||
|
you have to have \"tap to reveal\" enabled or use the copy button.\n\nThis message will not
|
||||||
|
be shown again.</string>
|
||||||
|
|
||||||
<string name="dialog_msg_keystore_error">Failed to load the encryption key from the KeyStore.
|
<string name="dialog_msg_keystore_error">Failed to load the encryption key from the KeyStore.
|
||||||
<b>Any entries that are added will get lost.</b>\n\nTo still be able to use andOTP you can go
|
<b>Any entries that are added will get lost.</b>\n\nTo still be able to use andOTP you can go
|
||||||
to the <b>Settings</b> and switch the <b>Database encryption</b> to <b>Password / PIN</b>.</string>
|
to the <b>Settings</b> and switch the <b>Database encryption</b> to <b>Password / PIN</b>.</string>
|
||||||
|
|
Loading…
Reference in a new issue