Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Commit

Permalink
directory structure setting moved to general settings (#3166)
Browse files Browse the repository at this point in the history
* directory structure setting moved to general settings

* Update app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt

Co-authored-by: Harsh Shandilya <[email protected]>
Signed-off-by: Alexander Grahn <[email protected]>

---------

Signed-off-by: Alexander Grahn <[email protected]>
Co-authored-by: Harsh Shandilya <[email protected]>
  • Loading branch information
agrahn and msfjarvis authored Aug 14, 2024
1 parent 401e6cb commit 0e76ef0
Show file tree
Hide file tree
Showing 20 changed files with 145 additions and 141 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ import app.passwordstore.util.auth.BiometricAuthenticator
import app.passwordstore.util.auth.BiometricAuthenticator.Result as BiometricResult
import app.passwordstore.util.autofill.AutofillPreferences
import app.passwordstore.util.autofill.AutofillResponseBuilder
import app.passwordstore.util.autofill.DirectoryStructure
import app.passwordstore.util.extensions.asLog
import app.passwordstore.util.features.Feature.EnablePGPPassphraseCache
import app.passwordstore.util.features.Features
import app.passwordstore.util.settings.DirectoryStructure
import app.passwordstore.util.settings.PreferenceKeys
import com.github.androidpasswordstore.autofillparser.AutofillAction
import com.github.androidpasswordstore.autofillparser.Credentials
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import app.passwordstore.data.password.PasswordItem
import app.passwordstore.databinding.ActivityOreoAutofillFilterBinding
import app.passwordstore.util.autofill.AutofillMatcher
import app.passwordstore.util.autofill.AutofillPreferences
import app.passwordstore.util.autofill.DirectoryStructure
import app.passwordstore.util.coroutines.DispatcherProvider
import app.passwordstore.util.extensions.viewBinding
import app.passwordstore.util.settings.DirectoryStructure
import app.passwordstore.util.viewmodel.FilterMode
import app.passwordstore.util.viewmodel.ListMode
import app.passwordstore.util.viewmodel.SearchMode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import app.passwordstore.ui.dialogs.DicewarePasswordGeneratorDialogFragment
import app.passwordstore.ui.dialogs.OtpImportDialogFragment
import app.passwordstore.ui.dialogs.PasswordGeneratorDialogFragment
import app.passwordstore.util.autofill.AutofillPreferences
import app.passwordstore.util.autofill.DirectoryStructure
import app.passwordstore.util.extensions.asLog
import app.passwordstore.util.extensions.base64
import app.passwordstore.util.extensions.commitChange
Expand All @@ -39,6 +38,7 @@ import app.passwordstore.util.extensions.isInsideRepository
import app.passwordstore.util.extensions.snackbar
import app.passwordstore.util.extensions.unsafeLazy
import app.passwordstore.util.extensions.viewBinding
import app.passwordstore.util.settings.DirectoryStructure
import app.passwordstore.util.settings.PreferenceKeys
import com.github.michaelbull.result.onFailure
import com.github.michaelbull.result.onSuccess
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import app.passwordstore.BuildConfig
import app.passwordstore.R
import app.passwordstore.util.autofill.DirectoryStructure
import app.passwordstore.util.extensions.autofillManager
import app.passwordstore.util.settings.PreferenceKeys
import com.github.androidpasswordstore.autofillparser.BrowserAutofillSupportLevel
Expand All @@ -24,10 +23,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
import de.Maxr1998.modernpreferences.PreferenceScreen
import de.Maxr1998.modernpreferences.helpers.editText
import de.Maxr1998.modernpreferences.helpers.onClick
import de.Maxr1998.modernpreferences.helpers.singleChoice
import de.Maxr1998.modernpreferences.helpers.switch
import de.Maxr1998.modernpreferences.preferences.SwitchPreference
import de.Maxr1998.modernpreferences.preferences.choice.SelectionItem

class AutofillSettings(private val activity: FragmentActivity) : SettingsProvider {

Expand Down Expand Up @@ -101,16 +98,6 @@ class AutofillSettings(private val activity: FragmentActivity) : SettingsProvide
false
}
}
val values =
activity.resources.getStringArray(R.array.oreo_autofill_directory_structure_values)
val titles =
activity.resources.getStringArray(R.array.oreo_autofill_directory_structure_entries)
val items = values.zip(titles).map { SelectionItem(it.first, it.second, null) }
singleChoice(PreferenceKeys.OREO_AUTOFILL_DIRECTORY_STRUCTURE, items) {
initialSelection = DirectoryStructure.DEFAULT.value
dependency = PreferenceKeys.AUTOFILL_ENABLE
titleRes = R.string.oreo_autofill_preference_directory_structure
}
editText(PreferenceKeys.OREO_AUTOFILL_DEFAULT_USERNAME) {
dependency = PreferenceKeys.AUTOFILL_ENABLE
titleRes = R.string.preference_default_username_title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import app.passwordstore.R
import app.passwordstore.util.auth.BiometricAuthenticator
import app.passwordstore.util.auth.BiometricAuthenticator.Result
import app.passwordstore.util.extensions.sharedPrefs
import app.passwordstore.util.settings.DirectoryStructure
import app.passwordstore.util.settings.PreferenceKeys
import de.Maxr1998.modernpreferences.PreferenceScreen
import de.Maxr1998.modernpreferences.helpers.onClick
Expand All @@ -34,6 +35,14 @@ class GeneralSettings(private val activity: FragmentActivity) : SettingsProvider
titleRes = R.string.pref_app_theme_title
}

