From d17ff0d9251bd2ad84778535dabe4884a4cf9d76 Mon Sep 17 00:00:00 2001 From: Aditya Wasan Date: Fri, 19 Feb 2021 13:57:57 +0530 Subject: Parse extra content into key value pairs (#1321) * ui: add skeleton recyclerview to parse extra content Signed-off-by: Aditya Wasan * ui: add recyclerview and update PasswordEntry to create map of key-value pairs Signed-off-by: Aditya Wasan * password-entry: When key-value pair is not correctly formed, display it as Extra Content Signed-off-by: Aditya Wasan * Fix formatting Signed-off-by: Aditya Wasan * bug: update otp code on main thread Signed-off-by: Aditya Wasan * Add complete string if key-value pair cannot be formed Signed-off-by: Aditya Wasan * test: add a few tests for key-value parsing logic Signed-off-by: Aditya Wasan * prefs: remove SHOW_EXTRA_CONTENT from shared preferences Signed-off-by: Aditya Wasan * Update CHANGELOG.md * Cleanup and refactor Signed-off-by: Harsh Shandilya * PasswordEntryTest: silence nullability warning Signed-off-by: Harsh Shandilya * PasswordEntry: simplify constructor Signed-off-by: Harsh Shandilya * PasswordEntry: annotate test-enablement visibility Signed-off-by: Harsh Shandilya * Reintroduce the catch-all field Signed-off-by: Harsh Shandilya * update parsing logic Signed-off-by: Aditya Wasan * add one more test case Signed-off-by: Aditya Wasan * Add missing newlines Signed-off-by: Harsh Shandilya * Remove unnecessary scrollview Signed-off-by: Harsh Shandilya * rv: do not return if hasExtraContent is false Signed-off-by: Aditya Wasan * Don't anchor RV to bottom Signed-off-by: Harsh Shandilya Co-authored-by: Harsh Shandilya --- .../dev/msfjarvis/aps/ui/crypto/DecryptActivity.kt | 102 ++++++++------------- 1 file changed, 39 insertions(+), 63 deletions(-) (limited to 'app/src/main/java/dev/msfjarvis/aps/ui/crypto') 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 8e08b039..88f76161 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 @@ -6,9 +6,7 @@ package dev.msfjarvis.aps.ui.crypto import android.content.Intent -import android.graphics.Typeface import android.os.Bundle -import android.text.method.PasswordTransformationMethod import android.view.Menu import android.view.MenuItem import android.view.View @@ -19,8 +17,10 @@ import com.github.ajalt.timberkt.e import com.github.michaelbull.result.onFailure import com.github.michaelbull.result.runCatching import dev.msfjarvis.aps.R +import dev.msfjarvis.aps.data.password.FieldItem import dev.msfjarvis.aps.data.password.PasswordEntry import dev.msfjarvis.aps.databinding.DecryptLayoutBinding +import dev.msfjarvis.aps.ui.adapters.FieldItemAdapter import dev.msfjarvis.aps.util.extensions.viewBinding import dev.msfjarvis.aps.util.settings.PreferenceKeys import java.io.ByteArrayOutputStream @@ -172,80 +172,56 @@ class DecryptActivity : BasePgpActivity(), OpenPgpServiceConnection.OnBound { startAutoDismissTimer() runCatching { val showPassword = settings.getBoolean(PreferenceKeys.SHOW_PASSWORD, true) - val showExtraContent = settings.getBoolean(PreferenceKeys.SHOW_EXTRA_CONTENT, true) - val monoTypeface = Typeface.createFromAsset(assets, "fonts/sourcecodepro.ttf") val entry = PasswordEntry(outputStream) + val items = arrayListOf() + val adapter = FieldItemAdapter(emptyList(), showPassword) { text -> + copyTextToClipboard(text) + } + + if (settings.getBoolean(PreferenceKeys.COPY_ON_DECRYPT, false)) { + copyPasswordToClipboard(entry.password) + } passwordEntry = entry invalidateOptionsMenu() - with(binding) { - if (entry.password.isEmpty()) { - passwordTextContainer.visibility = View.GONE - } else { - passwordTextContainer.visibility = View.VISIBLE - passwordText.typeface = monoTypeface - passwordText.setText(entry.password) - if (!showPassword) { - passwordText.transformationMethod = PasswordTransformationMethod.getInstance() - } - passwordTextContainer.setOnClickListener { copyPasswordToClipboard(entry.password) } - passwordText.setOnClickListener { copyPasswordToClipboard(entry.password) } - } - - if (entry.hasExtraContent()) { - if (entry.extraContentWithoutAuthData.isNotEmpty()) { - extraContentContainer.visibility = View.VISIBLE - extraContent.typeface = monoTypeface - extraContent.setText(entry.extraContentWithoutAuthData) - if (!showExtraContent) { - extraContent.transformationMethod = PasswordTransformationMethod.getInstance() - } - extraContentContainer.setOnClickListener { copyTextToClipboard(entry.extraContentWithoutAuthData) } - extraContent.setOnClickListener { copyTextToClipboard(entry.extraContentWithoutAuthData) } - } + if (entry.password.isNotEmpty()) { + items.add(FieldItem.createPasswordField(entry.password)) + } - if (entry.hasUsername()) { - usernameText.typeface = monoTypeface - usernameText.setText(entry.username) - usernameTextContainer.setEndIconOnClickListener { copyTextToClipboard(entry.username) } - usernameTextContainer.visibility = View.VISIBLE - } else { - usernameTextContainer.visibility = View.GONE + if (entry.hasTotp()) { + launch(Dispatchers.IO) { + // Calculate the actual remaining time for the first pass + // then return to the standard 30 second affair. + val remainingTime = + entry.totpPeriod - (System.currentTimeMillis() % entry.totpPeriod) + withContext(Dispatchers.Main) { + val code = entry.calculateTotpCode() ?: "Error" + items.add(FieldItem.createOtpField(code)) } - - if (entry.hasTotp()) { - otpTextContainer.visibility = View.VISIBLE - otpTextContainer.setEndIconOnClickListener { - copyTextToClipboard( - otpText.text.toString(), - snackbarTextRes = R.string.clipboard_otp_copied_text - ) - } - launch(Dispatchers.IO) { - // Calculate the actual remaining time for the first pass - // then return to the standard 30 second affair. - val remainingTime = entry.totpPeriod - (System.currentTimeMillis() % entry.totpPeriod) - withContext(Dispatchers.Main) { - otpText.setText(entry.calculateTotpCode() - ?: "Error") - } - delay(remainingTime.seconds) - repeat(Int.MAX_VALUE) { - val code = entry.calculateTotpCode() ?: "Error" - withContext(Dispatchers.Main) { - otpText.setText(code) - } - delay(30.seconds) - } + delay(remainingTime.seconds) + repeat(Int.MAX_VALUE) { + val code = entry.calculateTotpCode() ?: "Error" + withContext(Dispatchers.Main) { + adapter.updateOTPCode(code) } + delay(30.seconds) } } } - if (settings.getBoolean(PreferenceKeys.COPY_ON_DECRYPT, false)) { - copyPasswordToClipboard(entry.password) + if (!entry.username.isNullOrEmpty()) { + items.add(FieldItem.createUsernameField(entry.username)) } + + if (entry.hasExtraContentWithoutAuthData()) { + entry.extraContentMap.forEach { (key, value) -> + items.add(FieldItem(key, value, FieldItem.ActionType.COPY)) + } + } + + binding.recyclerView.adapter = adapter + adapter.updateItems(items) }.onFailure { e -> e(e) } -- cgit v1.2.3