summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarsh Shandilya <me@msfjarvis.dev>2020-10-02 15:48:26 +0530
committerHarsh Shandilya <me@msfjarvis.dev>2020-10-02 15:51:14 +0530
commitcf03c554785ee822be3408edcfb81fa4cf03d0e5 (patch)
treef503c31d5e5041dc92dccfa7f2d2b836edce662d
parentd792fa5135897a57383fbd147c369edc646fa817 (diff)
all: refactor ActivityResultContracts usages to adhere to API requirements
The newest versions of AndroidX Activity and Fragments correctly enforce the requirement for all contracts to be registered at class init or before the lifecycle has reached `Lifecycle.State.STARTED`. To comply with these requirements, move all instances of `registerForActivityResult` being called at arbitrary points in the code to be done at class init. Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt182
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/UserPreference.kt209
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt24
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt14
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt90
-rw-r--r--app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt48
6 files changed, 300 insertions, 267 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt
index fc14d805..b7ada287 100644
--- a/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/PasswordStore.kt
@@ -85,6 +85,97 @@ class PasswordStore : BaseGitActivity() {
ViewModelProvider.AndroidViewModelFactory(application)
}
+ private val storagePermissionRequest = registerForActivityResult(RequestPermission()) { granted ->
+ if (granted) checkLocalRepository()
+ }
+
+ private val directorySelectAction = registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ checkLocalRepository()
+ }
+ }
+
+ private val listRefreshAction = registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ refreshPasswordList()
+ }
+ }
+
+ private val passwordMoveAction = registerForActivityResult(StartActivityForResult()) { result ->
+ val intentData = result.data ?: return@registerForActivityResult
+ val filesToMove = requireNotNull(intentData.getStringArrayExtra("Files"))
+ val target = File(requireNotNull(intentData.getStringExtra("SELECTED_FOLDER_PATH")))
+ val repositoryPath = getRepositoryDirectory().absolutePath
+ if (!target.isDirectory) {
+ e { "Tried moving passwords to a non-existing folder." }
+ return@registerForActivityResult
+ }
+
+ d { "Moving passwords to ${intentData.getStringExtra("SELECTED_FOLDER_PATH")}" }
+ d { filesToMove.joinToString(", ") }
+
+ lifecycleScope.launch(Dispatchers.IO) {
+ for (file in filesToMove) {
+ val source = File(file)
+ if (!source.exists()) {
+ e { "Tried moving something that appears non-existent." }
+ continue
+ }
+ val destinationFile = File(target.absolutePath + "/" + source.name)
+ val basename = source.nameWithoutExtension
+ val sourceLongName = getLongName(requireNotNull(source.parent), repositoryPath, basename)
+ val destinationLongName = getLongName(target.absolutePath, repositoryPath, basename)
+ if (destinationFile.exists()) {
+ e { "Trying to move a file that already exists." }
+ withContext(Dispatchers.Main) {
+ MaterialAlertDialogBuilder(this@PasswordStore)
+ .setTitle(resources.getString(R.string.password_exists_title))
+ .setMessage(resources.getString(
+ R.string.password_exists_message,
+ destinationLongName,
+ sourceLongName)
+ )
+ .setPositiveButton(R.string.dialog_ok) { _, _ ->
+ launch(Dispatchers.IO) {
+ moveFile(source, destinationFile)
+ }
+ }
+ .setNegativeButton(R.string.dialog_cancel, null)
+ .show()
+ }
+ } else {
+ launch(Dispatchers.IO) {
+ moveFile(source, destinationFile)
+ }
+ }
+ }
+ when (filesToMove.size) {
+ 1 -> {
+ val source = File(filesToMove[0])
+ val basename = source.nameWithoutExtension
+ val sourceLongName = getLongName(requireNotNull(source.parent), repositoryPath, basename)
+ val destinationLongName = getLongName(target.absolutePath, repositoryPath, basename)
+ withContext(Dispatchers.Main) {
+ commitChange(
+ resources.getString(R.string.git_commit_move_text, sourceLongName, destinationLongName),
+ )
+ }
+ }
+ else -> {
+ val repoDir = getRepositoryDirectory().absolutePath
+ val relativePath = getRelativePath("${target.absolutePath}/", repoDir)
+ withContext(Dispatchers.Main) {
+ commitChange(
+ resources.getString(R.string.git_commit_move_multiple_text, relativePath),
+ )
+ }
+ }
+ }
+ }
+ refreshPasswordList()
+ plist?.dismissActionMode()
+ }
+
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
// open search view on search key, or Ctr+F
if ((keyCode == KeyEvent.KEYCODE_SEARCH || keyCode == KeyEvent.KEYCODE_F && event.isCtrlPressed) &&
@@ -288,9 +379,7 @@ class PasswordStore : BaseGitActivity() {
Snackbar.LENGTH_INDEFINITE
).run {
setAction(getString(R.string.snackbar_action_grant)) {
- registerForActivityResult(RequestPermission()) { granted ->
- if (granted) checkLocalRepository()
- }.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ storagePermissionRequest.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
dismiss()
}
show()
@@ -305,11 +394,7 @@ class PasswordStore : BaseGitActivity() {
private fun checkLocalRepository() {
val repo = initialize()
if (repo == null) {
- registerForActivityResult(StartActivityForResult()) { result ->
- if (result.resultCode == RESULT_OK) {
- checkLocalRepository()
- }
- }.launch(UserPreference.createDirectorySelectionIntent(this))
+ directorySelectAction.launch(UserPreference.createDirectorySelectionIntent(this))
} else {
checkLocalRepository(getRepositoryDirectory())
}
@@ -422,11 +507,7 @@ class PasswordStore : BaseGitActivity() {
val intent = Intent(this, PasswordCreationActivity::class.java)
intent.putExtra("FILE_PATH", currentDir.absolutePath)
intent.putExtra("REPO_PATH", getRepositoryDirectory().absolutePath)
- registerForActivityResult(StartActivityForResult()) { result ->
- if (result.resultCode == RESULT_OK) {
- refreshPasswordList()
- }
- }.launch(intent)
+ listRefreshAction.launch(intent)
}
fun createFolder() {
@@ -477,80 +558,7 @@ class PasswordStore : BaseGitActivity() {
val intent = Intent(this, SelectFolderActivity::class.java)
val fileLocations = values.map { it.file.absolutePath }.toTypedArray()
intent.putExtra("Files", fileLocations)
- registerForActivityResult(StartActivityForResult()) { result ->
- val intentData = result.data ?: return@registerForActivityResult
- val filesToMove = requireNotNull(intentData.getStringArrayExtra("Files"))
- val target = File(requireNotNull(intentData.getStringExtra("SELECTED_FOLDER_PATH")))
- val repositoryPath = getRepositoryDirectory().absolutePath
- if (!target.isDirectory) {
- e { "Tried moving passwords to a non-existing folder." }
- return@registerForActivityResult
- }
-
- d { "Moving passwords to ${intentData.getStringExtra("SELECTED_FOLDER_PATH")}" }
- d { filesToMove.joinToString(", ") }
-
- lifecycleScope.launch(Dispatchers.IO) {
- for (file in filesToMove) {
- val source = File(file)
- if (!source.exists()) {
- e { "Tried moving something that appears non-existent." }
- continue
- }
- val destinationFile = File(target.absolutePath + "/" + source.name)
- val basename = source.nameWithoutExtension
- val sourceLongName = getLongName(requireNotNull(source.parent), repositoryPath, basename)
- val destinationLongName = getLongName(target.absolutePath, repositoryPath, basename)
- if (destinationFile.exists()) {
- e { "Trying to move a file that already exists." }
- withContext(Dispatchers.Main) {
- MaterialAlertDialogBuilder(this@PasswordStore)
- .setTitle(resources.getString(R.string.password_exists_title))
- .setMessage(resources.getString(
- R.string.password_exists_message,
- destinationLongName,
- sourceLongName)
- )
- .setPositiveButton(R.string.dialog_ok) { _, _ ->
- launch(Dispatchers.IO) {
- moveFile(source, destinationFile)
- }
- }
- .setNegativeButton(R.string.dialog_cancel, null)
- .show()
- }
- } else {
- launch(Dispatchers.IO) {
- moveFile(source, destinationFile)
- }
- }
- }
- when (filesToMove.size) {
- 1 -> {
- val source = File(filesToMove[0])
- val basename = source.nameWithoutExtension
- val sourceLongName = getLongName(requireNotNull(source.parent), repositoryPath, basename)
- val destinationLongName = getLongName(target.absolutePath, repositoryPath, basename)
- withContext(Dispatchers.Main) {
- commitChange(
- resources.getString(R.string.git_commit_move_text, sourceLongName, destinationLongName),
- )
- }
- }
- else -> {
- val repoDir = getRepositoryDirectory().absolutePath
- val relativePath = getRelativePath("${target.absolutePath}/", repoDir)
- withContext(Dispatchers.Main) {
- commitChange(
- resources.getString(R.string.git_commit_move_multiple_text, relativePath),
- )
- }
- }
- }
- }
- refreshPasswordList()
- plist?.dismissActionMode()
- }.launch(intent)
+ passwordMoveAction.launch(intent)
}
enum class CategoryRenameError(val resource: Int) {
diff --git a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
index 62ce8b46..45915213 100644
--- a/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/UserPreference.kt
@@ -65,6 +65,106 @@ typealias ChangeListener = Preference.OnPreferenceChangeListener
class UserPreference : AppCompatActivity() {
private lateinit var prefsFragment: PrefsFragment
+ private var fromIntent = false
+
+ @Suppress("DEPRECATION")
+ private val directorySelectAction = registerForActivityResult(OpenDocumentTree()) { uri: Uri? ->
+ if (uri == null) return@registerForActivityResult
+
+ tag(TAG).d { "Selected repository URI is $uri" }
+ // TODO: This is fragile. Workaround until PasswordItem is backed by DocumentFile
+ val docId = DocumentsContract.getTreeDocumentId(uri)
+ val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
+ val path = if (split.size > 1) split[1] else split[0]
+ val repoPath = "${Environment.getExternalStorageDirectory()}/$path"
+ val prefs = sharedPrefs
+
+ tag(TAG).d { "Selected repository path is $repoPath" }
+
+ if (Environment.getExternalStorageDirectory().path == repoPath) {
+ MaterialAlertDialogBuilder(this)
+ .setTitle(getString(R.string.sdcard_root_warning_title))
+ .setMessage(getString(R.string.sdcard_root_warning_message))
+ .setPositiveButton("Remove everything") { _, _ ->
+ prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, uri.path) }
+ }
+ .setNegativeButton(R.string.dialog_cancel, null)
+ .show()
+ }
+ prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, repoPath) }
+ if (fromIntent) {
+ setResult(RESULT_OK)
+ finish()
+ }
+
+ }
+
+ private val sshKeyImportAction = registerForActivityResult(OpenDocument()) { uri: Uri? ->
+ if (uri == null) return@registerForActivityResult
+ runCatching {
+ SshKey.import(uri)
+
+ Toast.makeText(this, resources.getString(R.string.ssh_key_success_dialog_title), Toast.LENGTH_LONG).show()
+ setResult(RESULT_OK)
+ finish()
+ }.onFailure { e ->
+ MaterialAlertDialogBuilder(this)
+ .setTitle(resources.getString(R.string.ssh_key_error_dialog_title))
+ .setMessage(e.message)
+ .setPositiveButton(resources.getString(R.string.dialog_ok), null)
+ .show()
+ }
+ }
+
+ private val storeExportAction = registerForActivityResult(object : 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(applicationContext, uri)
+
+ if (targetDirectory != null) {
+ val service = Intent(applicationContext, PasswordExportService::class.java).apply {
+ action = PasswordExportService.ACTION_EXPORT_PASSWORD
+ putExtra("uri", uri)
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ startForegroundService(service)
+ } else {
+ startService(service)
+ }
+ }
+ }
+
+ private val storeCustomXkpwdDictionaryAction = registerForActivityResult(OpenDocument()) { uri ->
+ if (uri == null) return@registerForActivityResult
+
+ Toast.makeText(
+ this,
+ this.resources.getString(R.string.xkpwgen_custom_dict_imported, uri.path),
+ Toast.LENGTH_SHORT
+ ).show()
+
+ sharedPrefs.edit { putString(PreferenceKeys.PREF_KEY_CUSTOM_DICT, uri.toString()) }
+
+ val customDictPref = prefsFragment.findPreference<Preference>(PreferenceKeys.PREF_KEY_CUSTOM_DICT)
+ setCustomDictSummary(customDictPref, uri)
+ // copy user selected file to internal storage
+ val inputStream = contentResolver.openInputStream(uri)
+ val customDictFile = File(filesDir.toString(), XkpwdDictionary.XKPWD_CUSTOM_DICT_FILE).outputStream()
+ inputStream?.copyTo(customDictFile, 1024)
+ inputStream?.close()
+ customDictFile.close()
+
+ setResult(RESULT_OK)
+ }
class PrefsFragment : PreferenceFragmentCompat() {
@@ -471,7 +571,10 @@ class UserPreference : AppCompatActivity() {
when (intent?.getStringExtra("operation")) {
"get_ssh_key" -> getSshKey()
"make_ssh_key" -> makeSshKey(false)
- "git_external" -> selectExternalGitRepository(fromIntent = true)
+ "git_external" -> {
+ fromIntent = true
+ selectExternalGitRepository()
+ }
}
prefsFragment = PrefsFragment()
@@ -484,41 +587,12 @@ class UserPreference : AppCompatActivity() {
}
@Suppress("Deprecation") // for Environment.getExternalStorageDirectory()
- fun selectExternalGitRepository(fromIntent: Boolean = false) {
+ fun selectExternalGitRepository() {
MaterialAlertDialogBuilder(this)
.setTitle(this.resources.getString(R.string.external_repository_dialog_title))
.setMessage(this.resources.getString(R.string.external_repository_dialog_text))
.setPositiveButton(R.string.dialog_ok) { _, _ ->
- registerForActivityResult(OpenDocumentTree()) { uri: Uri? ->
- if (uri == null) return@registerForActivityResult
-
- tag(TAG).d { "Selected repository URI is $uri" }
- // TODO: This is fragile. Workaround until PasswordItem is backed by DocumentFile
- val docId = DocumentsContract.getTreeDocumentId(uri)
- val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
- val path = if (split.size > 1) split[1] else split[0]
- val repoPath = "${Environment.getExternalStorageDirectory()}/$path"
- val prefs = sharedPrefs
-
- tag(TAG).d { "Selected repository path is $repoPath" }
-
- if (Environment.getExternalStorageDirectory().path == repoPath) {
- MaterialAlertDialogBuilder(this)
- .setTitle(getString(R.string.sdcard_root_warning_title))
- .setMessage(getString(R.string.sdcard_root_warning_message))
- .setPositiveButton("Remove everything") { _, _ ->
- prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, uri.path) }
- }
- .setNegativeButton(R.string.dialog_cancel, null)
- .show()
- }
- prefs.edit { putString(PreferenceKeys.GIT_EXTERNAL_REPO, repoPath) }
- if (fromIntent) {
- setResult(RESULT_OK)
- finish()
- }
-
- }.launch(null)
+ directorySelectAction.launch(null)
}
.setNegativeButton(R.string.dialog_cancel, null)
.show()
@@ -539,26 +613,7 @@ class UserPreference : AppCompatActivity() {
}
private fun importSshKey() {
- registerForActivityResult(OpenDocument()) { uri: Uri? ->
- if (uri == null) return@registerForActivityResult
- runCatching {
- SshKey.import(uri)
-
- Toast.makeText(
- this,
- this.resources.getString(R.string.ssh_key_success_dialog_title),
- Toast.LENGTH_LONG
- ).show()
- setResult(RESULT_OK)
- finish()
- }.onFailure { e ->
- MaterialAlertDialogBuilder(this)
- .setTitle(resources.getString(R.string.ssh_key_error_dialog_title))
- .setMessage(e.message)
- .setPositiveButton(resources.getString(R.string.dialog_ok), null)
- .show()
- }
- }.launch(arrayOf("*/*"))
+ sshKeyImportAction.launch(arrayOf("*/*"))
}
/**
@@ -584,32 +639,7 @@ class UserPreference : AppCompatActivity() {
* Exports the passwords
*/
private fun exportPasswords() {
- registerForActivityResult(object : 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(applicationContext, uri)
-
- if (targetDirectory != null) {
- val service = Intent(applicationContext, PasswordExportService::class.java).apply {
- action = PasswordExportService.ACTION_EXPORT_PASSWORD
- putExtra("uri", uri)
- }
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- startForegroundService(service)
- } else {
- startService(service)
- }
- }
- }.launch(null)
+ storeExportAction.launch(null)
}
/**
@@ -628,28 +658,7 @@ class UserPreference : AppCompatActivity() {
* Pick custom xkpwd dictionary from sdcard
*/
private fun storeCustomDictionaryPath() {
- registerForActivityResult(OpenDocument()) { uri ->
- if (uri == null) return@registerForActivityResult
-
- Toast.makeText(
- this,
- this.resources.getString(R.string.xkpwgen_custom_dict_imported, uri.path),
- Toast.LENGTH_SHORT
- ).show()
-
- sharedPrefs.edit { putString(PreferenceKeys.PREF_KEY_CUSTOM_DICT, uri.toString()) }
-
- val customDictPref = prefsFragment.findPreference<Preference>(PreferenceKeys.PREF_KEY_CUSTOM_DICT)
- setCustomDictSummary(customDictPref, uri)
- // copy user selected file to internal storage
- val inputStream = contentResolver.openInputStream(uri)
- val customDictFile = File(filesDir.toString(), XkpwdDictionary.XKPWD_CUSTOM_DICT_FILE).outputStream()
- inputStream?.copyTo(customDictFile, 1024)
- inputStream?.close()
- customDictFile.close()
-
- setResult(RESULT_OK)
- }.launch(arrayOf("*/*"))
+ storeCustomXkpwdDictionaryAction.launch(arrayOf("*/*"))
}
private val isAccessibilityServiceEnabled: Boolean
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt
index 9bab9e6f..a5bdcfe0 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillDecryptActivity.kt
@@ -81,6 +81,18 @@ class AutofillDecryptActivity : AppCompatActivity(), CoroutineScope {
}
}
+ private val decryptInteractionRequiredAction = registerForActivityResult(StartIntentSenderForResult()) { result ->
+ if (continueAfterUserInteraction != null) {
+ val data = result.data
+ if (result.resultCode == RESULT_OK && data != null) {
+ continueAfterUserInteraction?.resume(data)
+ } else {
+ continueAfterUserInteraction?.resumeWithException(Exception("OpenPgpApi ACTION_DECRYPT_VERIFY failed to continue after user interaction"))
+ }
+ continueAfterUserInteraction = null
+ }
+ }
+
private var continueAfterUserInteraction: Continuation<Intent>? = null
private lateinit var directoryStructure: DirectoryStructure
@@ -198,17 +210,7 @@ class AutofillDecryptActivity : AppCompatActivity(), CoroutineScope {
val intentToResume = withContext(Dispatchers.Main) {
suspendCoroutine<Intent> { cont ->
continueAfterUserInteraction = cont
- registerForActivityResult(StartIntentSenderForResult()) { result ->
- if (continueAfterUserInteraction != null) {
- val data = result.data
- if (result.resultCode == RESULT_OK && data != null) {
- continueAfterUserInteraction?.resume(data)
- } else {
- continueAfterUserInteraction?.resumeWithException(Exception("OpenPgpApi ACTION_DECRYPT_VERIFY failed to continue after user interaction"))
- }
- continueAfterUserInteraction = null
- }
- }.launch(IntentSenderRequest.Builder(pendingIntent.intentSender).build())
+ decryptInteractionRequiredAction.launch(IntentSenderRequest.Builder(pendingIntent.intentSender).build())
}
}
decryptCredential(file, intentToResume)
diff --git a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt
index 95e49fdd..f22c6596 100644
--- a/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/autofill/oreo/ui/AutofillFilterActivity.kt
@@ -79,6 +79,13 @@ class AutofillFilterView : AppCompatActivity() {
ViewModelProvider.AndroidViewModelFactory(application)
}
+ private val decryptAction = registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ setResult(RESULT_OK, result.data)
+ }
+ finish()
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
@@ -197,12 +204,7 @@ class AutofillFilterView : AppCompatActivity() {
item.file
)
// intent?.extras? is checked to be non-null in onCreate
- registerForActivityResult(StartActivityForResult()) { result ->
- if (result.resultCode == RESULT_OK) {
- setResult(RESULT_OK, result.data)
- }
- finish()
- }.launch(AutofillDecryptActivity.makeDecryptFileIntent(
+ decryptAction.launch(AutofillDecryptActivity.makeDecryptFileIntent(
item.file,
intent!!.extras!!,
this
diff --git a/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt b/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt
index eb1303fc..d0998d6d 100644
--- a/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/crypto/PasswordCreationActivity.kt
@@ -47,6 +47,7 @@ import java.io.File
import java.io.IOException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
import me.msfjarvis.openpgpktx.util.OpenPgpApi
import me.msfjarvis.openpgpktx.util.OpenPgpServiceConnection
import me.msfjarvis.openpgpktx.util.OpenPgpUtils
@@ -63,6 +64,7 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB
private val oldFileName by lazy { intent.getStringExtra(EXTRA_FILE_NAME) }
private var oldCategory: String? = null
private var copy: Boolean = false
+ private var encryptionIntent: Intent = Intent()
private val userInteractionRequiredResult = registerForActivityResult(StartIntentSenderForResult()) { result ->
if (result.data == null) {
@@ -80,6 +82,41 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB
}
}
+ private val otpImportAction = registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ binding.otpImportButton.isVisible = false
+ val intentResult = IntentIntegrator.parseActivityResult(RESULT_OK, result.data)
+ val contents = "${intentResult.contents}\n"
+ val currentExtras = binding.extraContent.text.toString()
+ if (currentExtras.isNotEmpty() && currentExtras.last() != '\n')
+ binding.extraContent.append("\n$contents")
+ else
+ binding.extraContent.append(contents)
+ snackbar(message = getString(R.string.otp_import_success))
+ } else {
+ snackbar(message = getString(R.string.otp_import_failure))
+ }
+ }
+
+ private val gpgKeySelectAction = registerForActivityResult(StartActivityForResult()) { result ->
+ if (result.resultCode == RESULT_OK) {
+ result.data?.getStringArrayExtra(OpenPgpApi.EXTRA_KEY_IDS)?.let { keyIds ->
+ lifecycleScope.launch {
+ val gpgIdentifierFile = File(PasswordRepository.getRepositoryDirectory(), ".gpg-id")
+ withContext(Dispatchers.IO) {
+ gpgIdentifierFile.writeText(keyIds.joinToString("\n"))
+ }
+ commitChange(getString(
+ R.string.git_commit_gpg_id,
+ getLongName(gpgIdentifierFile.parentFile!!.absolutePath, repoPath, gpgIdentifierFile.name)
+ )).onSuccess {
+ encrypt(encryptionIntent)
+ }
+ }
+ }
+ }
+ }
+
private fun File.findTillRoot(fileName: String, rootPath: File): File? {
val gpgFile = File(this, fileName)
if (gpgFile.exists()) return gpgFile
@@ -107,26 +144,11 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB
setContentView(root)
generatePassword.setOnClickListener { generatePassword() }
otpImportButton.setOnClickListener {
- registerForActivityResult(StartActivityForResult()) { result ->
- if (result.resultCode == RESULT_OK) {
- otpImportButton.isVisible = false
- val intentResult = IntentIntegrator.parseActivityResult(RESULT_OK, result.data)
- val contents = "${intentResult.contents}\n"
- val currentExtras = extraContent.text.toString()
- if (currentExtras.isNotEmpty() && currentExtras.last() != '\n')
- extraContent.append("\n$contents")
- else
- extraContent.append(contents)
- snackbar(message = getString(R.string.otp_import_success))
- } else {
- snackbar(message = getString(R.string.otp_import_failure))
- }
- }.launch(
- IntentIntegrator(this@PasswordCreationActivity)
- .setOrientationLocked(false)
- .setBeepEnabled(false)
- .setDesiredBarcodeFormats(QR_CODE)
- .createScanIntent()
+ otpImportAction.launch(IntentIntegrator(this@PasswordCreationActivity)
+ .setOrientationLocked(false)
+ .setBeepEnabled(false)
+ .setDesiredBarcodeFormats(QR_CODE)
+ .createScanIntent()
)
}
@@ -307,8 +329,8 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB
copyPasswordToClipboard(editPass)
}
- val data = receivedIntent ?: Intent()
- data.action = OpenPgpApi.ACTION_ENCRYPT
+ encryptionIntent = receivedIntent ?: Intent()
+ encryptionIntent.action = OpenPgpApi.ACTION_ENCRYPT
// pass enters the key ID into `.gpg-id`.
val repoRoot = PasswordRepository.getRepositoryDirectory()
@@ -333,33 +355,19 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB
}
}
if (gpgIdentifiers.isEmpty()) {
- registerForActivityResult(StartActivityForResult()) { result ->
- if (result.resultCode == RESULT_OK) {
- result.data?.getStringArrayExtra(OpenPgpApi.EXTRA_KEY_IDS)?.let { keyIds ->
- gpgIdentifierFile.writeText(keyIds.joinToString("\n"))
- lifecycleScope.launch {
- commitChange(getString(
- R.string.git_commit_gpg_id,
- getLongName(gpgIdentifierFile.parentFile!!.absolutePath, repoPath, gpgIdentifierFile.name)
- )).onSuccess {
- encrypt(data)
- }
- }
- }
- }
- }.launch(Intent(this@PasswordCreationActivity, GetKeyIdsActivity::class.java))
+ gpgKeySelectAction.launch(Intent(this@PasswordCreationActivity, GetKeyIdsActivity::class.java))
return@with
}
val keyIds = gpgIdentifiers.filterIsInstance<GpgIdentifier.KeyId>().map { it.id }.toLongArray()
if (keyIds.isNotEmpty()) {
- data.putExtra(OpenPgpApi.EXTRA_KEY_IDS, keyIds)
+ encryptionIntent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, keyIds)
}
val userIds = gpgIdentifiers.filterIsInstance<GpgIdentifier.UserId>().map { it.email }.toTypedArray()
if (userIds.isNotEmpty()) {
- data.putExtra(OpenPgpApi.EXTRA_USER_IDS, userIds)
+ encryptionIntent.putExtra(OpenPgpApi.EXTRA_USER_IDS, userIds)
}
- data.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true)
+ encryptionIntent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true)
val content = "$editPass\n$editExtra"
val inputStream = ByteArrayInputStream(content.toByteArray())
@@ -386,7 +394,7 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB
}
lifecycleScope.launch(Dispatchers.IO) {
- api?.executeApiAsync(data, inputStream, outputStream) { result ->
+ api?.executeApiAsync(encryptionIntent, inputStream, outputStream) { result ->
when (result?.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
OpenPgpApi.RESULT_CODE_SUCCESS -> {
runCatching {
diff --git a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt b/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt
index 1eb1c95d..c06a6d63 100644
--- a/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt
+++ b/app/src/main/java/com/zeapo/pwdstore/ui/dialogs/FolderCreationDialogFragment.kt
@@ -31,6 +31,30 @@ import me.msfjarvis.openpgpktx.util.OpenPgpApi
class FolderCreationDialogFragment : DialogFragment() {
+ private lateinit var newFolder: File
+
+ private val keySelectAction = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == AppCompatActivity.RESULT_OK) {
+ result.data?.getStringArrayExtra(OpenPgpApi.EXTRA_KEY_IDS)?.let { keyIds ->
+ val gpgIdentifierFile = File(newFolder, ".gpg-id")
+ gpgIdentifierFile.writeText(keyIds.joinToString("\n"))
+ val repo = PasswordRepository.getRepository(null)
+ if (repo != null) {
+ lifecycleScope.launch {
+ val repoPath = getRepositoryDirectory().absolutePath
+ requireActivity().commitChange(
+ getString(
+ R.string.git_commit_gpg_id,
+ BasePgpActivity.getLongName(gpgIdentifierFile.parentFile!!.absolutePath, repoPath, gpgIdentifierFile.name)
+ ),
+ )
+ dismiss()
+ }
+ }
+ }
+ }
+ }
+
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val alertDialogBuilder = MaterialAlertDialogBuilder(requireContext())
alertDialogBuilder.setTitle(R.string.title_create_folder)
@@ -53,7 +77,7 @@ class FolderCreationDialogFragment : DialogFragment() {
val dialog = requireDialog()
val folderNameView = dialog.findViewById<TextInputEditText>(R.id.folder_name_text)
val folderNameViewContainer = dialog.findViewById<TextInputLayout>(R.id.folder_name_container)
- val newFolder = File("$currentDir/${folderNameView.text}")
+ newFolder = File("$currentDir/${folderNameView.text}")
folderNameViewContainer.error = when {
newFolder.isFile -> getString(R.string.folder_creation_err_file_exists)
newFolder.isDirectory -> getString(R.string.folder_creation_err_folder_exists)
@@ -63,27 +87,7 @@ class FolderCreationDialogFragment : DialogFragment() {
newFolder.mkdirs()
(requireActivity() as PasswordStore).refreshPasswordList(newFolder)
if (dialog.findViewById<MaterialCheckBox>(R.id.set_gpg_key).isChecked) {
- val gpgIdentifierFile = File(newFolder, ".gpg-id")
- registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
- if (result.resultCode == AppCompatActivity.RESULT_OK) {
- result.data?.getStringArrayExtra(OpenPgpApi.EXTRA_KEY_IDS)?.let { keyIds ->
- gpgIdentifierFile.writeText(keyIds.joinToString("\n"))
- val repo = PasswordRepository.getRepository(null)
- if (repo != null) {
- lifecycleScope.launch {
- val repoPath = getRepositoryDirectory().absolutePath
- requireActivity().commitChange(
- getString(
- R.string.git_commit_gpg_id,
- BasePgpActivity.getLongName(gpgIdentifierFile.parentFile!!.absolutePath, repoPath, gpgIdentifierFile.name)
- ),
- )
- dismiss()
- }
- }
- }
- }
- }.launch(Intent(requireContext(), GetKeyIdsActivity::class.java))
+ keySelectAction.launch(Intent(requireContext(), GetKeyIdsActivity::class.java))
return
} else {
dismiss()