val values = activity.resources.getStringArray(R.array.directory_structure_values)
val titles = activity.resources.getStringArray(R.array.directory_structure_entries)
val items = values.zip(titles).map { SelectionItem(it.first, it.second, null) }
singleChoice(PreferenceKeys.DIRECTORY_STRUCTURE, items) {
initialSelection = DirectoryStructure.DEFAULT.value
titleRes = R.string.pref_directory_structure
}

val sortValues = activity.resources.getStringArray(R.array.sort_order_values)
val sortOptions = activity.resources.getStringArray(R.array.sort_order_entries)
val sortItems = sortValues.zip(sortOptions).map { SelectionItem(it.first, it.second, null) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,124 +9,15 @@ import app.passwordstore.data.passfile.PasswordEntry
import app.passwordstore.util.extensions.getString
import app.passwordstore.util.extensions.sharedPrefs
import app.passwordstore.util.services.getDefaultUsername
import app.passwordstore.util.settings.DirectoryStructure
import app.passwordstore.util.settings.PreferenceKeys
import com.github.androidpasswordstore.autofillparser.Credentials
import java.io.File
import java.nio.file.Paths

enum class DirectoryStructure(val value: String) {
EncryptedUsername("encrypted_username"),
FileBased("file"),
DirectoryBased("directory");

/**
* Returns the username associated to [file], following the convention of the current
* [DirectoryStructure].
*
* Examples:
* - * --> null (EncryptedUsername)
* - work/example.org/[email protected] --> [email protected] (FileBased)
* - work/example.org/[email protected]/password.gpg --> [email protected] (DirectoryBased)
* - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback)
*/
fun getUsernameFor(file: File): String? =
when (this) {
EncryptedUsername -> null
FileBased -> file.nameWithoutExtension
DirectoryBased -> file.parentFile?.name ?: file.nameWithoutExtension
}

/**
* Returns the origin identifier associated to [file], following the convention of the current
* [DirectoryStructure].
*
* At least one of [DirectoryStructure.getIdentifierFor] and
* [DirectoryStructure.getAccountPartFor] will always return a non-null result.
*
* Examples:
* - work/example.org.gpg --> example.org (EncryptedUsername)
* - work/example.org/[email protected] --> example.org (FileBased)
* - example.org.gpg --> example.org (FileBased, fallback)
* - work/example.org/[email protected]/password.gpg --> example.org (DirectoryBased)
* - Temporary PIN.gpg --> null (DirectoryBased)
*/
fun getIdentifierFor(file: File): String? =
when (this) {
EncryptedUsername -> file.nameWithoutExtension
FileBased -> file.parentFile?.name ?: file.nameWithoutExtension
DirectoryBased -> file.parentFile?.parent
}

/**
* Returns the path components of [file] until right before the component that contains the origin
* identifier according to the current [DirectoryStructure].
*
* Examples:
* - work/example.org.gpg --> work (EncryptedUsername)
* - work/example.org/[email protected] --> work (FileBased)
* - example.org/[email protected] --> null (FileBased)
* - [email protected] --> null (FileBased)
* - work/example.org/[email protected]/password.gpg --> work (DirectoryBased)
* - example.org/[email protected]/password.gpg --> null (DirectoryBased)
*/
fun getPathToIdentifierFor(file: File): String? =
when (this) {
EncryptedUsername -> file.parent
FileBased -> file.parentFile?.parent
DirectoryBased -> file.parentFile?.parentFile?.parent
}

/**
* Returns the path component of [file] following the origin identifier according to the current
* [DirectoryStructure](without file extension).
*
* At least one of [DirectoryStructure.getIdentifierFor] and
* [DirectoryStructure.getAccountPartFor] will always return a non-null result.
*
* Examples:
* - * --> null (EncryptedUsername)
* - work/example.org/[email protected] --> [email protected] (FileBased)
* - example.org.gpg --> null (FileBased, fallback)
* - work/example.org/[email protected]/password.gpg --> [email protected]/password (DirectoryBased)
* - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback)
*/
fun getAccountPartFor(file: File): String? =
when (this) {
EncryptedUsername -> null
FileBased -> file.nameWithoutExtension.takeIf { file.parentFile != null }
DirectoryBased ->
file.parentFile?.let { parentFile -> "${parentFile.name}/${file.nameWithoutExtension}" }
?: file.nameWithoutExtension
}

fun getSaveFolderName(sanitizedIdentifier: String, username: String?) =
when (this) {
EncryptedUsername -> "/"
FileBased -> sanitizedIdentifier
DirectoryBased -> Paths.get(sanitizedIdentifier, username ?: "username").toString()
}

fun getSaveFileName(username: String?, identifier: String) =
when (this) {
EncryptedUsername -> identifier
FileBased -> username
DirectoryBased -> "password"
}

companion object {

val DEFAULT = FileBased

private val reverseMap = entries.associateBy { it.value }

fun fromValue(value: String?) = if (value != null) reverseMap[value] ?: DEFAULT else DEFAULT
}
}

object AutofillPreferences {

fun directoryStructure(context: Context): DirectoryStructure {
val value = context.sharedPrefs.getString(PreferenceKeys.OREO_AUTOFILL_DIRECTORY_STRUCTURE)
val value = context.sharedPrefs.getString(PreferenceKeys.DIRECTORY_STRUCTURE)
return DirectoryStructure.fromValue(value)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
* SPDX-License-Identifier: GPL-3.0-only
*/
package app.passwordstore.util.settings

import java.io.File
import java.nio.file.Paths

enum class DirectoryStructure(val value: String) {
EncryptedUsername("encrypted_username"),
FileBased("file"),
DirectoryBased("directory");

/**
* Returns the username associated to [file], following the convention of the current
* [DirectoryStructure].
*
* Examples:
* - * --> null (EncryptedUsername)
* - work/example.org/[email protected] --> [email protected] (FileBased)
* - work/example.org/[email protected]/password.gpg --> [email protected] (DirectoryBased)
* - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback)
*/
fun getUsernameFor(file: File): String? =
when (this) {
EncryptedUsername -> null
FileBased -> file.nameWithoutExtension
DirectoryBased -> file.parentFile?.name ?: file.nameWithoutExtension
}

/**
* Returns the origin identifier associated to [file], following the convention of the current
* [DirectoryStructure].
*
* At least one of [DirectoryStructure.getIdentifierFor] and
* [DirectoryStructure.getAccountPartFor] will always return a non-null result.
*
* Examples:
* - work/example.org.gpg --> example.org (EncryptedUsername)
* - work/example.org/[email protected] --> example.org (FileBased)
* - example.org.gpg --> example.org (FileBased, fallback)
* - work/example.org/[email protected]/password.gpg --> example.org (DirectoryBased)
* - Temporary PIN.gpg --> null (DirectoryBased)
*/
fun getIdentifierFor(file: File): String? =
when (this) {
EncryptedUsername -> file.nameWithoutExtension
FileBased -> file.parentFile?.name ?: file.nameWithoutExtension
DirectoryBased -> file.parentFile?.parent
}

/**
* Returns the path components of [file] until right before the component that contains the origin
* identifier according to the current [DirectoryStructure].
*
* Examples:
* - work/example.org.gpg --> work (EncryptedUsername)
* - work/example.org/[email protected] --> work (FileBased)
* - example.org/[email protected] --> null (FileBased)
* - [email protected] --> null (FileBased)
* - work/example.org/[email protected]/password.gpg --> work (DirectoryBased)
* - example.org/[email protected]/password.gpg --> null (DirectoryBased)
*/
fun getPathToIdentifierFor(file: File): String? =
when (this) {
EncryptedUsername -> file.parent
FileBased -> file.parentFile?.parent
DirectoryBased -> file.parentFile?.parentFile?.parent
}

/**
* Returns the path component of [file] following the origin identifier according to the current
* [DirectoryStructure](without file extension).
*
* At least one of [DirectoryStructure.getIdentifierFor] and
* [DirectoryStructure.getAccountPartFor] will always return a non-null result.
*
* Examples:
* - * --> null (EncryptedUsername)
* - work/example.org/[email protected] --> [email protected] (FileBased)
* - example.org.gpg --> null (FileBased, fallback)
* - work/example.org/[email protected]/password.gpg --> [email protected]/password (DirectoryBased)
* - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback)
*/
fun getAccountPartFor(file: File): String? =
when (this) {
EncryptedUsername -> null
FileBased -> file.nameWithoutExtension.takeIf { file.parentFile != null }
DirectoryBased ->
file.parentFile?.let { parentFile -> "${parentFile.name}/${file.nameWithoutExtension}" }
?: file.nameWithoutExtension
}

fun getSaveFolderName(sanitizedIdentifier: String, username: String?) =
when (this) {
EncryptedUsername -> "/"
FileBased -> sanitizedIdentifier
DirectoryBased -> Paths.get(sanitizedIdentifier, username ?: "username").toString()
}

fun getSaveFileName(username: String?, identifier: String) =
when (this) {
EncryptedUsername -> identifier
FileBased -> username
DirectoryBased -> "password"
}

companion object {

val DEFAULT = FileBased

private val reverseMap = entries.associateBy { it.value }

fun fromValue(value: String?) = if (value != null) reverseMap[value] ?: DEFAULT else DEFAULT
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ object PreferenceKeys {
const val LENGTH = "length"
const val OREO_AUTOFILL_CUSTOM_PUBLIC_SUFFIXES = "oreo_autofill_custom_public_suffixes"
const val OREO_AUTOFILL_DEFAULT_USERNAME = "oreo_autofill_default_username"
const val OREO_AUTOFILL_DIRECTORY_STRUCTURE = "oreo_autofill_directory_structure"
const val DIRECTORY_STRUCTURE = "oreo_autofill_directory_structure"
const val PREF_KEY_PWGEN_TYPE = "pref_key_pwgen_type"
const val REPOSITORY_INITIALIZED = "repository_initialized"
const val REPO_CHANGED = "repo_changed"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import app.passwordstore.data.password.PasswordItem
import app.passwordstore.data.repo.PasswordRepository
import app.passwordstore.injection.prefs.SettingsPreferences
import app.passwordstore.util.autofill.AutofillPreferences
import app.passwordstore.util.autofill.DirectoryStructure
import app.passwordstore.util.checkMainThread
import app.passwordstore.util.coroutines.DispatcherProvider
import app.passwordstore.util.settings.DirectoryStructure
import app.passwordstore.util.settings.PasswordSortOrder
import app.passwordstore.util.settings.PreferenceKeys
import com.github.androidpasswordstore.sublimefuzzy.Fuzzy
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
<string name="ssh_key_error_dialog_text">Nachricht : \n</string>
<string name="pref_recursive_filter_title">Suche in Unterordnern</string>
<string name="pref_recursive_filter_summary">Findet Passwörter auch in Unterordnern.</string>
<string name="pref_directory_structure">Passwort-Datei-Organisation</string>
<string name="pref_sort_order_title">Passwortsortierung</string>
<string name="pref_folder_first_sort_order">Ordner zuerst</string>
<string name="pref_file_first_sort_order">Dateien zuerst</string>
Expand Down Expand Up @@ -190,7 +191,6 @@
<string name="oreo_autofill_password_fill_support">Passwörter ausfüllen</string>
<string name="oreo_autofill_flaky_fill_support">Passwörter ausfüllen (kann manchmal sein, dass Sie den Browser neu starten müssen)</string>
<string name="oreo_autofill_no_support">Kein Support</string>
<string name="oreo_autofill_preference_directory_structure">Passwort-Datei-Organisation</string>
<string name="oreo_autofill_enable_dialog_description">Password Store kann das Ausfüllen von Anmeldeformularen und sogar das Speichern von Anmeldedaten in Apps oder auf Webseiten übernehmen.</string>
<string name="oreo_autofill_enable_dialog_instructions">Um diese Funktion zu aktivieren, tippen Sie auf OK, um zu Autofill-Einstellungen zu gelangen. Dort wählen Sie \"Password Store\" aus der Liste und bestätigen Sie die Bestätigungsaufforderung mit \"OK\".</string>
<string name="oreo_autofill_enable_dialog_installed_browsers">Autofill-Unterstützung mit installierten Browsern:</string>
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
<string name="ssh_key_error_dialog_text">Message : \n</string>
<string name="pref_recursive_filter_title">Filtrage récursif</string>
<string name="pref_recursive_filter_summary">Cherche le mot de passe dans tous les sous-répertoires du répertoire actuel.</string>
<string name="pref_directory_structure">Organisation des fichiers de mot de passe</string>
<string name="pref_sort_order_title">Ordre de tri des mots de passe</string>
<string name="pref_folder_first_sort_order">Dossiers en premier</string>
<string name="pref_file_first_sort_order">Fichiers en premier</string>
Expand Down Expand Up @@ -194,7 +195,6 @@
<string name="oreo_autofill_password_fill_support">Remplir le mot de passe</string>
<string name="oreo_autofill_flaky_fill_support">Remplir les mots de passe (peut nécessiter un redémarrage du navigateur de temps à autre)</string>
<string name="oreo_autofill_no_support">Pas de support</string>
<string name="oreo_autofill_preference_directory_structure">Organisation des fichiers de mot de passe</string>
<string name="oreo_autofill_enable_dialog_description">Password Store vous permet de remplir des formulaires de connexion ainsi que d\'enregistrer vos identifiants d\'applications ou de sites Web.</string>
<string name="oreo_autofill_enable_dialog_instructions">Pour activer cette fonctionnalité, appuyez sur OK pour aller dans les paramètres de saisie automatique, sélectionnez Password Store dans la liste puis confirmez avec OK.</string>
<string name="oreo_autofill_enable_dialog_installed_browsers">Prise en charge du remplissage automatique avec les navigateurs installés:</string>
Expand Down
Loading

0 comments on commit 0e76ef0

Please sign in to comment.