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

Commit a34f749

Browse files
authored
Add tentative workaround for dialog crashes and refactor Git-related code (#1100)
* Ensure we're creating dialogs on the main thread Signed-off-by: Harsh Shandilya <[email protected]> * Remove unused operation type Signed-off-by: Harsh Shandilya <[email protected]> * Refactor launchGitOperation to use an enum Signed-off-by: Harsh Shandilya <[email protected]>
1 parent eef8097 commit a34f749

File tree

7 files changed

+58
-63
lines changed

7 files changed

+58
-63
lines changed

app/src/main/java/com/zeapo/pwdstore/OnboardingActivity.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import com.github.michaelbull.result.onFailure
1717
import com.github.michaelbull.result.runCatching
1818
import com.google.android.material.dialog.MaterialAlertDialogBuilder
1919
import com.zeapo.pwdstore.databinding.ActivityOnboardingBinding
20-
import com.zeapo.pwdstore.git.BaseGitActivity
2120
import com.zeapo.pwdstore.git.GitServerConfigActivity
2221
import com.zeapo.pwdstore.utils.PasswordRepository
2322
import com.zeapo.pwdstore.utils.PreferenceKeys
@@ -92,9 +91,7 @@ class OnboardingActivity : AppCompatActivity() {
9291
*/
9392
private fun cloneToHiddenDir() {
9493
settings.edit { putBoolean(PreferenceKeys.GIT_EXTERNAL, false) }
95-
cloneAction.launch(Intent(this, GitServerConfigActivity::class.java).apply {
96-
putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_CLONE)
97-
})
94+
cloneAction.launch(GitServerConfigActivity.createCloneIntent(this))
9895
}
9996

10097
/**

app/src/main/java/com/zeapo/pwdstore/PasswordFragment.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package com.zeapo.pwdstore
66

77
import android.content.Context
8-
import android.content.Intent
98
import android.content.SharedPreferences
109
import android.os.Bundle
1110
import android.os.Parcelable
@@ -90,18 +89,16 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) {
9089
} else if (!PasswordRepository.isGitRepo()) {
9190
Snackbar.make(binding.root, getString(R.string.clone_git_repo), Snackbar.LENGTH_INDEFINITE)
9291
.setAction(R.string.clone_button) {
93-
val intent = Intent(context, GitServerConfigActivity::class.java)
94-
intent.putExtra(BaseGitActivity.REQUEST_ARG_OP, BaseGitActivity.REQUEST_CLONE)
95-
swipeResult.launch(intent)
92+
swipeResult.launch(GitServerConfigActivity.createCloneIntent(requireContext()))
9693
}
9794
.show()
9895
binding.swipeRefresher.isRefreshing = false
9996
} else {
10097
// When authentication is set to AuthMode.None then the only git operation we can
10198
// run is a pull, so automatically fallback to that.
10299
val operationId = when (GitSettings.authMode) {
103-
AuthMode.None -> BaseGitActivity.REQUEST_PULL
104-
else -> BaseGitActivity.REQUEST_SYNC
100+
AuthMode.None -> BaseGitActivity.GitOp.PULL
101+
else -> BaseGitActivity.GitOp.SYNC
105102
}
106103
requireStore().apply {
107104
lifecycleScope.launch {

app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -272,23 +272,23 @@ class PasswordStore : BaseGitActivity() {
272272
initBefore.show()
273273
return false
274274
}
275-
runGitOperation(REQUEST_PUSH)
275+
runGitOperation(GitOp.PUSH)
276276
return true
277277
}
278278
R.id.git_pull -> {
279279
if (!isInitialized) {
280280
initBefore.show()
281281
return false
282282
}
283-
runGitOperation(REQUEST_PULL)
283+
runGitOperation(GitOp.PULL)
284284
return true
285285
}
286286
R.id.git_sync -> {
287287
if (!isInitialized) {
288288
initBefore.show()
289289
return false
290290
}
291-
runGitOperation(REQUEST_SYNC)
291+
runGitOperation(GitOp.SYNC)
292292
return true
293293
}
294294
R.id.refresh -> {
@@ -312,10 +312,10 @@ class PasswordStore : BaseGitActivity() {
312312
searchItem.collapseActionView()
313313
}
314314

315-
private fun runGitOperation(operation: Int) = lifecycleScope.launch {
315+
private fun runGitOperation(operation: GitOp) = lifecycleScope.launch {
316316
launchGitOperation(operation).fold(
317317
success = { refreshPasswordList() },
318-
failure = ::promptOnErrorHandler
318+
failure = { promptOnErrorHandler(it) },
319319
)
320320
}
321321

@@ -520,7 +520,6 @@ class PasswordStore : BaseGitActivity() {
520520
val intent = Intent(this, SelectFolderActivity::class.java)
521521
val fileLocations = values.map { it.file.absolutePath }.toTypedArray()
522522
intent.putExtra("Files", fileLocations)
523-
intent.putExtra(REQUEST_ARG_OP, "SELECTFOLDER")
524523
registerForActivityResult(StartActivityForResult()) { result ->
525524
val intentData = result.data ?: return@registerForActivityResult
526525
val filesToMove = requireNotNull(intentData.getStringArrayExtra("Files"))

app/src/main/java/com/zeapo/pwdstore/git/BaseGitActivity.kt

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ package com.zeapo.pwdstore.git
66

77
import androidx.appcompat.app.AppCompatActivity
88
import androidx.core.content.edit
9-
import com.github.ajalt.timberkt.Timber.tag
109
import com.github.ajalt.timberkt.d
11-
import com.github.ajalt.timberkt.e
1210
import com.github.michaelbull.result.Err
1311
import com.github.michaelbull.result.Result
1412
import com.github.michaelbull.result.andThen
@@ -18,14 +16,15 @@ import com.zeapo.pwdstore.R
1816
import com.zeapo.pwdstore.git.config.GitSettings
1917
import com.zeapo.pwdstore.git.operation.BreakOutOfDetached
2018
import com.zeapo.pwdstore.git.operation.CloneOperation
21-
import com.zeapo.pwdstore.git.operation.GitOperation
2219
import com.zeapo.pwdstore.git.operation.PullOperation
2320
import com.zeapo.pwdstore.git.operation.PushOperation
2421
import com.zeapo.pwdstore.git.operation.ResetToRemoteOperation
2522
import com.zeapo.pwdstore.git.operation.SyncOperation
2623
import com.zeapo.pwdstore.utils.PreferenceKeys
2724
import com.zeapo.pwdstore.utils.getEncryptedPrefs
2825
import com.zeapo.pwdstore.utils.sharedPrefs
26+
import kotlinx.coroutines.Dispatchers
27+
import kotlinx.coroutines.withContext
2928
import net.schmizz.sshj.common.DisconnectReason
3029
import net.schmizz.sshj.common.SSHException
3130
import net.schmizz.sshj.userauth.UserAuthException
@@ -36,30 +35,38 @@ import net.schmizz.sshj.userauth.UserAuthException
3635
*/
3736
abstract class BaseGitActivity : AppCompatActivity() {
3837

38+
/**
39+
* Enum of possible Git operations than can be run through [launchGitOperation].
40+
*/
41+
enum class GitOp {
42+
BREAK_OUT_OF_DETACHED,
43+
CLONE,
44+
PULL,
45+
PUSH,
46+
RESET,
47+
SYNC,
48+
}
49+
3950
/**
4051
* Attempt to launch the requested Git operation.
4152
* @param operation The type of git operation to launch
4253
*/
43-
suspend fun launchGitOperation(operation: Int): Result<Unit, Throwable> {
54+
suspend fun launchGitOperation(operation: GitOp): Result<Unit, Throwable> {
4455
if (GitSettings.url == null) {
4556
return Err(IllegalStateException("Git url is not set!"))
4657
}
47-
if (operation == REQUEST_SYNC && !GitSettings.useMultiplexing) {
58+
if (operation == GitOp.SYNC && !GitSettings.useMultiplexing) {
4859
// If the server does not support multiple SSH channels per connection, we cannot run
4960
// a sync operation without reconnecting and thus break sync into its two parts.
50-
return launchGitOperation(REQUEST_PULL).andThen { launchGitOperation(REQUEST_PUSH) }
61+
return launchGitOperation(GitOp.PULL).andThen { launchGitOperation(GitOp.PUSH) }
5162
}
5263
val op = when (operation) {
53-
REQUEST_CLONE, GitOperation.GET_SSH_KEY_FROM_CLONE -> CloneOperation(this, GitSettings.url!!)
54-
REQUEST_PULL -> PullOperation(this)
55-
REQUEST_PUSH -> PushOperation(this)
56-
REQUEST_SYNC -> SyncOperation(this)
57-
BREAK_OUT_OF_DETACHED -> BreakOutOfDetached(this)
58-
REQUEST_RESET -> ResetToRemoteOperation(this)
59-
else -> {
60-
tag(TAG).e { "Operation not recognized : $operation" }
61-
return Err(IllegalArgumentException("$operation is not a valid Git operation"))
62-
}
64+
GitOp.CLONE -> CloneOperation(this, GitSettings.url!!)
65+
GitOp.PULL -> PullOperation(this)
66+
GitOp.PUSH -> PushOperation(this)
67+
GitOp.SYNC -> SyncOperation(this)
68+
GitOp.BREAK_OUT_OF_DETACHED -> BreakOutOfDetached(this)
69+
GitOp.RESET -> ResetToRemoteOperation(this)
6370
}
6471
return op.executeAfterAuthentication(GitSettings.authMode).mapError { throwable ->
6572
val err = rootCauseException(throwable)
@@ -76,22 +83,24 @@ abstract class BaseGitActivity : AppCompatActivity() {
7683
finish()
7784
}
7885

79-
fun promptOnErrorHandler(err: Throwable, onPromptDone: () -> Unit = {}) {
86+
suspend fun promptOnErrorHandler(err: Throwable, onPromptDone: () -> Unit = {}) {
8087
val error = rootCauseException(err)
8188
if (!isExplicitlyUserInitiatedError(error)) {
8289
getEncryptedPrefs("git_operation").edit {
8390
remove(PreferenceKeys.HTTPS_PASSWORD)
8491
}
8592
sharedPrefs.edit { remove(PreferenceKeys.SSH_OPENKEYSTORE_KEYID) }
8693
d(error)
87-
MaterialAlertDialogBuilder(this).run {
88-
setTitle(resources.getString(R.string.jgit_error_dialog_title))
89-
setMessage(ErrorMessages[error])
90-
setPositiveButton(resources.getString(R.string.dialog_ok)) { _, _ -> }
91-
setOnDismissListener {
92-
onPromptDone()
94+
withContext(Dispatchers.Main) {
95+
MaterialAlertDialogBuilder(this@BaseGitActivity).run {
96+
setTitle(resources.getString(R.string.jgit_error_dialog_title))
97+
setMessage(ErrorMessages[error])
98+
setPositiveButton(resources.getString(R.string.dialog_ok)) { _, _ -> }
99+
setOnDismissListener {
100+
onPromptDone()
101+
}
102+
show()
93103
}
94-
show()
95104
}
96105
} else {
97106
onPromptDone()
@@ -130,16 +139,4 @@ abstract class BaseGitActivity : AppCompatActivity() {
130139
}
131140
return rootCause
132141
}
133-
134-
companion object {
135-
136-
const val REQUEST_ARG_OP = "OPERATION"
137-
const val REQUEST_PULL = 101
138-
const val REQUEST_PUSH = 102
139-
const val REQUEST_CLONE = 103
140-
const val REQUEST_SYNC = 104
141-
const val BREAK_OUT_OF_DETACHED = 105
142-
const val REQUEST_RESET = 106
143-
const val TAG = "AbstractGitActivity"
144-
}
145142
}

app/src/main/java/com/zeapo/pwdstore/git/GitConfigActivity.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class GitConfigActivity : BaseGitActivity() {
9191
}
9292
binding.gitAbortRebase.setOnClickListener {
9393
lifecycleScope.launch {
94-
launchGitOperation(BREAK_OUT_OF_DETACHED).fold(
94+
launchGitOperation(GitOp.BREAK_OUT_OF_DETACHED).fold(
9595
success = {
9696
MaterialAlertDialogBuilder(this@GitConfigActivity).run {
9797
setTitle(resources.getString(R.string.git_abort_and_push_title))
@@ -115,7 +115,7 @@ class GitConfigActivity : BaseGitActivity() {
115115
}
116116
binding.gitResetToRemote.setOnClickListener {
117117
lifecycleScope.launch {
118-
launchGitOperation(REQUEST_RESET).fold(
118+
launchGitOperation(GitOp.RESET).fold(
119119
success = ::finishOnSuccessHandler,
120120
failure = { err ->
121121
promptOnErrorHandler(err) {

app/src/main/java/com/zeapo/pwdstore/git/GitServerConfigActivity.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*/
55
package com.zeapo.pwdstore.git
66

7+
import android.content.Context
8+
import android.content.Intent
79
import android.os.Bundle
810
import android.os.Handler
911
import android.view.MenuItem
@@ -42,7 +44,7 @@ class GitServerConfigActivity : BaseGitActivity() {
4244

4345
override fun onCreate(savedInstanceState: Bundle?) {
4446
super.onCreate(savedInstanceState)
45-
val isClone = intent?.extras?.getInt(REQUEST_ARG_OP) ?: -1 == REQUEST_CLONE
47+
val isClone = intent?.extras?.getBoolean("cloning") ?: false
4648
if (isClone) {
4749
binding.saveButton.text = getString(R.string.clone_button)
4850
}
@@ -151,7 +153,7 @@ class GitServerConfigActivity : BaseGitActivity() {
151153
localDir.deleteRecursively()
152154
}
153155
snackbar.dismiss()
154-
launchGitOperation(REQUEST_CLONE).fold(
156+
launchGitOperation(GitOp.CLONE).fold(
155157
success = {
156158
setResult(RESULT_OK)
157159
finish()
@@ -185,14 +187,22 @@ class GitServerConfigActivity : BaseGitActivity() {
185187
MaterialAlertDialogBuilder(this).setMessage(e.message).show()
186188
}
187189
lifecycleScope.launch {
188-
launchGitOperation(REQUEST_CLONE).fold(
190+
launchGitOperation(GitOp.CLONE).fold(
189191
success = {
190192
setResult(RESULT_OK)
191193
finish()
192194
},
193-
failure = ::promptOnErrorHandler,
195+
failure = { promptOnErrorHandler(it) },
194196
)
195197
}
196198
}
197199
}
200+
201+
companion object {
202+
fun createCloneIntent(context: Context): Intent {
203+
return Intent(context, GitServerConfigActivity::class.java).apply {
204+
putExtra("cloning", true)
205+
}
206+
}
207+
}
198208
}

app/src/main/java/com/zeapo/pwdstore/git/operation/GitOperation.kt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,4 @@ abstract class GitOperation(protected val callingActivity: FragmentActivity) {
202202
sshSessionFactory?.close()
203203
}
204204
}
205-
206-
companion object {
207-
208-
const val GET_SSH_KEY_FROM_CLONE = 201
209-
}
210205
}

0 commit comments

Comments
 (0)