aboutsummaryrefslogtreecommitdiffstats
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/AndroidManifest.xml23
-rw-r--r--app/src/main/java/app/passwordstore/ui/dialogs/TextInputDialog.kt71
-rw-r--r--app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt176
-rw-r--r--app/src/main/java/app/passwordstore/ui/git/log/GitLogActivity.kt49
-rw-r--r--app/src/main/java/app/passwordstore/ui/git/log/GitLogAdapter.kt65
-rw-r--r--app/src/main/java/app/passwordstore/ui/main/MainActivity.kt8
-rw-r--r--app/src/main/java/app/passwordstore/ui/proxy/ProxySelectorActivity.kt109
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt114
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt120
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/MiscSettings.kt76
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/PGPSettings.kt136
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/PasswordSettings.kt48
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt193
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt129
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsProvider.kt15
-rw-r--r--app/src/main/java/app/passwordstore/ui/setup/SetupGraph.kt2
-rw-r--r--app/src/main/java/app/passwordstore/util/git/GitLogModel.kt60
-rw-r--r--app/src/main/res/layout/activity_git_config.xml113
-rw-r--r--app/src/main/res/layout/activity_git_log.xml22
-rw-r--r--app/src/main/res/layout/activity_preference_recyclerview.xml18
-rw-r--r--app/src/main/res/layout/activity_proxy_selector.xml106
-rw-r--r--app/src/main/res/layout/dialog_text_input.xml25
-rw-r--r--app/src/main/res/layout/git_log_row_layout.xml45
-rw-r--r--app/src/main/res/layout/oreo_autofill_instructions.xml51
-rw-r--r--app/src/main/res/values-de/strings.xml1
-rw-r--r--app/src/main/res/values-fr/strings.xml1
-rw-r--r--app/src/main/res/values-gl/strings.xml1
-rw-r--r--app/src/main/res/values-it/strings.xml2
-rw-r--r--app/src/main/res/values-ko-rKR/strings.xml1
-rw-r--r--app/src/main/res/values-pl-rPL/strings.xml1
-rw-r--r--app/src/main/res/values-pt-rBR/strings.xml1
-rw-r--r--app/src/main/res/values-ru/strings.xml1
-rw-r--r--app/src/main/res/values-zh-rCN/strings.xml1
-rw-r--r--app/src/main/res/values/dimens.xml1
-rw-r--r--app/src/main/res/values/strings.xml2
35 files changed, 4 insertions, 1783 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 546bdde4..677321c7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -34,12 +34,6 @@
tools:targetApi="s">
<activity
- android:name=".ui.proxy.ProxySelectorActivity"
- android:exported="false"
- android:label="@string/activity_proxy_label"
- android:windowSoftInputMode="adjustResize" />
-
- <activity
android:name=".ui.main.LaunchActivity"
android:configChanges="orientation|screenSize"
android:exported="true"
@@ -67,23 +61,6 @@
android:windowSoftInputMode="stateAlwaysHidden"
tools:node="replace" />
- <activity
- android:name=".ui.git.config.GitConfigActivity"
- android:exported="false"
- android:label="@string/title_activity_git_config"
- android:windowSoftInputMode="adjustResize" />
-
- <activity
- android:name=".ui.git.log.GitLogActivity"
- android:exported="false"
- android:label="@string/title_activity_git_log" />
-
- <activity
- android:name=".ui.settings.SettingsActivity"
- android:exported="false"
- android:label="@string/action_settings"
- android:parentActivityName=".ui.main.MainActivity" />
-
<service
android:name=".util.services.ClipboardService"
android:exported="false"
diff --git a/app/src/main/java/app/passwordstore/ui/dialogs/TextInputDialog.kt b/app/src/main/java/app/passwordstore/ui/dialogs/TextInputDialog.kt
deleted file mode 100644
index 58c39968..00000000
--- a/app/src/main/java/app/passwordstore/ui/dialogs/TextInputDialog.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.dialogs
-
-import android.app.Dialog
-import android.content.DialogInterface
-import android.os.Bundle
-import android.view.WindowManager
-import androidx.core.os.bundleOf
-import androidx.fragment.app.DialogFragment
-import androidx.fragment.app.setFragmentResult
-import app.passwordstore.databinding.DialogTextInputBinding
-import app.passwordstore.util.extensions.finish
-import app.passwordstore.util.extensions.unsafeLazy
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-
-/**
- * General purpose [DialogFragment] that can be used to accept a single text input. It provides a
- * configurable title and text input hint through the instantiation helper at
- * [TextInputDialog.newInstance]. Typical usage would look something like this:
- * ```kotlin
- * val dialog = TextInputDialog.newInstance(getString(R.string.dialog_title), getString(R.string.dialog_hint))
- * dialog.show(supportFragmentManager, "text_input_dialog")
- * dialog.setFragmentResultListener(TextInputDialog.REQUEST_KEY) { _, bundle ->
- * doSomething(bundle.getString(TextInputDialog.BUNDLE_KEY_TEXT))
- * }
- * ```
- */
-class TextInputDialog : DialogFragment() {
- private val binding by unsafeLazy { DialogTextInputBinding.inflate(layoutInflater) }
-
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- val builder = MaterialAlertDialogBuilder(requireContext())
- builder.setView(binding.root)
- builder.setTitle(arguments?.getString(BUNDLE_KEY_TITLE))
- arguments?.getString(BUNDLE_KEY_HINT)?.let { hint ->
- binding.textInputLayout.isHintEnabled = true
- binding.textInputLayout.isHintAnimationEnabled = true
- binding.textInputLayout.hint = hint
- }
- builder.setPositiveButton(android.R.string.ok) { dialogInterface, _ ->
- setFragmentResult(REQUEST_KEY, bundleOf(BUNDLE_KEY_TEXT to binding.editText.text.toString()))
- dialogInterface.dismiss()
- }
- val dialog = builder.create()
- dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
- return dialog
- }
-
- override fun onCancel(dialog: DialogInterface) {
- super.onCancel(dialog)
- finish()
- }
-
- companion object {
- const val REQUEST_KEY = "text_input_dialog"
- const val BUNDLE_KEY_TEXT = "text"
- private const val BUNDLE_KEY_TITLE = "title"
- private const val BUNDLE_KEY_HINT = "hint"
-
- fun newInstance(title: String, hint: String? = null): TextInputDialog {
- val args = bundleOf(BUNDLE_KEY_TITLE to title, BUNDLE_KEY_HINT to hint)
- val dialog = TextInputDialog()
- dialog.arguments = args
- return dialog
- }
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt b/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt
deleted file mode 100644
index 695029d4..00000000
--- a/app/src/main/java/app/passwordstore/ui/git/config/GitConfigActivity.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-package app.passwordstore.ui.git.config
-
-import android.os.Bundle
-import android.os.Handler
-import android.os.Looper
-import android.util.Patterns
-import android.view.MenuItem
-import androidx.core.os.postDelayed
-import androidx.fragment.app.setFragmentResultListener
-import androidx.lifecycle.lifecycleScope
-import app.passwordstore.R
-import app.passwordstore.data.repo.PasswordRepository
-import app.passwordstore.databinding.ActivityGitConfigBinding
-import app.passwordstore.ui.dialogs.TextInputDialog
-import app.passwordstore.ui.git.base.BaseGitActivity
-import app.passwordstore.ui.git.log.GitLogActivity
-import app.passwordstore.util.extensions.asLog
-import app.passwordstore.util.extensions.launchActivity
-import app.passwordstore.util.extensions.viewBinding
-import com.github.michaelbull.result.fold
-import com.github.michaelbull.result.getOrElse
-import com.github.michaelbull.result.onFailure
-import com.github.michaelbull.result.runCatching
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.google.android.material.snackbar.Snackbar
-import kotlinx.coroutines.launch
-import logcat.LogPriority.ERROR
-import logcat.logcat
-import org.eclipse.jgit.lib.Constants
-import org.eclipse.jgit.lib.Repository
-import org.eclipse.jgit.lib.RepositoryState
-
-class GitConfigActivity : BaseGitActivity() {
-
- private val binding by viewBinding(ActivityGitConfigBinding::inflate)
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(binding.root)
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
-
- if (gitSettings.authorName.isEmpty()) binding.gitUserName.requestFocus()
- else binding.gitUserName.setText(gitSettings.authorName)
- binding.gitUserEmail.setText(gitSettings.authorEmail)
- setupTools()
- binding.saveButton.setOnClickListener {
- val email = binding.gitUserEmail.text.toString().trim()
- val name = binding.gitUserName.text.toString().trim()
- if (!email.matches(Patterns.EMAIL_ADDRESS.toRegex())) {
- MaterialAlertDialogBuilder(this)
- .setMessage(getString(R.string.invalid_email_dialog_text))
- .setPositiveButton(getString(R.string.dialog_ok), null)
- .show()
- } else {
- gitSettings.authorEmail = email
- gitSettings.authorName = name
- Snackbar.make(
- binding.root,
- getString(R.string.git_server_config_save_success),
- Snackbar.LENGTH_SHORT,
- )
- .show()
- Handler(Looper.getMainLooper()).postDelayed(500) { finish() }
- }
- }
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- return when (item.itemId) {
- android.R.id.home -> {
- onBackPressedDispatcher.onBackPressed()
- true
- }
- else -> super.onOptionsItemSelected(item)
- }
- }
-
- /** Sets up the UI components of the tools section. */
- private fun setupTools() {
- val repo = PasswordRepository.repository
- if (repo != null) {
- binding.gitHeadStatus.text = headStatusMsg(repo)
- // enable the abort button only if we're rebasing or merging
- val needsAbort =
- repo.repositoryState.isRebasing || repo.repositoryState == RepositoryState.MERGING
- binding.gitAbortRebase.isEnabled = needsAbort
- binding.gitAbortRebase.alpha = if (needsAbort) 1.0f else 0.5f
- }
- binding.gitLog.setOnClickListener {
- runCatching { launchActivity(GitLogActivity::class.java) }
- .onFailure { ex -> logcat(ERROR) { ex.asLog("Failed to start GitLogActivity") } }
- }
- binding.gitAbortRebase.setOnClickListener { abortRebase() }
- binding.gitResetToRemote.setOnClickListener { resetToRemote() }
- binding.gitGc.setOnClickListener {
- lifecycleScope.launch {
- launchGitOperation(GitOp.GC)
- .fold(
- success = ::finishOnSuccessHandler,
- failure = { err -> promptOnErrorHandler(err) { finish() } },
- )
- }
- }
- }
-
- private fun resetToRemote() {
- val dialog =
- TextInputDialog.newInstance(getString(R.string.git_utils_reset_remote_branch_title))
- dialog.show(supportFragmentManager, "BRANCH_INPUT_DIALOG")
- dialog.setFragmentResultListener(TextInputDialog.REQUEST_KEY) { _, bundle ->
- val result = bundle.getString(TextInputDialog.BUNDLE_KEY_TEXT)
- if (!result.isNullOrEmpty()) {
- remoteBranch = result
- lifecycleScope.launch {
- launchGitOperation(GitOp.RESET)
- .fold(
- success = ::finishOnSuccessHandler,
- failure = { err -> promptOnErrorHandler(err) { finish() } },
- )
- }
- }
- }
- }
-
- private fun abortRebase() {
- lifecycleScope.launch {
- launchGitOperation(GitOp.BREAK_OUT_OF_DETACHED)
- .fold(
- success = {
- val branch = PasswordRepository.getCurrentBranch()
- MaterialAlertDialogBuilder(this@GitConfigActivity).run {
- setTitle(resources.getString(R.string.git_abort_and_push_title))
- setMessage(
- resources.getString(
- R.string.git_break_out_of_detached_success,
- branch,
- "conflicting-$branch-...",
- )
- )
- setOnDismissListener { finish() }
- setPositiveButton(resources.getString(R.string.dialog_ok)) { _, _ -> }
- show()
- }
- },
- failure = { err -> promptOnErrorHandler(err) { finish() } },
- )
- }
- }
-
- /**
- * Returns a user-friendly message about the current state of HEAD.
- *
- * The state is recognized to be either pointing to a branch or detached.
- */
- private fun headStatusMsg(repo: Repository): String {
- return runCatching {
- val headRef = repo.findRef(Constants.HEAD)
- if (headRef.isSymbolic) {
- val branchName = headRef.target.name
- val shortBranchName = Repository.shortenRefName(branchName)
- getString(R.string.git_head_on_branch, shortBranchName)
- } else {
- val commitHash = headRef.objectId.abbreviate(8).name()
- getString(R.string.git_head_detached, commitHash)
- }
- }
- .getOrElse { ex ->
- logcat(ERROR) { "Error getting HEAD reference\n${ex}" }
- getString(R.string.git_head_missing)
- }
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/git/log/GitLogActivity.kt b/app/src/main/java/app/passwordstore/ui/git/log/GitLogActivity.kt
deleted file mode 100644
index a72881d1..00000000
--- a/app/src/main/java/app/passwordstore/ui/git/log/GitLogActivity.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.git.log
-
-import android.os.Bundle
-import android.view.MenuItem
-import androidx.recyclerview.widget.DividerItemDecoration
-import androidx.recyclerview.widget.LinearLayoutManager
-import app.passwordstore.databinding.ActivityGitLogBinding
-import app.passwordstore.ui.git.base.BaseGitActivity
-import app.passwordstore.util.extensions.viewBinding
-
-/**
- * Displays the repository's git commits in git-log fashion.
- *
- * It provides basic information about each commit by way of a non-interactive RecyclerView.
- */
-class GitLogActivity : BaseGitActivity() {
-
- private val binding by viewBinding(ActivityGitLogBinding::inflate)
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(binding.root)
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
- createRecyclerView()
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- return when (item.itemId) {
- android.R.id.home -> {
- finish()
- true
- }
- else -> super.onOptionsItemSelected(item)
- }
- }
-
- private fun createRecyclerView() {
- binding.gitLogRecyclerView.apply {
- setHasFixedSize(true)
- addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL))
- adapter = GitLogAdapter()
- }
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/git/log/GitLogAdapter.kt b/app/src/main/java/app/passwordstore/ui/git/log/GitLogAdapter.kt
deleted file mode 100644
index 95186188..00000000
--- a/app/src/main/java/app/passwordstore/ui/git/log/GitLogAdapter.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.git.log
-
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import androidx.recyclerview.widget.RecyclerView
-import app.passwordstore.databinding.GitLogRowLayoutBinding
-import app.passwordstore.util.git.GitCommit
-import app.passwordstore.util.git.GitLogModel
-import java.time.Instant
-import java.time.ZoneId
-import java.time.format.DateTimeFormatter
-import java.time.format.FormatStyle
-import java.util.Locale
-import logcat.LogPriority.ERROR
-import logcat.logcat
-
-private fun shortHash(hash: String): String {
- return hash.substring(0 until 8)
-}
-
-private fun stringFrom(date: Instant): String {
- return DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
- .withLocale(Locale.getDefault())
- .withZone(ZoneId.systemDefault())
- .format(date)
-}
-
-/** @see GitLogActivity */
-class GitLogAdapter : RecyclerView.Adapter<GitLogAdapter.ViewHolder>() {
-
- private val model = GitLogModel()
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
- val inflater = LayoutInflater.from(parent.context)
- val binding = GitLogRowLayoutBinding.inflate(inflater, parent, false)
- return ViewHolder(binding)
- }
-
- override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
- val commit = model.get(position)
- if (commit == null) {
- logcat(ERROR) { "There is no git commit for view holder at position $position." }
- return
- }
- viewHolder.bind(commit)
- }
-
- override fun getItemCount() = model.size
-
- class ViewHolder(private val binding: GitLogRowLayoutBinding) :
- RecyclerView.ViewHolder(binding.root) {
-
- fun bind(commit: GitCommit) =
- with(binding) {
- gitLogRowMessage.text = commit.shortMessage
- gitLogRowHash.text = shortHash(commit.hash)
- gitLogRowTime.text = stringFrom(commit.time)
- }
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/main/MainActivity.kt b/app/src/main/java/app/passwordstore/ui/main/MainActivity.kt
index 4d618cca..75062f6b 100644
--- a/app/src/main/java/app/passwordstore/ui/main/MainActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/main/MainActivity.kt
@@ -258,13 +258,13 @@ class MainActivity : BaseGitActivity() {
private const val EXTRA_SETUP = "SETUP"
/**
- * Opens one setup screen in an instance of its own, for callers outside the graph (legacy
- * Settings, autofill, git operations) and for those waiting for a result (the entry view's
+ * Opens one setup screen in an instance of its own, for callers outside the graph (autofill,
+ * the git operations' "No SSH key" dialog) and for those waiting for a result (the entry view's
* missing key). Leaving that screen finishes the instance; the PGP keys screen sets RESULT_OK
* once a key was imported.
*/
- // ponytail: a second instance instead of in-graph navigation, until steps 6 and 7 move
- // Settings and autofill into the graph.
+ // ponytail: a second instance instead of in-graph navigation, until step 7 moves autofill
+ // into the graph and the git operations' dialogs become Compose dialogs.
fun setupIntent(context: Context, start: SetupStart): Intent =
Intent(context, MainActivity::class.java).putExtra(EXTRA_SETUP, start.name)
}
diff --git a/app/src/main/java/app/passwordstore/ui/proxy/ProxySelectorActivity.kt b/app/src/main/java/app/passwordstore/ui/proxy/ProxySelectorActivity.kt
deleted file mode 100644
index cb5fbf40..00000000
--- a/app/src/main/java/app/passwordstore/ui/proxy/ProxySelectorActivity.kt
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.proxy
-
-import android.content.SharedPreferences
-import android.net.InetAddresses
-import android.os.Build
-import android.os.Bundle
-import android.os.Handler
-import android.os.Looper
-import android.util.Patterns
-import android.view.MenuItem
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.content.edit
-import androidx.core.os.postDelayed
-import androidx.core.widget.doOnTextChanged
-import app.passwordstore.R
-import app.passwordstore.databinding.ActivityProxySelectorBinding
-import app.passwordstore.injection.prefs.ProxyPreferences
-import app.passwordstore.util.extensions.getString
-import app.passwordstore.util.extensions.viewBinding
-import app.passwordstore.util.proxy.ProxyUtils
-import app.passwordstore.util.settings.GitSettings
-import app.passwordstore.util.settings.PreferenceKeys
-import dagger.hilt.android.AndroidEntryPoint
-import javax.inject.Inject
-
-@AndroidEntryPoint
-class ProxySelectorActivity : AppCompatActivity() {
-
- @Inject lateinit var gitSettings: GitSettings
- @ProxyPreferences @Inject lateinit var proxyPrefs: SharedPreferences
- @Inject lateinit var proxyUtils: ProxyUtils
- private val binding by viewBinding(ActivityProxySelectorBinding::inflate)
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(binding.root)
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
- with(binding) {
- proxyHost.setText(proxyPrefs.getString(PreferenceKeys.PROXY_HOST))
- proxyUser.setText(proxyPrefs.getString(PreferenceKeys.PROXY_USERNAME))
- proxyPrefs
- .getInt(PreferenceKeys.PROXY_PORT, -1)
- .takeIf { it != -1 }
- ?.let { proxyPort.setText("$it") }
- proxyPassword.setText(proxyPrefs.getString(PreferenceKeys.PROXY_PASSWORD))
- save.setOnClickListener { saveSettings() }
- proxyHost.doOnTextChanged { text, _, _, _ ->
- if (text != null) {
- proxyHost.error =
- if (isNumericAddress(text) || text.matches(WEB_ADDRESS_REGEX)) {
- null
- } else {
- getString(R.string.invalid_proxy_url)
- }
- }
- }
- }
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- when (item.itemId) {
- android.R.id.home -> {
- onBackPressedDispatcher.onBackPressed()
- }
- else -> return super.onOptionsItemSelected(item)
- }
- return true
- }
-
- private fun isNumericAddress(text: CharSequence): Boolean {
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- InetAddresses.isNumericAddress(text as String)
- } else {
- @Suppress("DEPRECATION") Patterns.IP_ADDRESS.matcher(text).matches()
- }
- }
-
- private fun saveSettings() {
- proxyPrefs.edit {
- binding.proxyHost.text
- ?.toString()
- ?.takeIf { it.isNotEmpty() }
- .let { gitSettings.proxyHost = it }
- binding.proxyUser.text
- ?.toString()
- ?.takeIf { it.isNotEmpty() }
- .let { gitSettings.proxyUsername = it }
- binding.proxyPort.text
- ?.toString()
- ?.takeIf { it.isNotEmpty() }
- ?.let { gitSettings.proxyPort = it.toInt() }
- binding.proxyPassword.text
- ?.toString()
- ?.takeIf { it.isNotEmpty() }
- .let { gitSettings.proxyPassword = it }
- }
- proxyUtils.setDefaultProxy()
- Handler(Looper.getMainLooper()).postDelayed(500) { finish() }
- }
-
- private companion object {
- private val WEB_ADDRESS_REGEX = Patterns.WEB_URL.toRegex()
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt
deleted file mode 100644
index afb2a691..00000000
--- a/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.settings
-
-import android.annotation.SuppressLint
-import android.content.Intent
-import android.provider.Settings
-import androidx.appcompat.widget.AppCompatTextView
-import androidx.core.net.toUri
-import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleEventObserver
-import app.passwordstore.BuildConfig
-import app.passwordstore.R
-import app.passwordstore.util.extensions.autofillManager
-import app.passwordstore.util.settings.PreferenceKeys
-import com.github.androidpasswordstore.autofillparser.BrowserAutofillSupportLevel
-import com.github.androidpasswordstore.autofillparser.getInstalledBrowsersWithAutofillSupportLevel
-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.switch
-import de.Maxr1998.modernpreferences.preferences.SwitchPreference
-
-class AutofillSettings(private val activity: FragmentActivity) : SettingsProvider {
-
- private val isAutofillServiceEnabled: Boolean
- get() {
- return activity.autofillManager?.hasEnabledAutofillServices() == true
- }
-
- private fun showAutofillDialog(pref: SwitchPreference) {
- val observer = LifecycleEventObserver { _, event ->
- when (event) {
- Lifecycle.Event.ON_RESUME -> {
- pref.checked = isAutofillServiceEnabled
- }
- else -> {}
- }
- }
- MaterialAlertDialogBuilder(activity).run {
- setTitle(R.string.pref_autofill_enable_title)
- @SuppressLint("InflateParams")
- val layout = activity.layoutInflater.inflate(R.layout.oreo_autofill_instructions, null)
- val supportedBrowsersTextView = layout.findViewById<AppCompatTextView>(R.id.supportedBrowsers)
- supportedBrowsersTextView.text =
- getInstalledBrowsersWithAutofillSupportLevel(context).joinToString(separator = "\n") {
- val appLabel = it.first
- val supportDescription =
- when (it.second) {
- BrowserAutofillSupportLevel.None ->
- activity.getString(R.string.oreo_autofill_no_support)
- BrowserAutofillSupportLevel.FlakyFill ->
- activity.getString(R.string.oreo_autofill_flaky_fill_support)
- BrowserAutofillSupportLevel.PasswordFill ->
- activity.getString(R.string.oreo_autofill_password_fill_support)
- BrowserAutofillSupportLevel.PasswordFillAndSaveIfNoAccessibility ->
- activity.getString(
- R.string.oreo_autofill_password_fill_and_conditional_save_support
- )
- BrowserAutofillSupportLevel.GeneralFill ->
- activity.getString(R.string.oreo_autofill_general_fill_support)
- BrowserAutofillSupportLevel.GeneralFillAndSave ->
- activity.getString(R.string.oreo_autofill_general_fill_and_save_support)
- }
- "$appLabel: $supportDescription"
- }
- setView(layout)
- setPositiveButton(R.string.dialog_ok) { _, _ ->
- val intent =
- Intent(Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE).apply {
- data = "package:${BuildConfig.APPLICATION_ID}".toUri()
- }
- activity.startActivity(intent)
- }
- setNegativeButton(R.string.dialog_cancel, null)
- setOnDismissListener { pref.checked = isAutofillServiceEnabled }
- activity.lifecycle.addObserver(observer)
- show()
- }
- }
-
- override fun provideSettings(builder: PreferenceScreen.Builder) {
- builder.apply {
- switch(PreferenceKeys.AUTOFILL_ENABLE) {
- titleRes = R.string.pref_autofill_enable_title
- defaultValue = isAutofillServiceEnabled
- onClick {
- if (isAutofillServiceEnabled) {
- activity.autofillManager?.disableAutofillServices()
- } else {
- showAutofillDialog(this)
- }
- false
- }
- }
- editText(PreferenceKeys.OREO_AUTOFILL_DEFAULT_USERNAME) {
- dependency = PreferenceKeys.AUTOFILL_ENABLE
- titleRes = R.string.preference_default_username_title
- summaryProvider = { activity.getString(R.string.preference_default_username_summary) }
- }
- editText(PreferenceKeys.OREO_AUTOFILL_CUSTOM_PUBLIC_SUFFIXES) {
- dependency = PreferenceKeys.AUTOFILL_ENABLE
- titleRes = R.string.preference_custom_public_suffixes_title
- summaryProvider = { activity.getString(R.string.preference_custom_public_suffixes_summary) }
- textInputHintRes = R.string.preference_custom_public_suffixes_hint
- }
- }
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt
deleted file mode 100644
index e3594269..00000000
--- a/app/src/main/java/app/passwordstore/ui/settings/GeneralSettings.kt
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.settings
-
-import android.content.pm.ShortcutManager
-import android.os.Build
-import androidx.core.content.edit
-import androidx.core.content.getSystemService
-import androidx.fragment.app.FragmentActivity
-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
-import de.Maxr1998.modernpreferences.helpers.singleChoice
-import de.Maxr1998.modernpreferences.helpers.switch
-import de.Maxr1998.modernpreferences.preferences.choice.SelectionItem
-
-class GeneralSettings(private val activity: FragmentActivity) : SettingsProvider {
-
- override fun provideSettings(builder: PreferenceScreen.Builder) {
- builder.apply {
- val themeValues = activity.resources.getStringArray(R.array.app_theme_values)
- val themeOptions = activity.resources.getStringArray(R.array.app_theme_options)
- val themeItems =
- themeValues.zip(themeOptions).map { SelectionItem(it.first, it.second, null) }
- singleChoice(PreferenceKeys.APP_THEME, themeItems) {
- initialSelection = activity.resources.getString(R.string.app_theme_def)
- 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) }
- singleChoice(PreferenceKeys.SORT_ORDER, sortItems) {
- initialSelection = sortValues[0]
- titleRes = R.string.pref_sort_order_title
- }
-
- switch(PreferenceKeys.DISABLE_SYNC_ACTION) {
- titleRes = R.string.pref_disable_sync_on_pull_title
- summaryRes = R.string.pref_disable_sync_on_pull_summary
- defaultValue = false
- }
-
- switch(PreferenceKeys.FILTER_RECURSIVELY) {
- titleRes = R.string.pref_recursive_filter_title
- summaryRes = R.string.pref_recursive_filter_summary
- defaultValue = true
- }
-
- switch(PreferenceKeys.SEARCH_ON_START) {
- titleRes = R.string.pref_search_on_start_title
- summaryRes = R.string.pref_search_on_start_summary
- defaultValue = false
- }
-
- switch(PreferenceKeys.SHOW_HIDDEN_CONTENTS) {
- titleRes = R.string.pref_show_hidden_title
- summaryRes = R.string.pref_show_hidden_summary
- defaultValue = false
- }
-
- // See https://github.com/android-password-store/Android-Password-Store/issues/2802
- val disableAuth = Build.VERSION.SDK_INT == Build.VERSION_CODES.UPSIDE_DOWN_CAKE
- val canAuthenticate = BiometricAuthenticator.canAuthenticate(activity)
- switch(PreferenceKeys.BIOMETRIC_AUTH_2) {
- titleRes = R.string.pref_biometric_auth_title
- defaultValue = false
- enabled = !disableAuth
- summaryRes =
- if (disableAuth) R.string.pref_biometric_auth_summary_disabled_platform
- else if (canAuthenticate) R.string.pref_biometric_auth_summary
- else R.string.pref_biometric_auth_summary_error
- onClick {
- enabled = false
- val isChecked = checked
- activity.sharedPrefs.edit {
- BiometricAuthenticator.authenticate(activity) { result ->
- when (result) {
- is Result.Success -> {
- // Apply the changes
- putBoolean(PreferenceKeys.BIOMETRIC_AUTH_2, checked)
- enabled = true
- }
- is Result.Retry -> {}
- else -> {
- // If any error occurs, revert back to the previous
- // state. This
- // catch-all clause includes the cancellation case.
- putBoolean(PreferenceKeys.BIOMETRIC_AUTH_2, !checked)
- checked = !isChecked
- enabled = true
- }
- }
- }
- }
- activity.getSystemService<ShortcutManager>()?.apply {
- removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList())
- }
- false
- }
- }
- }
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/MiscSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/MiscSettings.kt
deleted file mode 100644
index 9a5d1e3b..00000000
--- a/app/src/main/java/app/passwordstore/ui/settings/MiscSettings.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.settings
-
-import android.content.Context
-import android.content.Intent
-import android.net.Uri
-import androidx.activity.result.contract.ActivityResultContracts
-import androidx.documentfile.provider.DocumentFile
-import androidx.fragment.app.FragmentActivity
-import app.passwordstore.BuildConfig
-import app.passwordstore.R
-import app.passwordstore.util.services.PasswordExportService
-import app.passwordstore.util.settings.PreferenceKeys
-import de.Maxr1998.modernpreferences.PreferenceScreen
-import de.Maxr1998.modernpreferences.helpers.onClick
-import de.Maxr1998.modernpreferences.helpers.pref
-import de.Maxr1998.modernpreferences.helpers.switch
-
-class MiscSettings(activity: FragmentActivity) : SettingsProvider {
-
- private val storeExportAction =
- activity.registerForActivityResult(
- object : ActivityResultContracts.OpenDocumentTree() {
- override fun createIntent(context: Context, input: Uri?): Intent {
- return super.createIntent(context, input).apply {
- flags =
- Intent.FLAG_GRANT_READ_URI_PERMISSION or
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION or
- Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
- Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
- }
- }
- }
- ) { uri: Uri? ->
- if (uri == null) return@registerForActivityResult
- val targetDirectory = DocumentFile.fromTreeUri(activity.applicationContext, uri)
-
- if (targetDirectory != null) {
- val service =
- Intent(activity.applicationContext, PasswordExportService::class.java).apply {
- action = PasswordExportService.ACTION_EXPORT_PASSWORD
- putExtra("uri", uri)
- }
-
- activity.startForegroundService(service)
- }
- }
-
- override fun provideSettings(builder: PreferenceScreen.Builder) {
- builder.apply {
- pref(PreferenceKeys.EXPORT_PASSWORDS) {
- titleRes = R.string.prefs_export_passwords_title
- summaryRes = R.string.prefs_export_passwords_summary
- onClick {
- storeExportAction.launch(null)
- true
- }
- }
- switch(PreferenceKeys.CLEAR_CLIPBOARD_HISTORY) {
- defaultValue = false
- titleRes = R.string.pref_clear_clipboard_title
- summaryRes = R.string.pref_clear_clipboard_summary
- }
- switch(PreferenceKeys.ENABLE_DEBUG_LOGGING) {
- defaultValue = false
- titleRes = R.string.pref_debug_logging_title
- summaryRes = R.string.pref_debug_logging_summary
- visible = !BuildConfig.DEBUG
- }
- }
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/PGPSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/PGPSettings.kt
deleted file mode 100644
index 46e62faa..00000000
--- a/app/src/main/java/app/passwordstore/ui/settings/PGPSettings.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.settings
-
-import androidx.core.content.edit
-import androidx.fragment.app.FragmentActivity
-import androidx.lifecycle.lifecycleScope
-import app.passwordstore.R
-import app.passwordstore.data.crypto.PGPPassphraseCache
-import app.passwordstore.ui.main.MainActivity
-import app.passwordstore.ui.setup.SetupStart
-import app.passwordstore.util.auth.BiometricAuthenticator
-import app.passwordstore.util.extensions.sharedPrefs
-import app.passwordstore.util.features.Feature
-import app.passwordstore.util.settings.PreferenceKeys
-import de.Maxr1998.modernpreferences.PreferenceScreen
-import de.Maxr1998.modernpreferences.helpers.onClick
-import de.Maxr1998.modernpreferences.helpers.pref
-import de.Maxr1998.modernpreferences.helpers.switch
-import kotlinx.coroutines.launch
-
-class PGPSettings(
- private val activity: FragmentActivity,
- private val passphraseCache: PGPPassphraseCache,
-) : SettingsProvider {
-
- override fun provideSettings(builder: PreferenceScreen.Builder) {
- builder.apply {
- pref("_") {
- titleRes = R.string.pref_pgp_key_manager_title
- persistent = false
- onClick {
- activity.startActivity(MainActivity.setupIntent(activity, SetupStart.PgpKeys))
- false
- }
- }
- switch(PreferenceKeys.ASCII_ARMOR) {
- titleRes = R.string.pref_pgp_ascii_armor_title
- persistent = true
- }
- switch(Feature.EnablePGPPassphraseCache.configKey) {
- enabled = BiometricAuthenticator.canAuthenticate(activity)
- titleRes = R.string.pref_passphrase_cache_title
- summaryRes = R.string.pref_passphrase_cache_summary
- defaultValue = false
- onClick {
- if (BiometricAuthenticator.canAuthenticate(activity)) {
- val promptTitle =
- if (checked) R.string.pref_passphrase_cache_authenticate_enable
- else R.string.pref_passphrase_cache_authenticate_disable
-
- BiometricAuthenticator.authenticate(activity, promptTitle) { result ->
- when (result) {
- is BiometricAuthenticator.Result.Success -> {
- /* Any successful change of this setting clears the passphrase
- * cache for safety */
- activity.lifecycleScope.launch {
- passphraseCache.clearAllCachedPassphrases(activity)
- }
- activity.sharedPrefs.edit {
- putBoolean(Feature.EnablePGPPassphraseCache.configKey, checked)
- if (!checked) remove(PreferenceKeys.CLEAR_PASSPHRASE_CACHE)
- }
- }
- is BiometricAuthenticator.Result.Retry -> {}
- else -> {
- /* revert back to previous state in case of error or cancellation */
- checked = !checked
- activity.sharedPrefs.edit {
- putBoolean(Feature.EnablePGPPassphraseCache.configKey, checked)
- }
- }
- }
- }
- } else {
- /* we may get here if device lock has been disabled while PGP settings
- * screen was left open */
- checked = false
- enabled = false
- activity.sharedPrefs.edit {
- putBoolean(Feature.EnablePGPPassphraseCache.configKey, false)
- }
- }
- false
- }
- }
- switch(PreferenceKeys.CLEAR_PASSPHRASE_CACHE) {
- dependency = Feature.EnablePGPPassphraseCache.configKey
- titleRes = R.string.pref_passphrase_cache_auto_clear_title
- summaryRes = R.string.pref_passphrase_cache_auto_clear_summary
- defaultValue = true
- /* Clear the cache once when unchecking; this is to prevent a malicious user (someone
- * knowing the screen-lock pin, but not knowing the PGP passphrase) from bypassing cache
- * clearing via the settings. Disabling it requires authentication, and cache clearing
- * stays enabled in case of any authentication failure. */
- onClick {
- if (!checked) {
- if (
- BiometricAuthenticator.canAuthenticate(activity) &&
- activity.sharedPrefs.getBoolean(Feature.EnablePGPPassphraseCache.configKey, false)
- ) {
- BiometricAuthenticator.authenticate(
- activity,
- R.string.pref_passphrase_cache_auto_clear_authenticate_disable,
- ) { result ->
- when (result) {
- is BiometricAuthenticator.Result.Success -> {
- activity.sharedPrefs.edit {
- putBoolean(PreferenceKeys.CLEAR_PASSPHRASE_CACHE, false)
- }
- activity.lifecycleScope.launch {
- passphraseCache.clearAllCachedPassphrases(activity)
- }
- }
- is BiometricAuthenticator.Result.Retry -> {}
- else -> {
- activity.sharedPrefs.edit { remove(PreferenceKeys.CLEAR_PASSPHRASE_CACHE) }
- checked = true
- }
- }
- }
- } else {
- activity.sharedPrefs.edit { remove(PreferenceKeys.CLEAR_PASSPHRASE_CACHE) }
- checked = true
- enabled = false
- }
- }
- false
- }
- }
- }
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/PasswordSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/PasswordSettings.kt
deleted file mode 100644
index 9fe4cd42..00000000
--- a/app/src/main/java/app/passwordstore/ui/settings/PasswordSettings.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.settings
-
-import android.text.InputType
-import androidx.fragment.app.FragmentActivity
-import app.passwordstore.R
-import app.passwordstore.util.settings.PreferenceKeys
-import de.Maxr1998.modernpreferences.PreferenceScreen
-import de.Maxr1998.modernpreferences.helpers.editText
-import de.Maxr1998.modernpreferences.helpers.singleChoice
-import de.Maxr1998.modernpreferences.helpers.switch
-import de.Maxr1998.modernpreferences.preferences.choice.SelectionItem
-
-class PasswordSettings(private val activity: FragmentActivity) : SettingsProvider {
-
- override fun provideSettings(builder: PreferenceScreen.Builder) {
- builder.apply {
- val values = activity.resources.getStringArray(R.array.pwgen_provider_values)
- val labels = activity.resources.getStringArray(R.array.pwgen_provider_labels)
- val items = values.zip(labels).map { SelectionItem(it.first, it.second, null) }
- singleChoice(PreferenceKeys.PREF_KEY_PWGEN_TYPE, items) {
- initialSelection = "diceware"
- titleRes = R.string.pref_password_generator_type_title
- }
- editText(PreferenceKeys.GENERAL_SHOW_TIME) {
- titleRes = R.string.pref_clipboard_timeout_title
- summaryProvider = { timeout ->
- activity.getString(R.string.pref_clipboard_timeout_summary, timeout ?: "45")
- }
- textInputType = InputType.TYPE_CLASS_NUMBER
- }
- switch(PreferenceKeys.SHOW_PASSWORD) {
- titleRes = R.string.show_password_pref_title
- summaryRes = R.string.show_password_pref_summary
- defaultValue = true
- }
- switch(PreferenceKeys.COPY_ON_DECRYPT) {
- titleRes = R.string.pref_copy_title
- summaryRes = R.string.pref_copy_summary
- defaultValue = false
- }
- }
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt b/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt
deleted file mode 100644
index 23dd2829..00000000
--- a/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.settings
-
-import android.content.SharedPreferences
-import android.content.pm.ShortcutManager
-import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
-import androidx.core.content.edit
-import androidx.core.content.getSystemService
-import androidx.fragment.app.FragmentActivity
-import app.passwordstore.R
-import app.passwordstore.data.repo.PasswordRepository
-import app.passwordstore.injection.prefs.GitPreferences
-import app.passwordstore.ui.git.config.GitConfigActivity
-import app.passwordstore.ui.main.MainActivity
-import app.passwordstore.ui.proxy.ProxySelectorActivity
-import app.passwordstore.ui.setup.SetupStart
-import app.passwordstore.util.extensions.getString
-import app.passwordstore.util.extensions.launchActivity
-import app.passwordstore.util.extensions.sharedPrefs
-import app.passwordstore.util.extensions.snackbar
-import app.passwordstore.util.extensions.unsafeLazy
-import app.passwordstore.util.git.sshj.SshKey
-import app.passwordstore.util.settings.GitSettings
-import app.passwordstore.util.settings.PreferenceKeys
-import com.github.michaelbull.result.onFailure
-import com.github.michaelbull.result.runCatching
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.EntryPoint
-import dagger.hilt.InstallIn
-import dagger.hilt.android.EntryPointAccessors
-import dagger.hilt.components.SingletonComponent
-import de.Maxr1998.modernpreferences.Preference
-import de.Maxr1998.modernpreferences.PreferenceScreen
-import de.Maxr1998.modernpreferences.helpers.onClick
-import de.Maxr1998.modernpreferences.helpers.pref
-import de.Maxr1998.modernpreferences.helpers.switch
-
-class RepositorySettings(private val activity: FragmentActivity) : SettingsProvider {
-
- private val generateSshKey =
- activity.registerForActivityResult(StartActivityForResult()) {
- showSshKeyPref?.visible = SshKey.canShowSshPublicKey
- }
-
- private val hiltEntryPoint by unsafeLazy {
- EntryPointAccessors.fromApplication(
- activity.applicationContext,
- RepositorySettingsEntryPoint::class.java,
- )
- }
-
- private var showSshKeyPref: Preference? = null
-
- override fun provideSettings(builder: PreferenceScreen.Builder) {
- val encryptedPreferences = hiltEntryPoint.encryptedPreferences()
- val gitSettings = hiltEntryPoint.gitSettings()
-
- builder.apply {
- switch(PreferenceKeys.REBASE_ON_PULL) {
- titleRes = R.string.pref_rebase_on_pull_title
- summaryRes = R.string.pref_rebase_on_pull_summary
- summaryOnRes = R.string.pref_rebase_on_pull_summary_on
- defaultValue = true
- }
- pref(PreferenceKeys.GIT_SERVER_INFO) {
- titleRes = R.string.pref_edit_git_server_settings
- visible = PasswordRepository.isGitRepo()
- onClick {
- activity.startActivity(MainActivity.setupIntent(activity, SetupStart.GitServer))
- true
- }
- }
- pref(PreferenceKeys.PROXY_SETTINGS) {
- titleRes = R.string.pref_edit_proxy_settings
- visible = gitSettings.url?.startsWith("https") == true && PasswordRepository.isGitRepo()
- onClick {
- activity.launchActivity(ProxySelectorActivity::class.java)
- true
- }
- }
- pref(PreferenceKeys.GIT_CONFIG) {
- titleRes = R.string.pref_edit_git_config
- visible = PasswordRepository.isGitRepo()
- onClick {
- activity.launchActivity(GitConfigActivity::class.java)
- true
- }
- }
- pref(PreferenceKeys.SSH_KEY) {
- titleRes = R.string.pref_import_ssh_key_title
- visible = PasswordRepository.isGitRepo()
- onClick {
- generateSshKey.launch(MainActivity.setupIntent(activity, SetupStart.Ssh))
- true
- }
- }
- pref(PreferenceKeys.SSH_KEYGEN) {
- titleRes = R.string.pref_ssh_keygen_title
- onClick {
- generateSshKey.launch(MainActivity.setupIntent(activity, SetupStart.SshGenerate))
- true
- }
- }
- showSshKeyPref =
- pref(PreferenceKeys.SSH_SEE_KEY) {
- titleRes = R.string.pref_ssh_see_key_title
- visible = PasswordRepository.isGitRepo() && SshKey.canShowSshPublicKey
- onClick {
- generateSshKey.launch(MainActivity.setupIntent(activity, SetupStart.Ssh))
- true
- }
- }
- pref(PreferenceKeys.CLEAR_SAVED_PASS) {
- fun Preference.updatePref() {
- val sshPass = encryptedPreferences.getString(PreferenceKeys.SSH_KEY_LOCAL_PASSPHRASE)
- val httpsPass = encryptedPreferences.getString(PreferenceKeys.HTTPS_PASSWORD)
- if (sshPass == null && httpsPass == null) {
- visible = false
- return
- }
- titleRes =
- when {
- httpsPass != null -> R.string.clear_saved_passphrase_https
- else -> R.string.clear_saved_passphrase_ssh
- }
- visible = true
- requestRebind()
- }
- onClick {
- updatePref()
- true
- }
- updatePref()
- }
- pref(PreferenceKeys.SSH_OPENKEYSTORE_CLEAR_KEY_ID) {
- titleRes = R.string.pref_title_openkeystore_clear_keyid
- visible =
- activity.sharedPrefs.getString(PreferenceKeys.SSH_OPENKEYSTORE_KEYID)?.isNotEmpty()
- ?: false
- onClick {
- activity.sharedPrefs.edit { putString(PreferenceKeys.SSH_OPENKEYSTORE_KEYID, null) }
- visible = false
- true
- }
- }
- pref(PreferenceKeys.GIT_DELETE_REPO) {
- titleRes = R.string.pref_git_delete_repo_title
- summaryRes = R.string.pref_git_delete_repo_summary
- onClick {
- val repoDir = PasswordRepository.getRepositoryDirectory()
- MaterialAlertDialogBuilder(activity)
- .setTitle(R.string.pref_dialog_delete_title)
- .setMessage(activity.getString(R.string.dialog_delete_msg, repoDir))
- .setCancelable(false)
- .setPositiveButton(R.string.dialog_delete) { dialogInterface, _ ->
- runCatching {
- PasswordRepository.closeRepository()
- PasswordRepository.getRepositoryDirectory().let { dir ->
- dir.deleteRecursively()
- dir.mkdirs()
- }
- }
- .onFailure { it.message?.let { message -> activity.snackbar(message = message) } }
-
- activity.getSystemService<ShortcutManager>()?.apply {
- removeDynamicShortcuts(dynamicShortcuts.map { it.id }.toMutableList())
- }
- activity.sharedPrefs.edit { putBoolean(PreferenceKeys.REPOSITORY_INITIALIZED, false) }
- dialogInterface.cancel()
- activity.finish()
- }
- .setNegativeButton(R.string.dialog_do_not_delete) { dialogInterface, _ ->
- run { dialogInterface.cancel() }
- }
- .show()
- true
- }
- }
- }
- }
-
- @EntryPoint
- @InstallIn(SingletonComponent::class)
- interface RepositorySettingsEntryPoint {
- fun gitSettings(): GitSettings
-
- @GitPreferences fun encryptedPreferences(): SharedPreferences
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt
deleted file mode 100644
index 02addd84..00000000
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.settings
-
-import android.os.Bundle
-import android.view.MenuItem
-import androidx.activity.OnBackPressedCallback
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.os.BundleCompat
-import app.passwordstore.R
-import app.passwordstore.data.crypto.PGPPassphraseCache
-import app.passwordstore.databinding.ActivityPreferenceRecyclerviewBinding
-import app.passwordstore.util.extensions.viewBinding
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
-import de.Maxr1998.modernpreferences.Preference
-import de.Maxr1998.modernpreferences.PreferencesAdapter
-import de.Maxr1998.modernpreferences.helpers.screen
-import de.Maxr1998.modernpreferences.helpers.subScreen
-import javax.inject.Inject
-
-@AndroidEntryPoint
-class SettingsActivity : AppCompatActivity() {
-
- @Inject lateinit var passphraseCache: PGPPassphraseCache
- private val miscSettings = MiscSettings(this)
- private val autofillSettings = AutofillSettings(this)
- private val passwordSettings = PasswordSettings(this)
- private val repositorySettings = RepositorySettings(this)
- private val generalSettings = GeneralSettings(this)
- private lateinit var pgpSettings: PGPSettings
-
- private val binding by viewBinding(ActivityPreferenceRecyclerviewBinding::inflate)
- private val preferencesAdapter: PreferencesAdapter
- get() = binding.preferenceRecyclerView.adapter as PreferencesAdapter
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(binding.root)
- Preference.Config.dialogBuilderFactory = { context -> MaterialAlertDialogBuilder(context) }
- pgpSettings = PGPSettings(this, passphraseCache)
- val screen =
- screen(this) {
- subScreen {
- collapseIcon = true
- titleRes = R.string.pref_category_general_title
- iconRes = R.drawable.app_settings_alt_24px
- generalSettings.provideSettings(this)
- }
- subScreen {
- collapseIcon = true
- titleRes = R.string.pref_category_autofill_title
- iconRes = R.drawable.ic_wysiwyg_24px
- autofillSettings.provideSettings(this)
- }
- subScreen {
- collapseIcon = true
- titleRes = R.string.pref_category_passwords_title
- iconRes = R.drawable.ic_password_24px
- passwordSettings.provideSettings(this)
- }
- subScreen {
- collapseIcon = true
- titleRes = R.string.pref_category_repository_title
- iconRes = R.drawable.ic_call_merge_24px
- repositorySettings.provideSettings(this)
- }
- subScreen {
- collapseIcon = true
- titleRes = R.string.pref_category_misc_title
- iconRes = R.drawable.ic_miscellaneous_services_24px
- miscSettings.provideSettings(this)
- }
- subScreen {
- collapseIcon = true
- titleRes = R.string.pref_category_pgp_title
- iconRes = R.drawable.ic_lock_open_24px
- pgpSettings.provideSettings(this)
- }
- }
- val backPressedCallback =
- object : OnBackPressedCallback(true) {
- override fun handleOnBackPressed() {
- preferencesAdapter.goBack()
- }
- }
- onBackPressedDispatcher.addCallback(backPressedCallback)
- val adapter = PreferencesAdapter(screen)
- adapter.onScreenChangeListener =
- PreferencesAdapter.OnScreenChangeListener { subScreen, entering ->
- backPressedCallback.isEnabled = entering
- supportActionBar?.title =
- if (!entering) {
- getString(R.string.action_settings)
- } else {
- getString(subScreen.titleRes)
- }
- }
- if (savedInstanceState != null) {
- BundleCompat.getParcelable(
- savedInstanceState,
- "adapter",
- PreferencesAdapter.SavedState::class.java,
- )
- ?.let(adapter::loadSavedState)
- }
- binding.preferenceRecyclerView.adapter = adapter
- }
-
- override fun onSaveInstanceState(outState: Bundle) {
- super.onSaveInstanceState(outState)
- outState.putParcelable("adapter", preferencesAdapter.getSavedState())
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- return when (item.itemId) {
- android.R.id.home ->
- if (!preferencesAdapter.goBack()) {
- super.onOptionsItemSelected(item)
- } else {
- true
- }
- else -> super.onOptionsItemSelected(item)
- }
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsProvider.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsProvider.kt
deleted file mode 100644
index cacca80f..00000000
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsProvider.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.ui.settings
-
-import de.Maxr1998.modernpreferences.PreferenceScreen
-
-/** Used to generate a uniform API for all settings UI classes. */
-interface SettingsProvider {
-
- /** Inserts the settings items for the class into the given [builder]. */
- fun provideSettings(builder: PreferenceScreen.Builder)
-}
diff --git a/app/src/main/java/app/passwordstore/ui/setup/SetupGraph.kt b/app/src/main/java/app/passwordstore/ui/setup/SetupGraph.kt
index c2c2a2ac..40dfae74 100644
--- a/app/src/main/java/app/passwordstore/ui/setup/SetupGraph.kt
+++ b/app/src/main/java/app/passwordstore/ui/setup/SetupGraph.kt
@@ -33,10 +33,8 @@ import kotlinx.serialization.Serializable
/** The setup screens [MainActivity.setupIntent] opens on their own. */
enum class SetupStart(val route: Any) {
- GitServer(GitServerRoute(clone = false)),
Ssh(SshKeyRoute),
SshGenerate(SshKeyGenRoute),
- PgpKeys(PgpKeysRoute()),
PgpImport(PgpKeysRoute(KeysMode.Need)),
}
diff --git a/app/src/main/java/app/passwordstore/util/git/GitLogModel.kt b/app/src/main/java/app/passwordstore/util/git/GitLogModel.kt
deleted file mode 100644
index 329db6d5..00000000
--- a/app/src/main/java/app/passwordstore/util/git/GitLogModel.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-package app.passwordstore.util.git
-
-import app.passwordstore.data.repo.PasswordRepository
-import app.passwordstore.util.extensions.asLog
-import app.passwordstore.util.extensions.hash
-import app.passwordstore.util.extensions.time
-import app.passwordstore.util.extensions.unsafeLazy
-import com.github.michaelbull.result.getOrElse
-import com.github.michaelbull.result.runCatching
-import logcat.LogPriority.ERROR
-import logcat.logcat
-import org.eclipse.jgit.api.Git
-import org.eclipse.jgit.revwalk.RevCommit
-
-private val TAG = GitLogModel::class.java.simpleName
-
-private fun commits(): Iterable<RevCommit> {
- val repo = PasswordRepository.repository
- if (repo == null) {
- logcat(TAG, ERROR) { "Could not access git repository" }
- return listOf()
- }
- return runCatching { Git(repo).log().call() }
- .getOrElse { e ->
- logcat(TAG, ERROR) { e.asLog("Failed to obtain git commits") }
- listOf()
- }
-}
-
-/**
- * Provides [GitCommit] s from a git-log of the password git repository.
- *
- * All commits are acquired on the first request to this object.
- */
-class GitLogModel {
-
- // All commits are acquired here at once. Acquiring the commits in batches would not have been
- // entirely sensible because the amount of computation required to obtain commit number n from
- // the log includes the amount of computation required to obtain commit number n-1 from the log.
- // This is because the commit graph is walked from HEAD to the last commit to obtain.
- // Additionally, tests with 1000 commits in the log have not produced a significant delay in the
- // user experience.
- private val cache: MutableList<GitCommit> by unsafeLazy {
- commits()
- .map { GitCommit(it.hash, it.shortMessage, it.authorIdent.name, it.time) }
- .toMutableList()
- }
- val size = cache.size
-
- fun get(index: Int): GitCommit? {
- if (index >= size)
- logcat(ERROR) { "Cannot get git commit with index $index. There are only $size." }
- return cache.getOrNull(index)
- }
-}
diff --git a/app/src/main/res/layout/activity_git_config.xml b/app/src/main/res/layout/activity_git_config.xml
deleted file mode 100644
index b43ec6d6..00000000
--- a/app/src/main/res/layout/activity_git_config.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<!--
- ~ Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- ~ SPDX-License-Identifier: GPL-3.0-only
- -->
-
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:padding="@dimen/activity_horizontal_margin"
- tools:context="app.passwordstore.ui.git.config.GitConfigActivity"
- tools:layout_editor_absoluteX="0dp"
- tools:layout_editor_absoluteY="81dp">
-
- <com.google.android.material.textfield.TextInputLayout
- android:id="@+id/username_input_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:hint="@string/git_user_name_hint"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- tools:layout_editor_absoluteY="64dp">
-
- <com.google.android.material.textfield.TextInputEditText
- android:id="@+id/git_user_name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:inputType="textPersonName" />
-
- </com.google.android.material.textfield.TextInputLayout>
-
- <com.google.android.material.textfield.TextInputLayout
- android:id="@+id/email_input_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:hint="@string/git_user_email"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/username_input_layout">
-
- <com.google.android.material.textfield.TextInputEditText
- android:id="@+id/git_user_email"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:inputType="textEmailAddress" />
-
- </com.google.android.material.textfield.TextInputLayout>
-
- <com.google.android.material.button.MaterialButton
- android:id="@+id/save_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/crypto_save"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toBottomOf="@id/email_input_layout" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/git_tools_title"
- style="@style/TextAppearance.MaterialComponents.Headline5"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/git_tools"
- android:textSize="24sp"
- android:textStyle="bold"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/save_button" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/git_head_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/git_tools_title"
- tools:text="HEAD status" />
-
- <com.google.android.material.button.MaterialButton
- android:id="@+id/git_log"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/git_log"
- app:layout_constraintTop_toBottomOf="@+id/git_head_status" />
-
- <com.google.android.material.button.MaterialButton
- android:id="@+id/git_abort_rebase"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/abort_rebase"
- app:layout_constraintTop_toBottomOf="@+id/git_log" />
-
- <com.google.android.material.button.MaterialButton
- android:id="@+id/git_reset_to_remote"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/reset_to_remote"
- app:layout_constraintTop_toBottomOf="@id/git_abort_rebase" />
-
- <com.google.android.material.button.MaterialButton
- android:id="@+id/git_gc"
- android:layout_marginTop="8dp"
- android:text="@string/git_run_gc_job"
- app:layout_constraintTop_toBottomOf="@id/git_reset_to_remote"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/layout/activity_git_log.xml b/app/src/main/res/layout/activity_git_log.xml
deleted file mode 100644
index e9884db0..00000000
--- a/app/src/main/res/layout/activity_git_log.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- ~ SPDX-License-Identifier: GPL-3.0-only
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/git_log_recycler_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:scrollbars="vertical"
- app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
- tools:context="app.passwordstore.ui.git.log.GitLogActivity"
- tools:listitem="@layout/git_log_row_layout" />
-
-</LinearLayout>
diff --git a/app/src/main/res/layout/activity_preference_recyclerview.xml b/app/src/main/res/layout/activity_preference_recyclerview.xml
deleted file mode 100644
index 805bc79a..00000000
--- a/app/src/main/res/layout/activity_preference_recyclerview.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- ~ SPDX-License-Identifier: GPL-3.0-only
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/preference_recycler_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
-
-</LinearLayout>
diff --git a/app/src/main/res/layout/activity_proxy_selector.xml b/app/src/main/res/layout/activity_proxy_selector.xml
deleted file mode 100644
index b83ca9f7..00000000
--- a/app/src/main/res/layout/activity_proxy_selector.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- ~ SPDX-License-Identifier: GPL-3.0-only
- -->
-
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <com.google.android.material.textfield.TextInputLayout
- android:id="@+id/proxy_host_input_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/activity_horizontal_margin"
- android:layout_marginTop="@dimen/activity_vertical_margin"
- android:layout_marginEnd="@dimen/activity_horizontal_margin"
- android:hint="@string/proxy_hostname"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- tools:layout_editor_absoluteY="64dp">
-
- <com.google.android.material.textfield.TextInputEditText
- android:id="@+id/proxy_host"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:inputType="textUri"
- android:nextFocusForward="@id/proxy_user" />
-
- </com.google.android.material.textfield.TextInputLayout>
-
- <com.google.android.material.textfield.TextInputLayout
- android:id="@+id/proxy_user_input_layout"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/activity_horizontal_margin"
- android:layout_marginTop="@dimen/normal_margin"
- android:layout_marginEnd="@dimen/normal_margin"
- android:hint="@string/username"
- app:layout_constraintEnd_toStartOf="@id/proxy_port_input_layout"
- app:layout_constraintHorizontal_weight="0.65"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/proxy_host_input_layout">
-
- <com.google.android.material.textfield.TextInputEditText
- android:id="@+id/proxy_user"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:inputType="textWebEmailAddress"
- android:nextFocusForward="@id/proxy_port" />
-
- </com.google.android.material.textfield.TextInputLayout>
-
- <com.google.android.material.textfield.TextInputLayout
- android:id="@+id/proxy_port_input_layout"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/normal_margin"
- android:layout_marginTop="@dimen/normal_margin"
- android:layout_marginEnd="@dimen/activity_horizontal_margin"
- android:hint="@string/port"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_weight="0.35"
- app:layout_constraintStart_toEndOf="@id/proxy_user_input_layout"
- app:layout_constraintTop_toBottomOf="@id/proxy_host_input_layout">
-
- <com.google.android.material.textfield.TextInputEditText
- android:id="@+id/proxy_port"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:inputType="number"
- android:nextFocusForward="@id/proxy_password" />
- </com.google.android.material.textfield.TextInputLayout>
-
- <com.google.android.material.textfield.TextInputLayout
- android:id="@+id/proxy_password_input_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="@dimen/activity_horizontal_margin"
- android:layout_marginTop="@dimen/normal_margin"
- android:layout_marginEnd="@dimen/activity_horizontal_margin"
- android:hint="@string/password"
- app:endIconMode="password_toggle"
- app:layout_constraintStart_toStartOf="@id/proxy_user_input_layout"
- app:layout_constraintTop_toBottomOf="@id/proxy_user_input_layout">
-
- <com.google.android.material.textfield.TextInputEditText
- android:id="@+id/proxy_password"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:inputType="textPassword" />
- </com.google.android.material.textfield.TextInputLayout>
-
- <com.google.android.material.button.MaterialButton
- android:id="@+id/save"
- style="?attr/materialButtonOutlinedStyle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/normal_margin"
- android:layout_marginEnd="@dimen/activity_horizontal_margin"
- android:text="@string/crypto_save"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toBottomOf="@id/proxy_password_input_layout" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/layout/dialog_text_input.xml b/app/src/main/res/layout/dialog_text_input.xml
deleted file mode 100644
index c8539273..00000000
--- a/app/src/main/res/layout/dialog_text_input.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- ~ SPDX-License-Identifier: GPL-3.0-only
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="@dimen/activity_horizontal_margin">
-
- <com.google.android.material.textfield.TextInputLayout
- android:id="@+id/text_input_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <com.google.android.material.textfield.TextInputEditText
- android:id="@+id/edit_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <requestFocus />
- </com.google.android.material.textfield.TextInputLayout>
-
-</LinearLayout>
diff --git a/app/src/main/res/layout/git_log_row_layout.xml b/app/src/main/res/layout/git_log_row_layout.xml
deleted file mode 100644
index e996f6af..00000000
--- a/app/src/main/res/layout/git_log_row_layout.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- ~ SPDX-License-Identifier: GPL-3.0-only
- -->
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingHorizontal="@dimen/activity_vertical_margin"
- android:paddingVertical="@dimen/activity_horizontal_margin">
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/git_log_row_message"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/normal_margin"
- android:ellipsize="end"
- android:maxLines="2"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/git_log_row_hash"
- tools:text="Commit message" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/git_log_row_hash"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="?attr/colorSecondary"
- android:textStyle="bold"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- tools:text="Hash" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/git_log_row_time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:alpha="0.5"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- tools:text="Time" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/layout/oreo_autofill_instructions.xml b/app/src/main/res/layout/oreo_autofill_instructions.xml
deleted file mode 100644
index 66881390..00000000
--- a/app/src/main/res/layout/oreo_autofill_instructions.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright © 2014-2024 The Android Password Store Authors. All Rights Reserved.
- ~ SPDX-License-Identifier: GPL-3.0-only
- -->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="24dp"
- android:paddingTop="20dp"
- android:paddingRight="24dp"
- android:paddingBottom="20dp">
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/intro_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/oreo_autofill_enable_dialog_description"
- android:textSize="16sp" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/activity_vertical_margin"
- android:text="@string/oreo_autofill_enable_dialog_instructions"
- android:textSize="16sp" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/activity_vertical_margin"
- android:text="@string/oreo_autofill_enable_dialog_installed_browsers"
- android:textSize="16sp"
- android:textStyle="bold" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/supportedBrowsers"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="16sp"
- tools:text="Firefox: Fill and save credentials" />
-
-
- </LinearLayout>
-</ScrollView>
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 618aac0d..08b74717 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -215,7 +215,6 @@
<string name="pref_biometric_auth_title">Biometrische Authentifizierung</string>
<string name="pref_biometric_auth_summary">Falls aktiviert, werden Sie beim Starten der App nach Ihrem Fingerabdruck gefragt.</string>
<string name="pref_biometric_auth_summary_error">Fingerabdrucksensor fehlt oder ist nicht ansprechbar.</string>
- <string name="pref_title_openkeystore_clear_keyid">Lösche gespeicherte OpenKeystore SSH-Schlüssel-ID.</string>
<string name="your_public_key">Ihr öffentlicher Schlüssel</string>
<string name="error_generate_ssh_key">Fehler beim Erstellen des SSH-Schlüssels</string>
<string name="pref_show_hidden_title">Alle Dateien und Ordner anzeigen</string>
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 4cc7d29d..796884d7 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -203,7 +203,6 @@
<string name="pref_biometric_auth_title">Activer l\'authentification biométrique</string>
<string name="pref_biometric_auth_summary">Lorsque cette option est activée, Password Store vous demandera votre empreinte digitale au lancement</string>
<string name="pref_biometric_auth_summary_error">Lecteur d\'empreinte digitale non accessible ou manquant</string>
- <string name="pref_title_openkeystore_clear_keyid">Effacer la clé d\'identification SSH d\'OpenKeystore mémorisée</string>
<string name="your_public_key">Votre clé publique</string>
<string name="error_generate_ssh_key">Une erreur est survenue pendant la génération de la clé ssh</string>
<string name="pref_show_hidden_title">Afficher tous les fichiers et dossiers</string>
diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml
index 34b1ce6a..b79e2990 100644
--- a/app/src/main/res/values-gl/strings.xml
+++ b/app/src/main/res/values-gl/strings.xml
@@ -217,7 +217,6 @@ a app desde unha fonte de confianza, como a Play Store, Amazon Appstore, F-Droid
<string name="pref_biometric_auth_title">Activar autenticación biométrica</string>
<string name="pref_biometric_auth_summary">Ao activala, Password Store vaiche pedir a túa pegada dactilar ao iniciar a app</string>
<string name="pref_biometric_auth_summary_error">O hardware de pegada dixital non é accesible ou existente</string>
- <string name="pref_title_openkeystore_clear_keyid">Eliminar o ID lembrado da chave SSH en OpenKeystore</string>
<string name="your_public_key">A túa chave pública</string>
<string name="error_generate_ssh_key">Algo fallou ao intentar crear a chave-ssh</string>
<string name="pref_show_hidden_title">Mostar cartafoles ocultos</string>
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 28a38301..ee7affd2 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -198,7 +198,6 @@
<string name="pref_biometric_auth_title">Abilita autenticazione biometrica</string>
<string name="pref_biometric_auth_summary">Se attiva, HardenedPass chiede l\'impronta digitale all\'avvio dell\'app</string>
<string name="pref_biometric_auth_summary_error">L\'hardware delle impronte digitali non è accessibile o mancante</string>
- <string name="pref_title_openkeystore_clear_keyid">Elimina l\'ID della Chiave SSH di OpenKeystore memorizzato</string>
<string name="your_public_key">La tua chiave pubblica</string>
<string name="error_generate_ssh_key">Errore durante la generazione della chiave SSH</string>
<string name="pref_show_hidden_title">Mostra tutti i file e cartelle</string>
@@ -303,7 +302,6 @@
<string name="pref_passphrase_cache_auto_clear_authenticate_disable">Autenticati per disattivare la cancellazione automatica</string>
<string name="pref_passphrase_cache_auto_clear_title">Cancella automaticamente le frasi segrete memorizzate</string>
<string name="pref_passphrase_cache_auto_clear_summary">Cancella le frasi segrete memorizzate allo spegnimento dello schermo</string>
- <string name="pref_biometric_auth_summary_disabled_platform">Funzione non disponibile a causa di un bug della piattaforma</string>
<string name="password_creation_encrypt_fail_message">Impossibile cifrare la password, non è stato salvato nulla: %1$s</string>
<string name="otp_import_failure_no_selection">Nessuna immagine selezionata</string>
<string name="invalid_gpg_id">Trovato .gpg-id, ma contiene un ID chiave, un\'impronta o un ID utente non valido</string>
diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml
index 06e0a555..b2836176 100644
--- a/app/src/main/res/values-ko-rKR/strings.xml
+++ b/app/src/main/res/values-ko-rKR/strings.xml
@@ -211,7 +211,6 @@
<string name="pref_biometric_auth_title">생체 인증 사용</string>
<string name="pref_biometric_auth_summary">비밀번호 저장소를 활성화하면 앱을 시작할 때 지문을 입력하라는 메시지가 표시됩니다</string>
<string name="pref_biometric_auth_summary_error">지문 하드웨어에 액세스할 수 없거나 누락된 경우</string>
- <string name="pref_title_openkeystore_clear_keyid">저장된 OpenKeyStore SSH 키 ID 지우기</string>
<string name="your_public_key">공개 키</string>
<string name="error_generate_ssh_key">Ssh 키를 생성하는 동안 오류가 발생했습니다.</string>
<string name="pref_show_hidden_title">모든 파일 및 폴더 표시</string>
diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml
index 6bdb966c..34272cae 100644
--- a/app/src/main/res/values-pl-rPL/strings.xml
+++ b/app/src/main/res/values-pl-rPL/strings.xml
@@ -210,7 +210,6 @@
<string name="pref_biometric_auth_title">Włącz uwierzytelnianie biometryczne</string>
<string name="pref_biometric_auth_summary">Gdy włączone, Password Store zapyta Cię o odcisk palca podczas uruchamiania aplikacji</string>
<string name="pref_biometric_auth_summary_error">Czytnik linii papilarnych jest niedostępny</string>
- <string name="pref_title_openkeystore_clear_keyid">Wyczyść zapamiętany identyfikator klucza SSH OpenKeystore</string>
<string name="your_public_key">Twój klucz publiczny</string>
<string name="error_generate_ssh_key">Błąd podczas generowania klucza SSH</string>
<string name="pref_show_hidden_title">Pokaż ukryte pliki i foldery</string>
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 8f40c831..9f60b64e 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -215,7 +215,6 @@
<string name="pref_biometric_auth_title">Ativar autenticação biométrica</string>
<string name="pref_biometric_auth_summary">Quando ativado, o Password Store irá pedir a sua impressão digital ao iniciar o aplicativo</string>
<string name="pref_biometric_auth_summary_error">Hardware de impressão digital não acessível ou ausente</string>
- <string name="pref_title_openkeystore_clear_keyid">Limpar ID de chave SSH lembrada do OpenKeystore</string>
<string name="your_public_key">Sua chave pública</string>
<string name="error_generate_ssh_key">Erro ao tentar gerar a chave SSH</string>
<string name="pref_show_hidden_title">Mostrar todos os arquivos e pastas</string>
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index af3078bc..298d9508 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -208,7 +208,6 @@
<string name="pref_biometric_auth_title">Включить биометрическую аутентификацию</string>
<string name="pref_biometric_auth_summary">Когда ключено, Password Store будет запрашивать ваш опечаток пальца при каждом запуске приложения</string>
<string name="pref_biometric_auth_summary_error">Сенсор отпечатка пальца не доступен или отсутствует</string>
- <string name="pref_title_openkeystore_clear_keyid">Очистить сохраненный SSH Key идентификатор OpenKystortore</string>
<string name="your_public_key">Ваш публичный ключ</string>
<string name="error_generate_ssh_key">Возникла ошибка при попытке генерации ssh ключа</string>
<string name="pref_show_hidden_title">Показать все файлы и директории</string>
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 959d5fac..85125fc2 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -216,7 +216,6 @@
<string name="pref_biometric_auth_title">启用生物识别认证</string>
<string name="pref_biometric_auth_summary">如果启用,Password Store 将在启动应用时提示您使用指纹进行身份验证</string>
<string name="pref_biometric_auth_summary_error">指纹硬件无法访问或丢失</string>
- <string name="pref_title_openkeystore_clear_keyid">清除记住的 OpenKeystore SSH 密钥ID</string>
<string name="your_public_key">你的公开密钥</string>
<string name="error_generate_ssh_key">尝试生成SSH密钥时出错</string>
<string name="pref_show_hidden_title">显示所有文件和目录</string>
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 8351a358..44d4f581 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -7,5 +7,4 @@
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
- <dimen name="normal_margin">8dp</dimen>
</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 403ee2ae..653cf72c 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -247,8 +247,6 @@
<string name="pref_biometric_auth_title">Enable biometric authentication</string>
<string name="pref_biometric_auth_summary">When enabled, HardenedPass will prompt you for your fingerprint when launching the app</string>
<string name="pref_biometric_auth_summary_error">Fingerprint hardware not accessible or missing</string>
- <string name="pref_biometric_auth_summary_disabled_platform">Feature unavailable due to a platform bug</string>
- <string name="pref_title_openkeystore_clear_keyid">Clear remembered OpenKeystore SSH Key ID</string>
<string name="your_public_key">Your public key</string>
<string name="error_generate_ssh_key">Error while trying to generate the ssh-key</string>
<string name="pref_show_hidden_title">Show all files and folders</string>