mirror of
https://github.com/bitwarden/android.git
synced 2024-11-24 02:15:53 +03:00
PM-14353 : Clean up consumed snackbar on quick resubmission due to state based nav. (#4235)
This commit is contained in:
parent
29384596d4
commit
e397c036e4
5 changed files with 69 additions and 16 deletions
|
@ -19,4 +19,9 @@ interface SnackbarRelayManager {
|
|||
* the [relay] to receive the data from.
|
||||
*/
|
||||
fun getSnackbarDataFlow(relay: SnackbarRelay): Flow<BitwardenSnackbarData>
|
||||
|
||||
/**
|
||||
* Clears the buffer for the given [relay].
|
||||
*/
|
||||
fun clearRelayBuffer(relay: SnackbarRelay)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.x8bit.bitwarden.ui.platform.manager.snackbar
|
|||
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
||||
import com.x8bit.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarData
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
|
@ -26,6 +27,11 @@ class SnackbarRelayManagerImpl : SnackbarRelayManager {
|
|||
}
|
||||
.filterNotNull()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun clearRelayBuffer(relay: SnackbarRelay) {
|
||||
getSnackbarDataFlowInternal(relay).resetReplayCache()
|
||||
}
|
||||
|
||||
private fun getSnackbarDataFlowInternal(
|
||||
relay: SnackbarRelay,
|
||||
): MutableSharedFlow<BitwardenSnackbarData?> =
|
||||
|
|
|
@ -73,8 +73,8 @@ class VaultViewModel @Inject constructor(
|
|||
private val settingsRepository: SettingsRepository,
|
||||
private val vaultRepository: VaultRepository,
|
||||
private val firstTimeActionManager: FirstTimeActionManager,
|
||||
private val snackbarRelayManager: SnackbarRelayManager,
|
||||
featureFlagManager: FeatureFlagManager,
|
||||
snackbarRelayManager: SnackbarRelayManager,
|
||||
) : BaseViewModel<VaultState, VaultEvent, VaultAction>(
|
||||
initialState = run {
|
||||
val userState = requireNotNull(authRepository.userStateFlow.value)
|
||||
|
@ -283,6 +283,9 @@ class VaultViewModel @Inject constructor(
|
|||
SwitchAccountResult.AccountSwitched -> true
|
||||
SwitchAccountResult.NoChange -> false
|
||||
}
|
||||
if (isSwitchingAccounts) {
|
||||
snackbarRelayManager.clearRelayBuffer(SnackbarRelay.MY_VAULT_RELAY)
|
||||
}
|
||||
mutableStateFlow.update {
|
||||
it.copy(isSwitchingAccounts = isSwitchingAccounts)
|
||||
}
|
||||
|
|
|
@ -66,16 +66,16 @@ class SnackbarRelayManagerTest {
|
|||
fun `When multiple consumers are registered to the same relay, send data to all consumers`() =
|
||||
runTest {
|
||||
val relayManager = SnackbarRelayManagerImpl()
|
||||
val relay1 = SnackbarRelay.MY_VAULT_RELAY
|
||||
val relay = SnackbarRelay.MY_VAULT_RELAY
|
||||
val expectedData = BitwardenSnackbarData(message = "Test message".asText())
|
||||
turbineScope {
|
||||
val consumer1 = relayManager.getSnackbarDataFlow(relay1).testIn(backgroundScope)
|
||||
relayManager.sendSnackbarData(data = expectedData, relay = relay1)
|
||||
val consumer1 = relayManager.getSnackbarDataFlow(relay).testIn(backgroundScope)
|
||||
relayManager.sendSnackbarData(data = expectedData, relay = relay)
|
||||
assertEquals(
|
||||
expectedData,
|
||||
consumer1.awaitItem(),
|
||||
)
|
||||
val consumer2 = relayManager.getSnackbarDataFlow(relay1).testIn(backgroundScope)
|
||||
val consumer2 = relayManager.getSnackbarDataFlow(relay).testIn(backgroundScope)
|
||||
assertEquals(
|
||||
expectedData,
|
||||
consumer2.awaitItem(),
|
||||
|
@ -85,20 +85,40 @@ class SnackbarRelayManagerTest {
|
|||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `When multiple consumers are register to the same relay, and one is completed before the other the second consumer registers should not receive any emissions`() =
|
||||
fun `When multiple consumers are registered to the same relay, and one is completed before the other the second consumer registers should not receive any emissions`() =
|
||||
runTest {
|
||||
val relayManager = SnackbarRelayManagerImpl()
|
||||
val relay1 = SnackbarRelay.MY_VAULT_RELAY
|
||||
val relay = SnackbarRelay.MY_VAULT_RELAY
|
||||
val expectedData = BitwardenSnackbarData(message = "Test message".asText())
|
||||
turbineScope {
|
||||
val consumer1 = relayManager.getSnackbarDataFlow(relay1).testIn(backgroundScope)
|
||||
relayManager.sendSnackbarData(data = expectedData, relay = relay1)
|
||||
val consumer1 = relayManager.getSnackbarDataFlow(relay).testIn(backgroundScope)
|
||||
relayManager.sendSnackbarData(data = expectedData, relay = relay)
|
||||
assertEquals(
|
||||
expectedData,
|
||||
consumer1.awaitItem(),
|
||||
)
|
||||
consumer1.cancel()
|
||||
val consumer2 = relayManager.getSnackbarDataFlow(relay1).testIn(backgroundScope)
|
||||
val consumer2 = relayManager.getSnackbarDataFlow(relay).testIn(backgroundScope)
|
||||
consumer2.expectNoEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MaxLineLength")
|
||||
@Test
|
||||
fun `When multiple consumers register to the same relay, and clearRelayBuffer is called, the second consumer should not receive any emissions`() =
|
||||
runTest {
|
||||
val relayManager = SnackbarRelayManagerImpl()
|
||||
val relay = SnackbarRelay.MY_VAULT_RELAY
|
||||
val expectedData = BitwardenSnackbarData(message = "Test message".asText())
|
||||
turbineScope {
|
||||
val consumer1 = relayManager.getSnackbarDataFlow(relay).testIn(backgroundScope)
|
||||
relayManager.sendSnackbarData(data = expectedData, relay = relay)
|
||||
assertEquals(
|
||||
expectedData,
|
||||
consumer1.awaitItem(),
|
||||
)
|
||||
relayManager.clearRelayBuffer(relay)
|
||||
val consumer2 = relayManager.getSnackbarDataFlow(relay).testIn(backgroundScope)
|
||||
consumer2.expectNoEvents()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ import com.x8bit.bitwarden.ui.platform.base.util.asText
|
|||
import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary
|
||||
import com.x8bit.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarData
|
||||
import com.x8bit.bitwarden.ui.platform.manager.snackbar.SnackbarRelay
|
||||
import com.x8bit.bitwarden.ui.platform.manager.snackbar.SnackbarRelayManagerImpl
|
||||
import com.x8bit.bitwarden.ui.platform.manager.snackbar.SnackbarRelayManager
|
||||
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.model.ListingItemOverflowAction
|
||||
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterData
|
||||
import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType
|
||||
|
@ -49,6 +49,7 @@ import io.mockk.mockk
|
|||
import io.mockk.runs
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
|
@ -66,7 +67,12 @@ class VaultViewModelTest : BaseViewModelTest() {
|
|||
ZoneOffset.UTC,
|
||||
)
|
||||
|
||||
private val snackbarRelayManager = SnackbarRelayManagerImpl()
|
||||
private val mutableSnackbarDataFlow = MutableStateFlow<BitwardenSnackbarData?>(null)
|
||||
private val snackbarRelayManager: SnackbarRelayManager = mockk {
|
||||
every { getSnackbarDataFlow(SnackbarRelay.MY_VAULT_RELAY) } returns mutableSnackbarDataFlow
|
||||
.filterNotNull()
|
||||
every { clearRelayBuffer(SnackbarRelay.MY_VAULT_RELAY) } just runs
|
||||
}
|
||||
|
||||
private val clipboardManager: BitwardenClipboardManager = mockk {
|
||||
every { setText(any<String>()) } just runs
|
||||
|
@ -1802,15 +1808,28 @@ class VaultViewModelTest : BaseViewModelTest() {
|
|||
fun `when SnackbarRelay flow updates, snackbar is shown`() = runTest {
|
||||
val viewModel = createViewModel()
|
||||
val expectedSnackbarData = BitwardenSnackbarData(message = "test message".asText())
|
||||
mutableSnackbarDataFlow.update { expectedSnackbarData }
|
||||
viewModel.eventFlow.test {
|
||||
snackbarRelayManager.sendSnackbarData(
|
||||
data = expectedSnackbarData,
|
||||
relay = SnackbarRelay.MY_VAULT_RELAY,
|
||||
)
|
||||
assertEquals(VaultEvent.ShowSnackbar(expectedSnackbarData), awaitItem())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when account switch action is handled, clear snackbar relay buffer should be called`() =
|
||||
runTest {
|
||||
val viewModel = createViewModel()
|
||||
switchAccountResult = SwitchAccountResult.AccountSwitched
|
||||
viewModel.trySendAction(
|
||||
VaultAction.SwitchAccountClick(
|
||||
accountSummary = mockk() {
|
||||
every { userId } returns "updatedUserId"
|
||||
},
|
||||
),
|
||||
)
|
||||
verify(exactly = 1) {
|
||||
snackbarRelayManager.clearRelayBuffer(SnackbarRelay.MY_VAULT_RELAY)
|
||||
}
|
||||
}
|
||||
private fun createViewModel(): VaultViewModel =
|
||||
VaultViewModel(
|
||||
authRepository = authRepository,
|
||||
|
|
Loading…
Reference in a new issue