From aaf6ceb8ecbc71f6948c84b1a19fb83abfe8a418 Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Mon, 25 Apr 2022 10:47:02 +0530 Subject: all: reformat with ktfmt 0.36 --- .../aps/ui/autofill/AutofillDecryptActivity.kt | 44 ++--- .../aps/ui/autofill/AutofillDecryptActivityV2.kt | 24 +-- .../aps/ui/autofill/AutofillFilterView.kt | 44 ++--- .../autofill/AutofillPublisherChangedActivity.kt | 39 ++-- .../dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt | 54 +++--- .../msfjarvis/aps/ui/crypto/GetKeyIdsActivity.kt | 18 +- .../aps/ui/crypto/PasswordCreationActivity.kt | 197 +++++++++++---------- .../aps/ui/crypto/PasswordCreationActivityV2.kt | 161 ++++++++--------- .../ui/dialogs/PasswordGeneratorDialogFragment.kt | 33 ++-- .../aps/ui/folderselect/SelectFolderFragment.kt | 19 +- .../aps/ui/git/config/GitConfigActivity.kt | 23 ++- .../aps/ui/git/config/GitServerConfigActivity.kt | 42 ++--- .../aps/ui/onboarding/fragments/CloneFragment.kt | 12 +- .../msfjarvis/aps/ui/passwords/PasswordFragment.kt | 40 ++--- .../msfjarvis/aps/ui/passwords/PasswordStore.kt | 9 +- .../aps/ui/proxy/ProxySelectorActivity.kt | 35 ++-- .../aps/ui/settings/RepositorySettings.kt | 6 +- .../aps/ui/sshkeygen/SshKeyImportActivity.kt | 20 +-- 18 files changed, 415 insertions(+), 405 deletions(-) (limited to 'app/src/main/java/dev/msfjarvis/aps/ui') diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivity.kt index 291c654f..bd3141a8 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivity.kt @@ -200,18 +200,18 @@ class AutofillDecryptActivity : AppCompatActivity() { ) { OpenPgpApi.RESULT_CODE_SUCCESS -> { runCatching { - val entry = - withContext(Dispatchers.IO) { - @Suppress("BlockingMethodInNonBlockingContext") - passwordEntryFactory.create(decryptedOutput.toByteArray()) - } - AutofillPreferences.credentialsFromStoreEntry( - this, - file, - entry, - directoryStructure - ) - } + val entry = + withContext(Dispatchers.IO) { + @Suppress("BlockingMethodInNonBlockingContext") + passwordEntryFactory.create(decryptedOutput.toByteArray()) + } + AutofillPreferences.credentialsFromStoreEntry( + this, + file, + entry, + directoryStructure + ) + } .getOrElse { e -> logcat(ERROR) { e.asLog("Failed to parse password entry") } return null @@ -221,17 +221,17 @@ class AutofillDecryptActivity : AppCompatActivity() { val pendingIntent: PendingIntent = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT)!! runCatching { - val intentToResume = - withContext(Dispatchers.Main) { - suspendCoroutine { cont -> - continueAfterUserInteraction = cont - decryptInteractionRequiredAction.launch( - IntentSenderRequest.Builder(pendingIntent.intentSender).build() - ) + val intentToResume = + withContext(Dispatchers.Main) { + suspendCoroutine { cont -> + continueAfterUserInteraction = cont + decryptInteractionRequiredAction.launch( + IntentSenderRequest.Builder(pendingIntent.intentSender).build() + ) + } } - } - decryptCredential(file, intentToResume) - } + decryptCredential(file, intentToResume) + } .getOrElse { e -> logcat(ERROR) { e.asLog("OpenPgpApi ACTION_DECRYPT_VERIFY failed with user interaction") diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivityV2.kt b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivityV2.kt index d7287605..af875e00 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivityV2.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillDecryptActivityV2.kt @@ -150,25 +150,25 @@ class AutofillDecryptActivityV2 : AppCompatActivity() { } .onSuccess { encryptedInput -> runCatching { - withContext(Dispatchers.IO) { - val outputStream = ByteArrayOutputStream() - repository.decrypt( - password, - encryptedInput, - outputStream, - ) - outputStream + withContext(Dispatchers.IO) { + val outputStream = ByteArrayOutputStream() + repository.decrypt( + password, + encryptedInput, + outputStream, + ) + outputStream + } } - } .onFailure { e -> logcat(ERROR) { e.asLog("Decryption failed") } return null } .onSuccess { result -> return runCatching { - val entry = passwordEntryFactory.create(result.toByteArray()) - AutofillPreferences.credentialsFromStoreEntry(this, file, entry, directoryStructure) - } + val entry = passwordEntryFactory.create(result.toByteArray()) + AutofillPreferences.credentialsFromStoreEntry(this, file, entry, directoryStructure) + } .getOrElse { e -> logcat(ERROR) { e.asLog("Failed to parse password entry") } return null diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillFilterView.kt b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillFilterView.kt index 573e5337..6bf238a1 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillFilterView.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillFilterView.kt @@ -149,31 +149,31 @@ class AutofillFilterView : AppCompatActivity() { ::PasswordViewHolder, lifecycleScope, ) { item -> - val file = item.file.relativeTo(item.rootDir) - val pathToIdentifier = directoryStructure.getPathToIdentifierFor(file) - val identifier = directoryStructure.getIdentifierFor(file) - val accountPart = directoryStructure.getAccountPartFor(file) - check(identifier != null || accountPart != null) { - "At least one of identifier and accountPart should always be non-null" - } - title.text = - if (identifier != null) { - buildSpannedString { - if (pathToIdentifier != null) append("$pathToIdentifier/") - bold { underline { append(identifier) } } - } - } else { - accountPart + val file = item.file.relativeTo(item.rootDir) + val pathToIdentifier = directoryStructure.getPathToIdentifierFor(file) + val identifier = directoryStructure.getIdentifierFor(file) + val accountPart = directoryStructure.getAccountPartFor(file) + check(identifier != null || accountPart != null) { + "At least one of identifier and accountPart should always be non-null" } - subtitle.apply { - if (identifier != null && accountPart != null) { - text = accountPart - visibility = View.VISIBLE - } else { - visibility = View.GONE + title.text = + if (identifier != null) { + buildSpannedString { + if (pathToIdentifier != null) append("$pathToIdentifier/") + bold { underline { append(identifier) } } + } + } else { + accountPart + } + subtitle.apply { + if (identifier != null && accountPart != null) { + text = accountPart + visibility = View.VISIBLE + } else { + visibility = View.GONE + } } } - } .onItemClicked { _, item -> decryptAndFill(item) } layoutManager = LinearLayoutManager(context) } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillPublisherChangedActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillPublisherChangedActivity.kt index 794fad8c..b0b5ea9c 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillPublisherChangedActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/autofill/AutofillPublisherChangedActivity.kt @@ -105,27 +105,28 @@ class AutofillPublisherChangedActivity : AppCompatActivity() { private fun showPackageInfo() { runCatching { - with(binding) { - val packageInfo = packageManager.getPackageInfo(appPackage, PackageManager.GET_META_DATA) - val installTime = DateUtils.getRelativeTimeSpanString(packageInfo.firstInstallTime) - warningAppInstallDate.text = - getString(R.string.oreo_autofill_warning_publisher_install_time, installTime) - val appInfo = packageManager.getApplicationInfo(appPackage, PackageManager.GET_META_DATA) - warningAppName.text = - getString( - R.string.oreo_autofill_warning_publisher_app_name, - packageManager.getApplicationLabel(appInfo) - ) + with(binding) { + val packageInfo = packageManager.getPackageInfo(appPackage, PackageManager.GET_META_DATA) + val installTime = DateUtils.getRelativeTimeSpanString(packageInfo.firstInstallTime) + warningAppInstallDate.text = + getString(R.string.oreo_autofill_warning_publisher_install_time, installTime) + val appInfo = packageManager.getApplicationInfo(appPackage, PackageManager.GET_META_DATA) + warningAppName.text = + getString( + R.string.oreo_autofill_warning_publisher_app_name, + packageManager.getApplicationLabel(appInfo) + ) - val currentHash = computeCertificatesHash(this@AutofillPublisherChangedActivity, appPackage) - warningAppAdvancedInfo.text = - getString( - R.string.oreo_autofill_warning_publisher_advanced_info_template, - appPackage, - currentHash - ) + val currentHash = + computeCertificatesHash(this@AutofillPublisherChangedActivity, appPackage) + warningAppAdvancedInfo.text = + getString( + R.string.oreo_autofill_warning_publisher_advanced_info_template, + appPackage, + currentHash + ) + } } - } .onFailure { e -> logcat(ERROR) { e.asLog("Failed to retrieve package info for $appPackage") } finish() diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt index 77abde2a..af9a4ddd 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt @@ -178,42 +178,42 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound { OpenPgpApi.RESULT_CODE_SUCCESS -> { startAutoDismissTimer() runCatching { - val showPassword = settings.getBoolean(PreferenceKeys.SHOW_PASSWORD, true) - val entry = passwordEntryFactory.create(outputStream.toByteArray()) + val showPassword = settings.getBoolean(PreferenceKeys.SHOW_PASSWORD, true) + val entry = passwordEntryFactory.create(outputStream.toByteArray()) - if (settings.getBoolean(PreferenceKeys.COPY_ON_DECRYPT, false)) { - copyPasswordToClipboard(entry.password) - } + if (settings.getBoolean(PreferenceKeys.COPY_ON_DECRYPT, false)) { + copyPasswordToClipboard(entry.password) + } - passwordEntry = entry - invalidateOptionsMenu() + passwordEntry = entry + invalidateOptionsMenu() - val items = arrayListOf() - if (!entry.password.isNullOrBlank()) { - items.add(FieldItem.createPasswordField(entry.password!!)) - } + val items = arrayListOf() + if (!entry.password.isNullOrBlank()) { + items.add(FieldItem.createPasswordField(entry.password!!)) + } - if (entry.hasTotp()) { - items.add(FieldItem.createOtpField(entry.totp.first())) - } + if (entry.hasTotp()) { + items.add(FieldItem.createOtpField(entry.totp.first())) + } - if (!entry.username.isNullOrBlank()) { - items.add(FieldItem.createUsernameField(entry.username!!)) - } + if (!entry.username.isNullOrBlank()) { + items.add(FieldItem.createUsernameField(entry.username!!)) + } - entry.extraContent.forEach { (key, value) -> - items.add(FieldItem(key, value, FieldItem.ActionType.COPY)) - } + entry.extraContent.forEach { (key, value) -> + items.add(FieldItem(key, value, FieldItem.ActionType.COPY)) + } - val adapter = - FieldItemAdapter(items, showPassword) { text -> copyTextToClipboard(text) } - binding.recyclerView.adapter = adapter - binding.recyclerView.itemAnimator = null + val adapter = + FieldItemAdapter(items, showPassword) { text -> copyTextToClipboard(text) } + binding.recyclerView.adapter = adapter + binding.recyclerView.itemAnimator = null - if (entry.hasTotp()) { - entry.totp.onEach(adapter::updateOTPCode).launchIn(lifecycleScope) + if (entry.hasTotp()) { + entry.totp.onEach(adapter::updateOTPCode).launchIn(lifecycleScope) + } } - } .onFailure { e -> logcat(ERROR) { e.asLog() } } } OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED -> { diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/GetKeyIdsActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/GetKeyIdsActivity.kt index b24868c9..afd30270 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/GetKeyIdsActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/GetKeyIdsActivity.kt @@ -56,15 +56,15 @@ class GetKeyIdsActivity : BasePgpActivity() { when (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { OpenPgpApi.RESULT_CODE_SUCCESS -> { runCatching { - val ids = - result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS)?.map { - OpenPgpUtils.convertKeyIdToHex(it) - } - ?: emptyList() - val keyResult = Intent().putExtra(OpenPgpApi.EXTRA_KEY_IDS, ids.toTypedArray()) - setResult(RESULT_OK, keyResult) - finish() - } + val ids = + result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS)?.map { + OpenPgpUtils.convertKeyIdToHex(it) + } + ?: emptyList() + val keyResult = Intent().putExtra(OpenPgpApi.EXTRA_KEY_IDS, ids.toTypedArray()) + setResult(RESULT_OK, keyResult) + finish() + } .onFailure { e -> logcat(ERROR) { e.asLog() } } } OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED -> { diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt index 930da5cd..7a9ba54e 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivity.kt @@ -143,15 +143,15 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB val reader = QRCodeReader() runCatching { - val result = reader.decode(binaryBitmap) - val text = result.text - val currentExtras = binding.extraContent.text.toString() - if (currentExtras.isNotEmpty() && currentExtras.last() != '\n') - binding.extraContent.append("\n$text") - else binding.extraContent.append(text) - snackbar(message = getString(R.string.otp_import_success)) - binding.otpImportButton.isVisible = false - } + val result = reader.decode(binaryBitmap) + val text = result.text + val currentExtras = binding.extraContent.text.toString() + if (currentExtras.isNotEmpty() && currentExtras.last() != '\n') + binding.extraContent.append("\n$text") + else binding.extraContent.append(text) + snackbar(message = getString(R.string.otp_import_success)) + binding.otpImportButton.isVisible = false + } .onFailure { snackbar(message = getString(R.string.otp_import_failure)) } } @@ -411,22 +411,25 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB File(repoRoot, directory.text.toString()).findTillRoot(".gpg-id", repoRoot) ?: File(repoRoot, ".gpg-id").apply { createNewFile() } val gpgIdentifiers = - gpgIdentifierFile.readLines().filter { it.isNotBlank() }.map { line -> - GpgIdentifier.fromString(line) - ?: run { - // The line being empty means this is most likely an empty `.gpg-id` - // file - // we created. Skip the validation so we can make the user add a real - // ID. - if (line.isEmpty()) return@run - if (line.removePrefix("0x").matches("[a-fA-F0-9]{8}".toRegex())) { - snackbar(message = resources.getString(R.string.short_key_ids_unsupported)) - } else { - snackbar(message = resources.getString(R.string.invalid_gpg_id)) + gpgIdentifierFile + .readLines() + .filter { it.isNotBlank() } + .map { line -> + GpgIdentifier.fromString(line) + ?: run { + // The line being empty means this is most likely an empty `.gpg-id` + // file + // we created. Skip the validation so we can make the user add a real + // ID. + if (line.isEmpty()) return@run + if (line.removePrefix("0x").matches("[a-fA-F0-9]{8}".toRegex())) { + snackbar(message = resources.getString(R.string.short_key_ids_unsupported)) + } else { + snackbar(message = resources.getString(R.string.invalid_gpg_id)) + } + return@with } - return@with - } - } + } if (gpgIdentifiers.isEmpty()) { gpgKeySelectAction.launch( Intent(this@PasswordCreationActivity, GetKeyIdsActivity::class.java) @@ -480,86 +483,92 @@ class PasswordCreationActivity : BasePgpActivity(), OpenPgpServiceConnection.OnB when (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) { OpenPgpApi.RESULT_CODE_SUCCESS -> { runCatching { - val file = File(path) - // If we're not editing, this file should not already exist! - // Additionally, if we were editing and the incoming and outgoing - // filenames differ, it means we renamed. Ensure that the target - // doesn't already exist to prevent an accidental overwrite. - if ((!editing || (editing && suggestedName != file.nameWithoutExtension)) && - file.exists() - ) { - snackbar(message = getString(R.string.password_creation_duplicate_error)) - return@runCatching - } - - if (!file.isInsideRepository()) { - snackbar(message = getString(R.string.message_error_destination_outside_repo)) - return@runCatching - } + val file = File(path) + // If we're not editing, this file should not already exist! + // Additionally, if we were editing and the incoming and outgoing + // filenames differ, it means we renamed. Ensure that the target + // doesn't already exist to prevent an accidental overwrite. + if ((!editing || (editing && suggestedName != file.nameWithoutExtension)) && + file.exists() + ) { + snackbar(message = getString(R.string.password_creation_duplicate_error)) + return@runCatching + } - withContext(Dispatchers.IO) { - file.outputStream().use { it.write(outputStream.toByteArray()) } - } + if (!file.isInsideRepository()) { + snackbar(message = getString(R.string.message_error_destination_outside_repo)) + return@runCatching + } - // associate the new password name with the last name's timestamp in - // history - val preference = getSharedPreferences("recent_password_history", Context.MODE_PRIVATE) - val oldFilePathHash = "$repoPath/${oldCategory?.trim('/')}/$oldFileName.gpg".base64() - val timestamp = preference.getString(oldFilePathHash) - if (timestamp != null) { - preference.edit { - remove(oldFilePathHash) - putString(file.absolutePath.base64(), timestamp) + withContext(Dispatchers.IO) { + file.outputStream().use { it.write(outputStream.toByteArray()) } } - } - val returnIntent = Intent() - returnIntent.putExtra(RETURN_EXTRA_CREATED_FILE, path) - returnIntent.putExtra(RETURN_EXTRA_NAME, editName) - returnIntent.putExtra( - RETURN_EXTRA_LONG_NAME, - getLongName(fullPath, repoPath, editName) - ) + // associate the new password name with the last name's timestamp in + // history + val preference = + getSharedPreferences("recent_password_history", Context.MODE_PRIVATE) + val oldFilePathHash = + "$repoPath/${oldCategory?.trim('/')}/$oldFileName.gpg".base64() + val timestamp = preference.getString(oldFilePathHash) + if (timestamp != null) { + preference.edit { + remove(oldFilePathHash) + putString(file.absolutePath.base64(), timestamp) + } + } - if (shouldGeneratePassword) { - val directoryStructure = AutofillPreferences.directoryStructure(applicationContext) - val entry = passwordEntryFactory.create(content.encodeToByteArray()) - returnIntent.putExtra(RETURN_EXTRA_PASSWORD, entry.password) - val username = entry.username ?: directoryStructure.getUsernameFor(file) - returnIntent.putExtra(RETURN_EXTRA_USERNAME, username) - } + val returnIntent = Intent() + returnIntent.putExtra(RETURN_EXTRA_CREATED_FILE, path) + returnIntent.putExtra(RETURN_EXTRA_NAME, editName) + returnIntent.putExtra( + RETURN_EXTRA_LONG_NAME, + getLongName(fullPath, repoPath, editName) + ) - if (directoryInputLayout.isVisible && - directoryInputLayout.isEnabled && - oldFileName != null - ) { - val oldFile = File("$repoPath/${oldCategory?.trim('/')}/$oldFileName.gpg") - if (oldFile.path != file.path && !oldFile.delete()) { - setResult(RESULT_CANCELED) - MaterialAlertDialogBuilder(this@PasswordCreationActivity) - .setTitle(R.string.password_creation_file_fail_title) - .setMessage( - getString(R.string.password_creation_file_delete_fail_message, oldFileName) - ) - .setCancelable(false) - .setPositiveButton(android.R.string.ok) { _, _ -> finish() } - .show() - return@runCatching + if (shouldGeneratePassword) { + val directoryStructure = + AutofillPreferences.directoryStructure(applicationContext) + val entry = passwordEntryFactory.create(content.encodeToByteArray()) + returnIntent.putExtra(RETURN_EXTRA_PASSWORD, entry.password) + val username = entry.username ?: directoryStructure.getUsernameFor(file) + returnIntent.putExtra(RETURN_EXTRA_USERNAME, username) } - } - val commitMessageRes = - if (editing) R.string.git_commit_edit_text else R.string.git_commit_add_text - lifecycleScope.launch { - commitChange( - resources.getString(commitMessageRes, getLongName(fullPath, repoPath, editName)) - ) - .onSuccess { - setResult(RESULT_OK, returnIntent) - finish() + if (directoryInputLayout.isVisible && + directoryInputLayout.isEnabled && + oldFileName != null + ) { + val oldFile = File("$repoPath/${oldCategory?.trim('/')}/$oldFileName.gpg") + if (oldFile.path != file.path && !oldFile.delete()) { + setResult(RESULT_CANCELED) + MaterialAlertDialogBuilder(this@PasswordCreationActivity) + .setTitle(R.string.password_creation_file_fail_title) + .setMessage( + getString(R.string.password_creation_file_delete_fail_message, oldFileName) + ) + .setCancelable(false) + .setPositiveButton(android.R.string.ok) { _, _ -> finish() } + .show() + return@runCatching } + } + + val commitMessageRes = + if (editing) R.string.git_commit_edit_text else R.string.git_commit_add_text + lifecycleScope.launch { + commitChange( + resources.getString( + commitMessageRes, + getLongName(fullPath, repoPath, editName) + ) + ) + .onSuccess { + setResult(RESULT_OK, returnIntent) + finish() + } + } } - } .onFailure { e -> if (e is IOException) { logcat(ERROR) { e.asLog("Failed to write password file") } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt index a24fbc9e..a35891a5 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/crypto/PasswordCreationActivityV2.kt @@ -119,15 +119,15 @@ class PasswordCreationActivityV2 : BasePgpActivity() { val reader = QRCodeReader() runCatching { - val result = reader.decode(binaryBitmap) - val text = result.text - val currentExtras = binding.extraContent.text.toString() - if (currentExtras.isNotEmpty() && currentExtras.last() != '\n') - binding.extraContent.append("\n$text") - else binding.extraContent.append(text) - snackbar(message = getString(R.string.otp_import_success)) - binding.otpImportButton.isVisible = false - } + val result = reader.decode(binaryBitmap) + val text = result.text + val currentExtras = binding.extraContent.text.toString() + if (currentExtras.isNotEmpty() && currentExtras.last() != '\n') + binding.extraContent.append("\n$text") + else binding.extraContent.append(text) + snackbar(message = getString(R.string.otp_import_success)) + binding.otpImportButton.isVisible = false + } .onFailure { snackbar(message = getString(R.string.otp_import_failure)) } } @@ -357,86 +357,87 @@ class PasswordCreationActivityV2 : BasePgpActivity() { lifecycleScope.launch(Dispatchers.Main) { runCatching { - val result = - withContext(Dispatchers.IO) { - val outputStream = ByteArrayOutputStream() - repository.encrypt(content.byteInputStream(), outputStream) - outputStream + val result = + withContext(Dispatchers.IO) { + val outputStream = ByteArrayOutputStream() + repository.encrypt(content.byteInputStream(), outputStream) + outputStream + } + val file = File(path) + // If we're not editing, this file should not already exist! + // Additionally, if we were editing and the incoming and outgoing + // filenames differ, it means we renamed. Ensure that the target + // doesn't already exist to prevent an accidental overwrite. + if ((!editing || (editing && suggestedName != file.nameWithoutExtension)) && + file.exists() + ) { + snackbar(message = getString(R.string.password_creation_duplicate_error)) + return@runCatching } - val file = File(path) - // If we're not editing, this file should not already exist! - // Additionally, if we were editing and the incoming and outgoing - // filenames differ, it means we renamed. Ensure that the target - // doesn't already exist to prevent an accidental overwrite. - if ((!editing || (editing && suggestedName != file.nameWithoutExtension)) && file.exists() - ) { - snackbar(message = getString(R.string.password_creation_duplicate_error)) - return@runCatching - } - - if (!file.isInsideRepository()) { - snackbar(message = getString(R.string.message_error_destination_outside_repo)) - return@runCatching - } - withContext(Dispatchers.IO) { file.writeBytes(result.toByteArray()) } - - // associate the new password name with the last name's timestamp in - // history - val preference = getSharedPreferences("recent_password_history", Context.MODE_PRIVATE) - val oldFilePathHash = "$repoPath/${oldCategory?.trim('/')}/$oldFileName.gpg".base64() - val timestamp = preference.getString(oldFilePathHash) - if (timestamp != null) { - preference.edit { - remove(oldFilePathHash) - putString(file.absolutePath.base64(), timestamp) + if (!file.isInsideRepository()) { + snackbar(message = getString(R.string.message_error_destination_outside_repo)) + return@runCatching } - } - val returnIntent = Intent() - returnIntent.putExtra(RETURN_EXTRA_CREATED_FILE, path) - returnIntent.putExtra(RETURN_EXTRA_NAME, editName) - returnIntent.putExtra(RETURN_EXTRA_LONG_NAME, getLongName(fullPath, repoPath, editName)) - - if (shouldGeneratePassword) { - val directoryStructure = AutofillPreferences.directoryStructure(applicationContext) - val entry = passwordEntryFactory.create(content.encodeToByteArray()) - returnIntent.putExtra(RETURN_EXTRA_PASSWORD, entry.password) - val username = entry.username ?: directoryStructure.getUsernameFor(file) - returnIntent.putExtra(RETURN_EXTRA_USERNAME, username) - } + withContext(Dispatchers.IO) { file.writeBytes(result.toByteArray()) } + + // associate the new password name with the last name's timestamp in + // history + val preference = getSharedPreferences("recent_password_history", Context.MODE_PRIVATE) + val oldFilePathHash = "$repoPath/${oldCategory?.trim('/')}/$oldFileName.gpg".base64() + val timestamp = preference.getString(oldFilePathHash) + if (timestamp != null) { + preference.edit { + remove(oldFilePathHash) + putString(file.absolutePath.base64(), timestamp) + } + } - if (directoryInputLayout.isVisible && - directoryInputLayout.isEnabled && - oldFileName != null - ) { - val oldFile = File("$repoPath/${oldCategory?.trim('/')}/$oldFileName.gpg") - if (oldFile.path != file.path && !oldFile.delete()) { - setResult(RESULT_CANCELED) - MaterialAlertDialogBuilder(this@PasswordCreationActivityV2) - .setTitle(R.string.password_creation_file_fail_title) - .setMessage( - getString(R.string.password_creation_file_delete_fail_message, oldFileName) - ) - .setCancelable(false) - .setPositiveButton(android.R.string.ok) { _, _ -> finish() } - .show() - return@runCatching + val returnIntent = Intent() + returnIntent.putExtra(RETURN_EXTRA_CREATED_FILE, path) + returnIntent.putExtra(RETURN_EXTRA_NAME, editName) + returnIntent.putExtra(RETURN_EXTRA_LONG_NAME, getLongName(fullPath, repoPath, editName)) + + if (shouldGeneratePassword) { + val directoryStructure = AutofillPreferences.directoryStructure(applicationContext) + val entry = passwordEntryFactory.create(content.encodeToByteArray()) + returnIntent.putExtra(RETURN_EXTRA_PASSWORD, entry.password) + val username = entry.username ?: directoryStructure.getUsernameFor(file) + returnIntent.putExtra(RETURN_EXTRA_USERNAME, username) } - } - val commitMessageRes = - if (editing) R.string.git_commit_edit_text else R.string.git_commit_add_text - lifecycleScope.launch { - commitChange( - resources.getString(commitMessageRes, getLongName(fullPath, repoPath, editName)) - ) - .onSuccess { - setResult(RESULT_OK, returnIntent) - finish() + if (directoryInputLayout.isVisible && + directoryInputLayout.isEnabled && + oldFileName != null + ) { + val oldFile = File("$repoPath/${oldCategory?.trim('/')}/$oldFileName.gpg") + if (oldFile.path != file.path && !oldFile.delete()) { + setResult(RESULT_CANCELED) + MaterialAlertDialogBuilder(this@PasswordCreationActivityV2) + .setTitle(R.string.password_creation_file_fail_title) + .setMessage( + getString(R.string.password_creation_file_delete_fail_message, oldFileName) + ) + .setCancelable(false) + .setPositiveButton(android.R.string.ok) { _, _ -> finish() } + .show() + return@runCatching } + } + + val commitMessageRes = + if (editing) R.string.git_commit_edit_text else R.string.git_commit_add_text + lifecycleScope.launch { + commitChange( + resources.getString(commitMessageRes, getLongName(fullPath, repoPath, editName)) + ) + .onSuccess { + setResult(RESULT_OK, returnIntent) + finish() + } + } } - } .onFailure { e -> if (e is IOException) { logcat(ERROR) { e.asLog("Failed to write password file") } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/PasswordGeneratorDialogFragment.kt b/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/PasswordGeneratorDialogFragment.kt index a21e9a6a..b0ddc8a7 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/PasswordGeneratorDialogFragment.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/dialogs/PasswordGeneratorDialogFragment.kt @@ -48,8 +48,7 @@ class PasswordGeneratorDialogFragment : DialogFragment() { val monoTypeface = Typeface.createFromAsset(callingActivity.assets, "fonts/sourcecodepro.ttf") val prefs = requireActivity() - .applicationContext - .getSharedPreferences("PasswordGenerator", Context.MODE_PRIVATE) + .applicationContext.getSharedPreferences("PasswordGenerator", Context.MODE_PRIVATE) builder.setView(binding.root) @@ -102,21 +101,21 @@ class PasswordGeneratorDialogFragment : DialogFragment() { val passwordLength = getLength() setPrefs(requireContext(), passwordOptions, passwordLength) passwordField.text = - runCatching { PasswordGenerator.generate(passwordOptions, passwordLength) }.getOrElse { - exception -> - val errorText = - when (exception) { - is MaxIterationsExceededException -> - requireContext().getString(R.string.pwgen_max_iterations_exceeded) - is NoCharactersIncludedException -> - requireContext().getString(R.string.pwgen_no_chars_error) - is PasswordLengthTooShortException -> - requireContext().getString(R.string.pwgen_length_too_short_error) - else -> requireContext().getString(R.string.pwgen_some_error_occurred) - } - Toast.makeText(requireActivity(), errorText, Toast.LENGTH_SHORT).show() - "" - } + runCatching { PasswordGenerator.generate(passwordOptions, passwordLength) } + .getOrElse { exception -> + val errorText = + when (exception) { + is MaxIterationsExceededException -> + requireContext().getString(R.string.pwgen_max_iterations_exceeded) + is NoCharactersIncludedException -> + requireContext().getString(R.string.pwgen_no_chars_error) + is PasswordLengthTooShortException -> + requireContext().getString(R.string.pwgen_length_too_short_error) + else -> requireContext().getString(R.string.pwgen_some_error_occurred) + } + Toast.makeText(requireActivity(), errorText, Toast.LENGTH_SHORT).show() + "" + } } private fun isChecked(@IdRes id: Int): Boolean { diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/folderselect/SelectFolderFragment.kt b/app/src/main/java/dev/msfjarvis/aps/ui/folderselect/SelectFolderFragment.kt index ae430485..54fd2892 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/folderselect/SelectFolderFragment.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/folderselect/SelectFolderFragment.kt @@ -59,18 +59,17 @@ class SelectFolderFragment : Fragment(R.layout.password_recycler_view) { override fun onAttach(context: Context) { super.onAttach(context) runCatching { - listener = - object : OnFragmentInteractionListener { - override fun onFragmentInteraction(item: PasswordItem) { - if (item.type == PasswordItem.TYPE_CATEGORY) { - model.navigateTo(item.file, listMode = ListMode.DirectoriesOnly) - (requireActivity() as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled( - true - ) + listener = + object : OnFragmentInteractionListener { + override fun onFragmentInteraction(item: PasswordItem) { + if (item.type == PasswordItem.TYPE_CATEGORY) { + model.navigateTo(item.file, listMode = ListMode.DirectoriesOnly) + (requireActivity() as AppCompatActivity) + .supportActionBar?.setDisplayHomeAsUpEnabled(true) + } } } - } - } + } .onFailure { throw ClassCastException("$context must implement OnFragmentInteractionListener") } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitConfigActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitConfigActivity.kt index 959d9325..03c92313 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitConfigActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitConfigActivity.kt @@ -88,9 +88,8 @@ class GitConfigActivity : BaseGitActivity() { binding.gitAbortRebase.alpha = if (needsAbort) 1.0f else 0.5f } binding.gitLog.setOnClickListener { - runCatching { startActivity(Intent(this, GitLogActivity::class.java)) }.onFailure { ex -> - logcat(ERROR) { "Failed to start GitLogActivity\n${ex}" } - } + runCatching { startActivity(Intent(this, GitLogActivity::class.java)) } + .onFailure { ex -> logcat(ERROR) { "Failed to start GitLogActivity\n${ex}" } } } binding.gitAbortRebase.setOnClickListener { lifecycleScope.launch { @@ -142,16 +141,16 @@ class GitConfigActivity : BaseGitActivity() { */ private fun headStatusMsg(repo: Repository): String { return runCatching { - val headRef = repo.getRef(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) + val headRef = repo.getRef(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/dev/msfjarvis/aps/ui/git/config/GitServerConfigActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitServerConfigActivity.kt index 6b1f30ea..e713a54e 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitServerConfigActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/git/config/GitServerConfigActivity.kt @@ -240,24 +240,24 @@ class GitServerConfigActivity : BaseGitActivity() { .setCancelable(false) .setPositiveButton(R.string.dialog_delete) { dialog, _ -> runCatching { - lifecycleScope.launch { - val snackbar = - snackbar( - message = getString(R.string.delete_directory_progress_text), - length = Snackbar.LENGTH_INDEFINITE - ) - withContext(Dispatchers.IO) { localDir.deleteRecursively() } - snackbar.dismiss() - launchGitOperation(GitOp.CLONE) - .fold( - success = { - setResult(RESULT_OK) - finish() - }, - failure = { err -> promptOnErrorHandler(err) { finish() } } - ) + lifecycleScope.launch { + val snackbar = + snackbar( + message = getString(R.string.delete_directory_progress_text), + length = Snackbar.LENGTH_INDEFINITE + ) + withContext(Dispatchers.IO) { localDir.deleteRecursively() } + snackbar.dismiss() + launchGitOperation(GitOp.CLONE) + .fold( + success = { + setResult(RESULT_OK) + finish() + }, + failure = { err -> promptOnErrorHandler(err) { finish() } } + ) + } } - } .onFailure { e -> e.printStackTrace() MaterialAlertDialogBuilder(this).setMessage(e.message).show() @@ -268,11 +268,11 @@ class GitServerConfigActivity : BaseGitActivity() { .show() } else { runCatching { - // Silently delete & replace the lone .git folder if it exists - if (localDir.exists() && localDirFiles.size == 1 && localDirFiles[0].name == ".git") { - localDir.deleteRecursively() + // Silently delete & replace the lone .git folder if it exists + if (localDir.exists() && localDirFiles.size == 1 && localDirFiles[0].name == ".git") { + localDir.deleteRecursively() + } } - } .onFailure { e -> logcat(ERROR) { e.asLog() } MaterialAlertDialogBuilder(this).setMessage(e.message).show() diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/onboarding/fragments/CloneFragment.kt b/app/src/main/java/dev/msfjarvis/aps/ui/onboarding/fragments/CloneFragment.kt index 16c1a784..e3d1df85 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/onboarding/fragments/CloneFragment.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/onboarding/fragments/CloneFragment.kt @@ -55,13 +55,13 @@ class CloneFragment : Fragment(R.layout.fragment_clone) { private fun createRepository() { val localDir = PasswordRepository.getRepositoryDirectory() runCatching { - check(localDir.exists() || localDir.mkdir()) { "Failed to create directory!" } - PasswordRepository.createRepository(localDir) - if (!PasswordRepository.isInitialized) { - PasswordRepository.initialize() + check(localDir.exists() || localDir.mkdir()) { "Failed to create directory!" } + PasswordRepository.createRepository(localDir) + if (!PasswordRepository.isInitialized) { + PasswordRepository.initialize() + } + parentFragmentManager.performTransactionWithBackStack(KeySelectionFragment.newInstance()) } - parentFragmentManager.performTransactionWithBackStack(KeySelectionFragment.newInstance()) - } .onFailure { e -> logcat(ERROR) { e.asLog() } if (!localDir.delete()) { diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordFragment.kt b/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordFragment.kt index 063f472c..0d0f9cfc 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordFragment.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordFragment.kt @@ -293,32 +293,32 @@ class PasswordFragment : Fragment(R.layout.password_recycler_view) { override fun onAttach(context: Context) { super.onAttach(context) runCatching { - listener = - object : OnFragmentInteractionListener { - override fun onFragmentInteraction(item: PasswordItem) { - if (settings.getString(PreferenceKeys.SORT_ORDER) == - PasswordSortOrder.RECENTLY_USED.name - ) { - // save the time when password was used - val preferences = - context.getSharedPreferences("recent_password_history", Context.MODE_PRIVATE) - preferences.edit { - putString(item.file.absolutePath.base64(), System.currentTimeMillis().toString()) + listener = + object : OnFragmentInteractionListener { + override fun onFragmentInteraction(item: PasswordItem) { + if (settings.getString(PreferenceKeys.SORT_ORDER) == + PasswordSortOrder.RECENTLY_USED.name + ) { + // save the time when password was used + val preferences = + context.getSharedPreferences("recent_password_history", Context.MODE_PRIVATE) + preferences.edit { + putString(item.file.absolutePath.base64(), System.currentTimeMillis().toString()) + } } - } - if (item.type == PasswordItem.TYPE_CATEGORY) { - navigateTo(item.file) - } else { - if (requireArguments().getBoolean("matchWith", false)) { - requireStore().matchPasswordWithApp(item) + if (item.type == PasswordItem.TYPE_CATEGORY) { + navigateTo(item.file) } else { - requireStore().decryptPassword(item) + if (requireArguments().getBoolean("matchWith", false)) { + requireStore().matchPasswordWithApp(item) + } else { + requireStore().decryptPassword(item) + } } } } - } - } + } .onFailure { throw ClassCastException("$context must implement OnFragmentInteractionListener") } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordStore.kt b/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordStore.kt index e4ec2359..84bef7bb 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordStore.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/passwords/PasswordStore.kt @@ -292,9 +292,8 @@ class PasswordStore : BaseGitActivity() { .setPositiveButton(resources.getString(R.string.dialog_ok), null) when (id) { R.id.user_pref -> { - runCatching { startActivity(Intent(this, SettingsActivity::class.java)) }.onFailure { e -> - e.printStackTrace() - } + runCatching { startActivity(Intent(this, SettingsActivity::class.java)) } + .onFailure { e -> e.printStackTrace() } } R.id.git_push -> { if (!PasswordRepository.isInitialized) { @@ -618,9 +617,7 @@ class PasswordStore : BaseGitActivity() { fun matchPasswordWithApp(item: PasswordItem) { val path = - item - .file - .absolutePath + item.file.absolutePath .replace(PasswordRepository.getRepositoryDirectory().toString() + "/", "") .replace(".gpg", "") val data = Intent() diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/proxy/ProxySelectorActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/proxy/ProxySelectorActivity.kt index 6fc63673..41cab040 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/proxy/ProxySelectorActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/proxy/ProxySelectorActivity.kt @@ -42,9 +42,10 @@ class ProxySelectorActivity : AppCompatActivity() { 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") - } + 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, _, _, _ -> @@ -70,18 +71,22 @@ class ProxySelectorActivity : AppCompatActivity() { 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 - } + 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() } diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/settings/RepositorySettings.kt b/app/src/main/java/dev/msfjarvis/aps/ui/settings/RepositorySettings.kt index 1c43127a..ffd0f851 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/settings/RepositorySettings.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/settings/RepositorySettings.kt @@ -161,9 +161,9 @@ class RepositorySettings(private val activity: FragmentActivity) : SettingsProvi .setCancelable(false) .setPositiveButton(R.string.dialog_delete) { dialogInterface, _ -> runCatching { - PasswordRepository.getRepositoryDirectory().deleteRecursively() - PasswordRepository.closeRepository() - } + PasswordRepository.getRepositoryDirectory().deleteRecursively() + PasswordRepository.closeRepository() + } .onFailure { it.message?.let { message -> activity.snackbar(message = message) } } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { diff --git a/app/src/main/java/dev/msfjarvis/aps/ui/sshkeygen/SshKeyImportActivity.kt b/app/src/main/java/dev/msfjarvis/aps/ui/sshkeygen/SshKeyImportActivity.kt index af00e3df..446e0c32 100644 --- a/app/src/main/java/dev/msfjarvis/aps/ui/sshkeygen/SshKeyImportActivity.kt +++ b/app/src/main/java/dev/msfjarvis/aps/ui/sshkeygen/SshKeyImportActivity.kt @@ -25,16 +25,16 @@ class SshKeyImportActivity : AppCompatActivity() { 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() - } + 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)) -- cgit v1.2.3