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>
(cherry picked from commit cf03c55478)
This commit is contained in:
Harsh Shandilya 2020-10-02 15:48:26 +05:30
parent 8355db86f5
commit c70c1792f6
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
6 changed files with 300 additions and 267 deletions

View file

@ -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) {

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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,22 +144,7 @@ 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)
otpImportAction.launch(IntentIntegrator(this@PasswordCreationActivity)
.setOrientationLocked(false)
.setBeepEnabled(false)
.setDesiredBarcodeFormats(QR_CODE)
@ -306,8 +328,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()
@ -329,33 +351,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())
@ -382,7 +390,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 {

View file

@ -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()