aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java')
-rw-r--r--app/src/main/java/app/passwordstore/ui/editor/EditorDestination.kt9
-rw-r--r--app/src/main/java/app/passwordstore/ui/list/StoreActions.kt34
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsScreen.kt6
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsViewModel.kt2
-rw-r--r--app/src/main/java/app/passwordstore/util/settings/GitSettings.kt6
-rw-r--r--app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt1
6 files changed, 53 insertions, 5 deletions
diff --git a/app/src/main/java/app/passwordstore/ui/editor/EditorDestination.kt b/app/src/main/java/app/passwordstore/ui/editor/EditorDestination.kt
index 8e433957..617d804a 100644
--- a/app/src/main/java/app/passwordstore/ui/editor/EditorDestination.kt
+++ b/app/src/main/java/app/passwordstore/ui/editor/EditorDestination.kt
@@ -35,7 +35,9 @@ import app.passwordstore.R
import app.passwordstore.data.repo.PasswordRepository
import app.passwordstore.ui.crypto.copyPasswordToClipboard
import app.passwordstore.ui.crypto.getPGPIdentifiers
+import app.passwordstore.ui.git.base.BaseGitActivity
import app.passwordstore.ui.list.FolderPicker
+import app.passwordstore.ui.list.commitAndPush
import app.passwordstore.util.extensions.commitChange
import app.passwordstore.util.extensions.getString
import app.passwordstore.util.extensions.isInsideRepository
@@ -148,12 +150,15 @@ fun EditorDestination(
}
// ponytail: commit failures are not shown, as for the list's move and delete. A commit cut
// short by recreation runs again; one that already went through finds nothing to commit.
- activity.commitChange(
+ val message =
activity.getString(
if (original != null) R.string.git_commit_edit_text else R.string.git_commit_add_text,
saved.file.relativeTo(root).path.removeSuffix(".gpg"),
)
- )
+ // ponytail: AutofillSaveActivity closes right after saving, which would cancel a push, so its
+ // saves stay local until the next push or sync.
+ if (activity is BaseGitActivity) activity.commitAndPush(message)
+ else activity.commitChange(message)
keyboard?.hide()
focusManager.clearFocus()
viewModel.left()
diff --git a/app/src/main/java/app/passwordstore/ui/list/StoreActions.kt b/app/src/main/java/app/passwordstore/ui/list/StoreActions.kt
index cff0964c..94a234c1 100644
--- a/app/src/main/java/app/passwordstore/ui/list/StoreActions.kt
+++ b/app/src/main/java/app/passwordstore/ui/list/StoreActions.kt
@@ -6,7 +6,9 @@
package app.passwordstore.ui.list
import android.content.Context
+import androidx.compose.material3.SnackbarDuration
import androidx.core.content.edit
+import androidx.lifecycle.lifecycleScope
import app.passwordstore.R
import app.passwordstore.data.repo.PasswordRepository
import app.passwordstore.ui.crypto.getLongName
@@ -20,12 +22,17 @@ import app.passwordstore.util.extensions.getString
import app.passwordstore.util.extensions.isInsideRepository
import app.passwordstore.util.extensions.listFilesRecursively
import app.passwordstore.util.extensions.sharedPrefs
+import app.passwordstore.util.extensions.snackbar
import app.passwordstore.util.settings.PasswordSortOrder
import app.passwordstore.util.settings.PreferenceKeys
+import com.github.michaelbull.result.onFailure
+import com.github.michaelbull.result.onSuccess
import java.io.File
import java.nio.file.Files
+import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import logcat.LogPriority.ERROR
+import logcat.asLog
import logcat.logcat
/** Shared preferences file of the "recently used" sort order, keyed by base64 of the path. */
@@ -64,6 +71,27 @@ internal fun File.deleteWithoutFollowingLinks(): Boolean {
return delete()
}
+/**
+ * Commits the store and, when the user asked for it, pushes without holding up the caller. A failed
+ * push only says so: the commit stays local, and [BaseGitActivity.promptOnErrorHandler] would
+ * delete the saved credentials over what may just be a missing network.
+ *
+ * ponytail: a push cut off by recreation is not resumed; the next one sends everything. An SSH key
+ * behind biometrics prompts on each change.
+ */
+suspend fun BaseGitActivity.commitAndPush(message: String) {
+ commitChange(message).onSuccess {
+ if (gitSettings.pushAfterCommit && gitSettings.url != null) {
+ lifecycleScope.launch {
+ launchGitOperation(BaseGitActivity.GitOp.PUSH).onFailure {
+ logcat(ERROR) { it.asLog() }
+ snackbar(getString(R.string.git_push_after_commit_failed), SnackbarDuration.Long)
+ }
+ }
+ }
+ }
+}
+
/** Deletes [files] (entries or whole folders), drops their autofill matches and commits. */
suspend fun BaseGitActivity.deleteItems(files: List<File>) {
val root = PasswordRepository.getRepositoryDirectory()
@@ -72,7 +100,7 @@ suspend fun BaseGitActivity.deleteItems(files: List<File>) {
files.forEach { it.deleteWithoutFollowingLinks() }
AutofillMatcher.updateMatches(applicationContext, delete = deleted)
}
- commitChange(
+ commitAndPush(
getString(
R.string.git_commit_remove_text,
files.joinToString(", ") { it.toRelativeString(root) },
@@ -116,14 +144,14 @@ suspend fun BaseGitActivity.moveItems(files: List<File>, target: File) {
val relative = "${target.absolutePath}/".replace(repo, "").replace("/+".toRegex(), "/")
getString(R.string.git_commit_move_multiple_text, relative)
}
- commitChange(message)
+ commitAndPush(message)
}
/** Renames the folder [from] to [to], keeps its recently-used time, then commits. */
suspend fun BaseGitActivity.renameFolder(from: File, to: File) {
if (!moveFile(from, to)) return
moveHistory(from, to)
- commitChange(getString(R.string.git_commit_move_text, from.name, to.name))
+ commitAndPush(getString(R.string.git_commit_move_text, from.name, to.name))
}
/** Carries the "recently used" time of [from] over to [to]. */
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsScreen.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsScreen.kt
index ed78608f..a7bbe30a 100644
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsScreen.kt
+++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsScreen.kt
@@ -258,6 +258,12 @@ fun SettingsSectionScreen(
else R.string.pref_rebase_on_pull_summary
),
)
+ PreferenceSwitch(
+ title = stringResource(R.string.pref_push_after_commit_title),
+ checked = state.pushAfterCommit,
+ onCheckedChange = { onBoolean(PreferenceKeys.PUSH_AFTER_COMMIT, it) },
+ summary = stringResource(R.string.pref_push_after_commit_summary),
+ )
if (state.isGitRepo) {
PreferenceAction(
title = stringResource(R.string.pref_edit_git_server_settings),
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsViewModel.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsViewModel.kt
index ef604f1f..cfc576ae 100644
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsViewModel.kt
+++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsViewModel.kt
@@ -55,6 +55,7 @@ data class SettingsState(
val showPassword: Boolean,
val copyOnDecrypt: Boolean,
val rebaseOnPull: Boolean,
+ val pushAfterCommit: Boolean,
val isGitRepo: Boolean,
val httpsRemote: Boolean,
val canShowSshKey: Boolean,
@@ -205,6 +206,7 @@ constructor(
showPassword = prefs.getBoolean(PreferenceKeys.SHOW_PASSWORD, true),
copyOnDecrypt = prefs.getBoolean(PreferenceKeys.COPY_ON_DECRYPT, false),
rebaseOnPull = gitSettings.rebaseOnPull,
+ pushAfterCommit = gitSettings.pushAfterCommit,
isGitRepo = PasswordRepository.isGitRepo(),
httpsRemote = gitSettings.url?.startsWith("https") == true,
canShowSshKey = SshKey.canShowSshPublicKey,
diff --git a/app/src/main/java/app/passwordstore/util/settings/GitSettings.kt b/app/src/main/java/app/passwordstore/util/settings/GitSettings.kt
index 004028c4..0052f79c 100644
--- a/app/src/main/java/app/passwordstore/util/settings/GitSettings.kt
+++ b/app/src/main/java/app/passwordstore/util/settings/GitSettings.kt
@@ -125,6 +125,12 @@ constructor(
settings.edit { putBoolean(PreferenceKeys.REBASE_ON_PULL, value) }
}
+ var pushAfterCommit
+ get() = settings.getBoolean(PreferenceKeys.PUSH_AFTER_COMMIT, false)
+ set(value) {
+ settings.edit { putBoolean(PreferenceKeys.PUSH_AFTER_COMMIT, value) }
+ }
+
sealed class UpdateConnectionSettingsResult {
class MissingUsername(val newProtocol: Protocol) : UpdateConnectionSettingsResult()
diff --git a/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt b/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt
index ecc7a51c..9fd2658d 100644
--- a/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt
+++ b/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt
@@ -86,6 +86,7 @@ object PreferenceKeys {
const val PROXY_PASSWORD = "proxy_password"
const val REBASE_ON_PULL = "rebase_on_pull"
+ const val PUSH_AFTER_COMMIT = "push_after_commit"
const val DICEWARE_SEPARATOR = "diceware_separator"
const val DICEWARE_LENGTH = "diceware_length"