From fbe4e7aae78f1702eb74e6c2931f7dba1e0ff847 Mon Sep 17 00:00:00 2001 From: binsky08 Date: Fri, 12 Sep 2025 17:34:34 +0200 Subject: [PATCH 1/2] auto save user's selected credential sort order #181 Signed-off-by: binsky08 --- app/src/main/java/es/wolfi/app/passman/SettingValues.java | 3 ++- .../app/passman/fragments/CredentialItemFragment.java | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/es/wolfi/app/passman/SettingValues.java b/app/src/main/java/es/wolfi/app/passman/SettingValues.java index 84691dc0..b532bfba 100644 --- a/app/src/main/java/es/wolfi/app/passman/SettingValues.java +++ b/app/src/main/java/es/wolfi/app/passman/SettingValues.java @@ -40,7 +40,8 @@ public enum SettingValues { OFFLINE_STORAGE("offline_storage"), ENABLE_OFFLINE_CACHE("enable_offline_cache"), KEY_STORE_MIGRATION_STATE("key_store_migration_state"), - KEY_STORE_ENCRYPTION_KEY("key_store_encryption_key"); + KEY_STORE_ENCRYPTION_KEY("key_store_encryption_key"), + CREDENTIAL_LABEL_SORT("credential_label_sort"); private final String name; diff --git a/app/src/main/java/es/wolfi/app/passman/fragments/CredentialItemFragment.java b/app/src/main/java/es/wolfi/app/passman/fragments/CredentialItemFragment.java index 5db19325..b6fccc34 100644 --- a/app/src/main/java/es/wolfi/app/passman/fragments/CredentialItemFragment.java +++ b/app/src/main/java/es/wolfi/app/passman/fragments/CredentialItemFragment.java @@ -21,6 +21,7 @@ package es.wolfi.app.passman.fragments; import android.content.Context; +import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; @@ -70,6 +71,7 @@ public class CredentialItemFragment extends Fragment { private RecyclerView recyclerView; private Vault customVault = null; private boolean enableLimitedAutofillView = false; + private SharedPreferences sharedPreferences; /** * Mandatory empty constructor for the fragment manager to instantiate the @@ -139,6 +141,7 @@ public void onClick(View view) { vault.sort(sortMethod); applyFilters(vault, searchInput); + sharedPreferences.edit().putInt(SettingValues.CREDENTIAL_LABEL_SORT.toString(), sortMethod).apply(); } }); vault.sort(sortMethod); @@ -206,6 +209,10 @@ public void onClick(View view) { } else { recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount)); } + + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext()); + sortMethod = sharedPreferences.getInt(SettingValues.CREDENTIAL_LABEL_SORT.toString(), CredentialLabelSort.SortMethod.STANDARD.ordinal()); + loadCredentialList(view); } return view; From 7630d96a6ea20519681ce5d426f6022a0824cf1a Mon Sep 17 00:00:00 2001 From: binsky08 Date: Fri, 12 Sep 2025 18:15:38 +0200 Subject: [PATCH 2/2] implement credential sort settings as well as a case-insensitive sort option #181 Signed-off-by: binsky08 --- .../es/wolfi/app/passman/SettingValues.java | 4 +++- .../fragments/CredentialItemFragment.java | 10 ++++++--- .../passman/fragments/SettingsFragment.java | 11 ++++++++++ .../main/java/es/wolfi/passman/API/Vault.java | 4 ++-- .../es/wolfi/utils/CredentialLabelSort.java | 12 +++++++--- app/src/main/res/layout/fragment_settings.xml | 22 +++++++++++++++++++ app/src/main/res/values/strings.xml | 3 +++ 7 files changed, 57 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/es/wolfi/app/passman/SettingValues.java b/app/src/main/java/es/wolfi/app/passman/SettingValues.java index b532bfba..6f3af7a8 100644 --- a/app/src/main/java/es/wolfi/app/passman/SettingValues.java +++ b/app/src/main/java/es/wolfi/app/passman/SettingValues.java @@ -41,7 +41,9 @@ public enum SettingValues { ENABLE_OFFLINE_CACHE("enable_offline_cache"), KEY_STORE_MIGRATION_STATE("key_store_migration_state"), KEY_STORE_ENCRYPTION_KEY("key_store_encryption_key"), - CREDENTIAL_LABEL_SORT("credential_label_sort"); + CREDENTIAL_LABEL_SORT("credential_label_sort"), + CASE_INSENSITIVE_CREDENTIAL_LABEL_SORT("case_insensitive_credential_label_sort"), + RESTORE_CUSTOM_CREDENTIAL_SORT_ORDER("restore_custom_credential_sort_order"); private final String name; diff --git a/app/src/main/java/es/wolfi/app/passman/fragments/CredentialItemFragment.java b/app/src/main/java/es/wolfi/app/passman/fragments/CredentialItemFragment.java index b6fccc34..02b51d17 100644 --- a/app/src/main/java/es/wolfi/app/passman/fragments/CredentialItemFragment.java +++ b/app/src/main/java/es/wolfi/app/passman/fragments/CredentialItemFragment.java @@ -72,6 +72,7 @@ public class CredentialItemFragment extends Fragment { private Vault customVault = null; private boolean enableLimitedAutofillView = false; private SharedPreferences sharedPreferences; + private boolean caseInsensitiveSort = false; /** * Mandatory empty constructor for the fragment manager to instantiate the @@ -139,12 +140,12 @@ public void onClick(View view) { sortMethod = (++sortMethod % 3); updateToggleSortButtonImage(toggleSortButton); - vault.sort(sortMethod); + vault.sort(sortMethod, caseInsensitiveSort); applyFilters(vault, searchInput); sharedPreferences.edit().putInt(SettingValues.CREDENTIAL_LABEL_SORT.toString(), sortMethod).apply(); } }); - vault.sort(sortMethod); + vault.sort(sortMethod, caseInsensitiveSort); recyclerView.setAdapter(new CredentialViewAdapter(vault.getCredentials(), mListener, PreferenceManager.getDefaultSharedPreferences(getContext()))); scrollToLastPosition(); updateToggleSortButtonImage(toggleSortButton); @@ -211,7 +212,10 @@ public void onClick(View view) { } sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext()); - sortMethod = sharedPreferences.getInt(SettingValues.CREDENTIAL_LABEL_SORT.toString(), CredentialLabelSort.SortMethod.STANDARD.ordinal()); + caseInsensitiveSort = sharedPreferences.getBoolean(SettingValues.CASE_INSENSITIVE_CREDENTIAL_LABEL_SORT.toString(), false); + if (sharedPreferences.getBoolean(SettingValues.RESTORE_CUSTOM_CREDENTIAL_SORT_ORDER.toString(), true)) { + sortMethod = sharedPreferences.getInt(SettingValues.CREDENTIAL_LABEL_SORT.toString(), CredentialLabelSort.SortMethod.STANDARD.ordinal()); + } loadCredentialList(view); } diff --git a/app/src/main/java/es/wolfi/app/passman/fragments/SettingsFragment.java b/app/src/main/java/es/wolfi/app/passman/fragments/SettingsFragment.java index bccb3783..f97ddd7e 100644 --- a/app/src/main/java/es/wolfi/app/passman/fragments/SettingsFragment.java +++ b/app/src/main/java/es/wolfi/app/passman/fragments/SettingsFragment.java @@ -106,6 +106,8 @@ public class SettingsFragment extends Fragment { MaterialCheckBox enable_autofill_manual_search_fallback; Button open_autofill_android_settings_button; EditText clear_clipboard_delay_value; + MaterialCheckBox settings_case_insensitive_credential_label_sort_switch; + MaterialCheckBox settings_restore_custom_credential_sort_order_switch; EditText request_connect_timeout_value; EditText request_response_timeout_value; @@ -170,6 +172,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, open_autofill_android_settings_button = view.findViewById(R.id.open_autofill_android_settings_button); clear_clipboard_delay_value = view.findViewById(R.id.clear_clipboard_delay_value); + settings_case_insensitive_credential_label_sort_switch = view.findViewById(R.id.settings_case_insensitive_credential_label_sort_switch); + settings_restore_custom_credential_sort_order_switch = view.findViewById(R.id.settings_restore_custom_credential_sort_order_switch); + request_connect_timeout_value = view.findViewById(R.id.request_connect_timeout_value); request_response_timeout_value = view.findViewById(R.id.request_response_timeout_value); clear_offline_cache_button = view.findViewById(R.id.clear_offline_cache_button); @@ -281,6 +286,9 @@ public void onClick(View view) { clear_clipboard_delay_value.setText(String.valueOf(settings.getInt(SettingValues.CLEAR_CLIPBOARD_DELAY.toString(), 0))); + settings_case_insensitive_credential_label_sort_switch.setChecked(settings.getBoolean(SettingValues.CASE_INSENSITIVE_CREDENTIAL_LABEL_SORT.toString(), false)); + settings_restore_custom_credential_sort_order_switch.setChecked(settings.getBoolean(SettingValues.RESTORE_CUSTOM_CREDENTIAL_SORT_ORDER.toString(), true)); + request_connect_timeout_value.setText(String.valueOf(settings.getInt(SettingValues.REQUEST_CONNECT_TIMEOUT.toString(), 15))); request_response_timeout_value.setText(String.valueOf(settings.getInt(SettingValues.REQUEST_RESPONSE_TIMEOUT.toString(), 120))); clear_offline_cache_button.setText(String.format("%s (%s)", getString(R.string.clear_offline_cache), OfflineStorage.getInstance().getSize())); @@ -356,6 +364,9 @@ public void onClick(View view) { settings.edit().putInt(SettingValues.CLEAR_CLIPBOARD_DELAY.toString(), Integer.parseInt(clear_clipboard_delay_value.getText().toString())).commit(); Objects.requireNonNull(((PasswordListActivity) getActivity())).attachClipboardListener(); + settings.edit().putBoolean(SettingValues.CASE_INSENSITIVE_CREDENTIAL_LABEL_SORT.toString(), settings_case_insensitive_credential_label_sort_switch.isChecked()).commit(); + settings.edit().putBoolean(SettingValues.RESTORE_CUSTOM_CREDENTIAL_SORT_ORDER.toString(), settings_restore_custom_credential_sort_order_switch.isChecked()).commit(); + settings.edit().putInt(SettingValues.REQUEST_CONNECT_TIMEOUT.toString(), Integer.parseInt(request_connect_timeout_value.getText().toString())).commit(); settings.edit().putInt(SettingValues.REQUEST_RESPONSE_TIMEOUT.toString(), Integer.parseInt(request_response_timeout_value.getText().toString())).commit(); diff --git a/app/src/main/java/es/wolfi/passman/API/Vault.java b/app/src/main/java/es/wolfi/passman/API/Vault.java index 935301dc..c99df91f 100644 --- a/app/src/main/java/es/wolfi/passman/API/Vault.java +++ b/app/src/main/java/es/wolfi/passman/API/Vault.java @@ -352,9 +352,9 @@ public void onCompleted(Exception e, String result) { }); } - public void sort(int method) { + public void sort(int method, boolean caseInsensitiveSort) { credential_guid.clear(); - Collections.sort(credentials, new CredentialLabelSort(method)); + Collections.sort(credentials, new CredentialLabelSort(method, caseInsensitiveSort)); for (int i = 0; i < credentials.size(); i++) { credential_guid.put(credentials.get(i).getGuid(), i); } diff --git a/app/src/main/java/es/wolfi/utils/CredentialLabelSort.java b/app/src/main/java/es/wolfi/utils/CredentialLabelSort.java index 664b93d7..a0e02355 100644 --- a/app/src/main/java/es/wolfi/utils/CredentialLabelSort.java +++ b/app/src/main/java/es/wolfi/utils/CredentialLabelSort.java @@ -45,18 +45,24 @@ public enum SortMethod { } private final int method; + private final boolean caseInsensitiveSort; - public CredentialLabelSort(int method) { + public CredentialLabelSort(int method, boolean caseInsensitiveSort) { this.method = method; + this.caseInsensitiveSort = caseInsensitiveSort; } @Override public int compare(Credential left, Credential right) { if (method == SortMethod.ALPHABETICALLY_ASCENDING.ordinal()) { - return left.getLabel().compareTo(right.getLabel()); + return this.caseInsensitiveSort + ? left.getLabel().toLowerCase().compareTo(right.getLabel().toLowerCase()) + : left.getLabel().compareTo(right.getLabel()); } if (method == SortMethod.ALPHABETICALLY_DESCENDING.ordinal()) { - return right.getLabel().compareTo(left.getLabel()); + return this.caseInsensitiveSort + ? right.getLabel().toLowerCase().compareTo(left.getLabel().toLowerCase()) + : right.getLabel().compareTo(left.getLabel()); } return left.getId() - right.getId(); } diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 134b01e5..7ef08b72 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -241,6 +241,28 @@ android:inputType="number" tools:ignore="LabelFor" /> + + + + + + Manual credential search as autofill fallback option Set as autofill service Algorithm + Enable case-insensitive credential sort + Credential list sort settings + Restore custom credential sort order