From 6593522bba0f7fbb6ef0236a3c839b73cd46159a Mon Sep 17 00:00:00 2001 From: smiley Date: Sun, 16 Aug 2026 19:20:13 +0300 Subject: [PATCH] Add configurable save directory for Autofill-saved entries Credentials saved via the Autofill framework (the system "Save to Password Store?" prompt shown while the app is closed) were always written directly to the repository root, with no way to route them into a category subfolder like a user-organized store might use. Add a "Save directory" setting under Settings > Autofill that lets users specify a root subfolder; Autofill-originated saves are then resolved under that folder instead of the store root. Leaving it unset preserves the existing behavior exactly. The in-app "+" entry creation flow is unaffected in every case. Fixes #127 --- .../ui/autofill/AutofillSaveActivity.kt | 3 ++- .../ui/settings/AutofillSettings.kt | 12 +++++++++++ .../util/autofill/AutofillPreferences.kt | 20 +++++++++++++++++++ .../util/settings/PreferenceKeys.kt | 1 + app/src/main/res/values/strings.xml | 4 ++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt b/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt index 138c4a737c..176f148e0c 100644 --- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt @@ -128,6 +128,7 @@ class AutofillSaveActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val repo = PasswordRepository.getRepositoryDirectory() + val saveRoot = AutofillPreferences.saveDirectory(this) val saveIntent = Intent(this, PasswordCreationActivity::class.java).apply { putExtras( @@ -136,7 +137,7 @@ class AutofillSaveActivity : AppCompatActivity() { putString(BasePGPActivity.EXTRA_REPO_PATH, repo.absolutePath) putString( BasePGPActivity.EXTRA_FILE_PATH, - repo + saveRoot .resolve(intent.getStringExtra(EXTRA_FOLDER_NAME) ?: throw NullPointerException()) .absolutePath, ) diff --git a/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt index ce009a1071..684a09cc11 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt @@ -109,6 +109,18 @@ class AutofillSettings(private val activity: FragmentActivity) : SettingsProvide summaryProvider = { activity.getString(R.string.preference_custom_public_suffixes_summary) } textInputHintRes = R.string.preference_custom_public_suffixes_hint } + editText(PreferenceKeys.AUTOFILL_SAVE_DIRECTORY) { + dependency = PreferenceKeys.AUTOFILL_ENABLE + titleRes = R.string.preference_autofill_save_directory_title + summaryProvider = { value -> + activity.getString( + R.string.preference_autofill_save_directory_summary, + value?.takeUnless { it.isBlank() } + ?: activity.getString(R.string.preference_autofill_save_directory_root_placeholder), + ) + } + textInputHintRes = R.string.preference_autofill_save_directory_hint + } } } } diff --git a/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt b/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt index f9298b2c11..2b7d03708b 100644 --- a/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt +++ b/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt @@ -7,6 +7,7 @@ package app.passwordstore.util.autofill import android.content.Context import androidx.core.content.edit import app.passwordstore.data.passfile.PasswordEntry +import app.passwordstore.data.repo.PasswordRepository import app.passwordstore.util.extensions.getString import app.passwordstore.util.extensions.sharedPrefs import app.passwordstore.util.services.getDefaultUsername @@ -22,6 +23,25 @@ object AutofillPreferences { return DirectoryStructure.fromValue(value) } + /** + * The directory Autofill-saved credentials should be placed under, relative to the repository + * root. Backed by [PreferenceKeys.AUTOFILL_SAVE_DIRECTORY]; falls back to the repository root + * itself when unset. This only affects saves made through the Autofill framework (the system + * "Save to Password Store?" prompt) — it has no effect on entries created from within the app. + */ + fun saveDirectory(context: Context): File { + val root = PasswordRepository.getRepositoryDirectory() + // Drop empty and ".." segments to prevent escaping the repository root. + val configured = + context.sharedPrefs + .getString(PreferenceKeys.AUTOFILL_SAVE_DIRECTORY) + ?.split('/') + ?.filter { it.isNotBlank() && it != ".." } + ?.joinToString("/") + ?.takeUnless { it.isBlank() } + return if (configured == null) root else root.resolve(configured) + } + fun strictDomainSearch(context: Context): Boolean { return context.sharedPrefs.getBoolean(PreferenceKeys.STRICT_DOMAIN_SEARCH, true) } diff --git a/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt b/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt index c090b7cc0f..5261d0c57f 100644 --- a/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt +++ b/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt @@ -58,6 +58,7 @@ object PreferenceKeys { const val OREO_AUTOFILL_CUSTOM_PUBLIC_SUFFIXES = "oreo_autofill_custom_public_suffixes" const val OREO_AUTOFILL_DEFAULT_USERNAME = "oreo_autofill_default_username" const val DIRECTORY_STRUCTURE = "oreo_autofill_directory_structure" + const val AUTOFILL_SAVE_DIRECTORY = "oreo_autofill_save_directory" const val STRICT_DOMAIN_SEARCH = "oreo_autofill_strict_domain_search" const val PREF_KEY_PWGEN_TYPE = "pref_key_pwgen_type" const val REPOSITORY_INITIALIZED = "repository_initialized" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cb18607fe7..88d50e883b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -330,6 +330,10 @@ Custom domains Autofill will distinguish subdomains of these domains. company.com\npersonal.com + Save directory + Credentials saved via Autofill are placed under this folder instead of the store root. Currently: %1$s + e.g. www + store root Password item edited