diff options
Diffstat (limited to 'app/src/main/java')
| -rw-r--r-- | app/src/main/java/app/passwordstore/ui/entry/EntryDestination.kt | 20 | ||||
| -rw-r--r-- | app/src/main/java/app/passwordstore/ui/entry/EntryViewModel.kt | 6 |
2 files changed, 18 insertions, 8 deletions
diff --git a/app/src/main/java/app/passwordstore/ui/entry/EntryDestination.kt b/app/src/main/java/app/passwordstore/ui/entry/EntryDestination.kt index a54b517d..5c16b5a3 100644 --- a/app/src/main/java/app/passwordstore/ui/entry/EntryDestination.kt +++ b/app/src/main/java/app/passwordstore/ui/entry/EntryDestination.kt @@ -25,6 +25,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.key import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.remember @@ -104,6 +105,9 @@ fun EntryDestination( } } + // ponytail: after process death during key import or the editor, the unlock flow can start + // twice or a prompt can be left over the list; rare, no secret exposed. Fix by tracking + // whether the flow already started if it shows up. val keyImport = rememberLauncherForActivityResult(StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) unlock() else onClose() @@ -173,13 +177,15 @@ fun EntryDestination( ) EntryPrompt.Passphrase, EntryPrompt.WrongPassphrase -> - PassphraseDialog( - wrong = viewModel.prompt == EntryPrompt.WrongPassphrase, - cacheEnabled = viewModel.cacheEnabled, - clearCache = viewModel.clearCache, - onSubmit = { passphrase, clear -> viewModel.submit(passphrase, clear, activity) }, - onCancel = viewModel::cancel, - ) + key(viewModel.retries) { + PassphraseDialog( + wrong = viewModel.prompt == EntryPrompt.WrongPassphrase, + cacheEnabled = viewModel.cacheEnabled, + clearCache = viewModel.clearCache, + onSubmit = { passphrase, clear -> viewModel.submit(passphrase, clear, activity) }, + onCancel = viewModel::cancel, + ) + } } } } diff --git a/app/src/main/java/app/passwordstore/ui/entry/EntryViewModel.kt b/app/src/main/java/app/passwordstore/ui/entry/EntryViewModel.kt index 38d3b9d9..5714f2a6 100644 --- a/app/src/main/java/app/passwordstore/ui/entry/EntryViewModel.kt +++ b/app/src/main/java/app/passwordstore/ui/entry/EntryViewModel.kt @@ -86,7 +86,10 @@ constructor( private var started = false private var copyOnDecrypt = false - private var retries = 0 + /** Failed-or-asked passphrase prompts so far; keys the dialog so each attempt starts fresh. */ + var retries = 0 + private set + private var auth: BiometricResult = BiometricResult.CanceledByUser private var ids: List<PGPIdentifier> = emptyList() private var file: File? = null @@ -115,6 +118,7 @@ constructor( } fun submit(passphrase: String, clearCache: Boolean, context: Context) { + if (prompt == EntryPrompt.None) return prompt = EntryPrompt.None this.clearCache = clearCache val app = context.applicationContext |
