PM-10094: Disable double-navigation by default (#3660)
Some checks failed
Crowdin Push / Crowdin Push (push) Waiting to run
Scan / Check PR run (push) Failing after 0s
Scan / SAST scan (push) Has been skipped
Scan / Quality scan (push) Has been skipped
Test / Check PR run (push) Failing after 0s
Test / Test (push) Has been skipped

This commit is contained in:
Shannon Draeker 2024-08-01 15:31:04 -06:00 committed by GitHub
parent d0edca67c5
commit 055fbc1277
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 29 additions and 8 deletions

View file

@ -0,0 +1,8 @@
package com.x8bit.bitwarden.ui.platform.base.util
/**
* Almost all the events in the app involve navigation or toasts. To prevent accidentally
* navigating to the same view twice, by default, events are ignored if the view is not currently
* resumed. To avoid that restriction, specific events can implement [BackgroundEvent].
*/
interface BackgroundEvent

View file

@ -2,20 +2,32 @@ package com.x8bit.bitwarden.ui.platform.base.util
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
/** /**
* Convenience method for observing event flow from [BaseViewModel]. * Convenience method for observing event flow from [BaseViewModel].
*
* By default, events will only be consumed when the associated screen is
* resumed, to avoid bugs like duplicate navigation calls. To override
* this behavior, a given event type can implement [BackgroundEvent].
*/ */
@Composable @Composable
fun <E> EventsEffect( fun <E> EventsEffect(
viewModel: BaseViewModel<*, E, *>, viewModel: BaseViewModel<*, E, *>,
lifecycleOwner: Lifecycle = LocalLifecycleOwner.current.lifecycle,
handler: suspend (E) -> Unit, handler: suspend (E) -> Unit,
) { ) {
LaunchedEffect(key1 = Unit) { LaunchedEffect(key1 = Unit) {
viewModel.eventFlow viewModel.eventFlow
.filter {
it is BackgroundEvent ||
lifecycleOwner.currentState.isAtLeast(Lifecycle.State.RESUMED)
}
.onEach { handler.invoke(it) } .onEach { handler.invoke(it) }
.launchIn(this) .launchIn(this)
} }

View file

@ -37,6 +37,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.TotpCodeResult
import com.x8bit.bitwarden.data.vault.repository.model.UpdateCipherResult import com.x8bit.bitwarden.data.vault.repository.model.UpdateCipherResult
import com.x8bit.bitwarden.data.vault.repository.model.VaultData import com.x8bit.bitwarden.data.vault.repository.model.VaultData
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.BackgroundEvent
import com.x8bit.bitwarden.ui.platform.base.util.Text import com.x8bit.bitwarden.ui.platform.base.util.Text
import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.base.util.concat import com.x8bit.bitwarden.ui.platform.base.util.concat
@ -2358,8 +2359,7 @@ sealed class VaultAddEditEvent {
/** /**
* Navigate the user to the tooltip URI. * Navigate the user to the tooltip URI.
*/ */
data object NavigateToTooltipUri : data object NavigateToTooltipUri : VaultAddEditEvent()
VaultAddEditEvent()
/** /**
* Navigate to the QR code scan screen. * Navigate to the QR code scan screen.
@ -2385,7 +2385,7 @@ sealed class VaultAddEditEvent {
*/ */
data class CompleteFido2Registration( data class CompleteFido2Registration(
val result: Fido2RegisterCredentialResult, val result: Fido2RegisterCredentialResult,
) : VaultAddEditEvent() ) : BackgroundEvent, VaultAddEditEvent()
/** /**
* Perform user verification for a FIDO 2 credential operation. * Perform user verification for a FIDO 2 credential operation.
@ -2394,7 +2394,7 @@ sealed class VaultAddEditEvent {
*/ */
data class Fido2UserVerification( data class Fido2UserVerification(
val isRequired: Boolean, val isRequired: Boolean,
) : VaultAddEditEvent() ) : BackgroundEvent, VaultAddEditEvent()
} }
/** /**

View file

@ -46,6 +46,7 @@ import com.x8bit.bitwarden.data.vault.repository.model.GenerateTotpResult
import com.x8bit.bitwarden.data.vault.repository.model.RemovePasswordSendResult import com.x8bit.bitwarden.data.vault.repository.model.RemovePasswordSendResult
import com.x8bit.bitwarden.data.vault.repository.model.VaultData import com.x8bit.bitwarden.data.vault.repository.model.VaultData
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.BackgroundEvent
import com.x8bit.bitwarden.ui.platform.base.util.Text import com.x8bit.bitwarden.ui.platform.base.util.Text
import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.base.util.concat import com.x8bit.bitwarden.ui.platform.base.util.concat
@ -2102,7 +2103,7 @@ sealed class VaultItemListingEvent {
*/ */
data class CompleteFido2Registration( data class CompleteFido2Registration(
val result: Fido2RegisterCredentialResult, val result: Fido2RegisterCredentialResult,
) : VaultItemListingEvent() ) : BackgroundEvent, VaultItemListingEvent()
/** /**
* Perform user verification for a FIDO 2 credential operation. * Perform user verification for a FIDO 2 credential operation.
@ -2110,7 +2111,7 @@ sealed class VaultItemListingEvent {
data class Fido2UserVerification( data class Fido2UserVerification(
val isRequired: Boolean, val isRequired: Boolean,
val selectedCipherView: CipherView, val selectedCipherView: CipherView,
) : VaultItemListingEvent() ) : BackgroundEvent, VaultItemListingEvent()
/** /**
* FIDO 2 credential assertion result has been received and the process is ready to be * FIDO 2 credential assertion result has been received and the process is ready to be
@ -2120,7 +2121,7 @@ sealed class VaultItemListingEvent {
*/ */
data class CompleteFido2Assertion( data class CompleteFido2Assertion(
val result: Fido2CredentialAssertionResult, val result: Fido2CredentialAssertionResult,
) : VaultItemListingEvent() ) : BackgroundEvent, VaultItemListingEvent()
/** /**
* FIDO 2 credential lookup result has been received and the process is ready to be completed. * FIDO 2 credential lookup result has been received and the process is ready to be completed.
@ -2129,7 +2130,7 @@ sealed class VaultItemListingEvent {
*/ */
data class CompleteFido2GetCredentialsRequest( data class CompleteFido2GetCredentialsRequest(
val result: Fido2GetCredentialsResult, val result: Fido2GetCredentialsResult,
) : VaultItemListingEvent() ) : BackgroundEvent, VaultItemListingEvent()
} }
/** /**