mirror of
https://github.com/android-password-store/Android-Password-Store
synced 2025-08-30 05:48:09 +00:00
refactor: rework password dialog to avoid memory leak
This commit is contained in:
parent
227a2bf174
commit
26abbbef97
@ -11,6 +11,7 @@ import android.content.IntentSender
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.autofill.AutofillManager
|
import android.view.autofill.AutofillManager
|
||||||
|
import androidx.fragment.app.setFragmentResultListener
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import app.passwordstore.R
|
import app.passwordstore.R
|
||||||
import app.passwordstore.data.crypto.PGPPassphraseCache
|
import app.passwordstore.data.crypto.PGPPassphraseCache
|
||||||
@ -35,7 +36,6 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import logcat.LogPriority.ERROR
|
import logcat.LogPriority.ERROR
|
||||||
@ -120,16 +120,15 @@ class AutofillDecryptActivity : BasePGPActivity() {
|
|||||||
|
|
||||||
private fun askPassphrase(filePath: String, clientState: Bundle, action: AutofillAction) {
|
private fun askPassphrase(filePath: String, clientState: Bundle, action: AutofillAction) {
|
||||||
val dialog = PasswordDialog()
|
val dialog = PasswordDialog()
|
||||||
lifecycleScope.launch {
|
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
|
||||||
withContext(dispatcherProvider.main()) {
|
dialog.setFragmentResultListener(PasswordDialog.PASSWORD_RESULT_KEY) { key, bundle ->
|
||||||
dialog.password.collectLatest { value ->
|
if (key == PasswordDialog.PASSWORD_RESULT_KEY) {
|
||||||
if (value != null) {
|
val value = bundle.getString(PasswordDialog.PASSWORD_RESULT_KEY)!!
|
||||||
decryptWithPassphrase(File(filePath), clientState, action, value)
|
lifecycleScope.launch(dispatcherProvider.main()) {
|
||||||
}
|
decryptWithPassphrase(File(filePath), clientState, action, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun decryptWithPassphrase(
|
private suspend fun decryptWithPassphrase(
|
||||||
|
@ -9,6 +9,7 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
import androidx.fragment.app.setFragmentResultListener
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import app.passwordstore.R
|
import app.passwordstore.R
|
||||||
import app.passwordstore.crypto.PGPIdentifier
|
import app.passwordstore.crypto.PGPIdentifier
|
||||||
@ -35,7 +36,6 @@ import java.io.File
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@ -189,9 +189,11 @@ class DecryptActivity : BasePGPActivity() {
|
|||||||
if (isError) {
|
if (isError) {
|
||||||
dialog.setError()
|
dialog.setError()
|
||||||
}
|
}
|
||||||
lifecycleScope.launch(dispatcherProvider.main()) {
|
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
|
||||||
dialog.password.collectLatest { value ->
|
dialog.setFragmentResultListener(PasswordDialog.PASSWORD_RESULT_KEY) { key, bundle ->
|
||||||
if (value != null) {
|
if (key == PasswordDialog.PASSWORD_RESULT_KEY) {
|
||||||
|
val value = bundle.getString(PasswordDialog.PASSWORD_RESULT_KEY)!!
|
||||||
|
lifecycleScope.launch(dispatcherProvider.main()) {
|
||||||
when (val result = decryptWithPassphrase(value, gpgIdentifiers)) {
|
when (val result = decryptWithPassphrase(value, gpgIdentifiers)) {
|
||||||
is Ok -> {
|
is Ok -> {
|
||||||
val entry = passwordEntryFactory.create(result.value.toByteArray())
|
val entry = passwordEntryFactory.create(result.value.toByteArray())
|
||||||
@ -210,7 +212,6 @@ class DecryptActivity : BasePGPActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun decryptWithCachedPassphrase(
|
private suspend fun decryptWithCachedPassphrase(
|
||||||
|
@ -10,24 +10,21 @@ import android.content.DialogInterface
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.fragment.app.setFragmentResult
|
||||||
import app.passwordstore.R
|
import app.passwordstore.R
|
||||||
import app.passwordstore.databinding.DialogPasswordEntryBinding
|
import app.passwordstore.databinding.DialogPasswordEntryBinding
|
||||||
import app.passwordstore.util.extensions.finish
|
import app.passwordstore.util.extensions.finish
|
||||||
import app.passwordstore.util.extensions.unsafeLazy
|
import app.passwordstore.util.extensions.unsafeLazy
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import kotlinx.coroutines.flow.update
|
|
||||||
|
|
||||||
/** [DialogFragment] to request a password from the user and forward it along. */
|
/** [DialogFragment] to request a password from the user and forward it along. */
|
||||||
class PasswordDialog : DialogFragment() {
|
class PasswordDialog : DialogFragment() {
|
||||||
|
|
||||||
private val binding by unsafeLazy { DialogPasswordEntryBinding.inflate(layoutInflater) }
|
private val binding by unsafeLazy { DialogPasswordEntryBinding.inflate(layoutInflater) }
|
||||||
private var isError: Boolean = false
|
private var isError: Boolean = false
|
||||||
private val _password = MutableStateFlow<String?>(null)
|
|
||||||
val password = _password.asStateFlow()
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val builder = MaterialAlertDialogBuilder(requireContext())
|
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||||
@ -66,7 +63,12 @@ class PasswordDialog : DialogFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setPasswordAndDismiss() {
|
private fun setPasswordAndDismiss() {
|
||||||
_password.update { binding.passwordEditText.text.toString() }
|
val password = binding.passwordEditText.text.toString()
|
||||||
|
setFragmentResult(PASSWORD_RESULT_KEY, bundleOf(PASSWORD_RESULT_KEY to password))
|
||||||
dismissAllowingStateLoss()
|
dismissAllowingStateLoss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PASSWORD_RESULT_KEY = "password_result"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user