diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt index 5aee1aea89..d3dbe4af19 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt @@ -1,7 +1,6 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.other import android.content.res.Resources -import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -36,6 +35,7 @@ import com.bitwarden.ui.platform.base.util.standardHorizontalMargin import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar import com.bitwarden.ui.platform.components.button.BitwardenOutlinedButton import com.bitwarden.ui.platform.components.model.CardStyle +import com.bitwarden.ui.platform.components.toggle.BitwardenSwitch import com.bitwarden.ui.platform.components.util.rememberVectorPainter import com.bitwarden.ui.platform.resource.BitwardenDrawable import com.bitwarden.ui.platform.theme.BitwardenTheme @@ -47,7 +47,8 @@ import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenLoadingDialog import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog import com.x8bit.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold -import com.bitwarden.ui.platform.components.toggle.BitwardenSwitch +import com.x8bit.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarHost +import com.x8bit.bitwarden.ui.platform.components.snackbar.rememberBitwardenSnackbarHostState import kotlinx.collections.immutable.toImmutableList /** @@ -60,19 +61,11 @@ fun OtherScreen( viewModel: OtherViewModel = hiltViewModel(), ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() - val context = LocalContext.current + val snackbarHostState = rememberBitwardenSnackbarHostState() EventsEffect(viewModel = viewModel) { event -> when (event) { OtherEvent.NavigateBack -> onNavigateBack.invoke() - is OtherEvent.ShowToast -> { - Toast - .makeText( - context, - event.message(context.resources), - Toast.LENGTH_SHORT, - ) - .show() - } + is OtherEvent.ShowSnackbar -> snackbarHostState.showSnackbar(snackbarData = event.data) } } @@ -99,6 +92,9 @@ fun OtherScreen( }, ) }, + snackbarHost = { + BitwardenSnackbarHost(bitwardenHostState = snackbarHostState) + }, ) { OtherContent( state = state, diff --git a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModel.kt b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModel.kt index 3ba6944e9b..1120e2761a 100644 --- a/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModel.kt +++ b/app/src/main/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModel.kt @@ -12,6 +12,7 @@ import com.x8bit.bitwarden.data.platform.manager.network.NetworkConnectionManage import com.x8bit.bitwarden.data.platform.repository.SettingsRepository import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency import com.x8bit.bitwarden.data.vault.repository.VaultRepository +import com.x8bit.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarData import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.launchIn @@ -152,7 +153,7 @@ class OtherViewModel @Inject constructor( } private fun handleManualVaultSyncReceive() { - sendEvent(OtherEvent.ShowToast(R.string.syncing_complete.asText())) + sendEvent(OtherEvent.ShowSnackbar(R.string.syncing_complete.asText())) } } @@ -203,9 +204,23 @@ sealed class OtherEvent { /** * Show a toast with the given message. */ - data class ShowToast( - val message: Text, - ) : OtherEvent() + data class ShowSnackbar( + val data: BitwardenSnackbarData, + ) : OtherEvent() { + constructor( + message: Text, + messageHeader: Text? = null, + actionLabel: Text? = null, + withDismissAction: Boolean = false, + ) : this( + data = BitwardenSnackbarData( + message = message, + messageHeader = messageHeader, + actionLabel = actionLabel, + withDismissAction = withDismissAction, + ), + ) + } } /** diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt index c672721742..fc21b65086 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt @@ -15,6 +15,7 @@ import com.bitwarden.ui.util.asText import com.bitwarden.ui.util.assertNoDialogExists import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest +import com.x8bit.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarData import io.mockk.every import io.mockk.mockk import io.mockk.verify @@ -84,6 +85,15 @@ class OtherScreenTest : BitwardenComposeTest() { verify { viewModel.trySendAction(OtherAction.BackClick) } } + @Test + fun `on ShowSnackbar should display snackbar content`() { + val message = "message" + val data = BitwardenSnackbarData(message = message.asText()) + composeTestRule.onNodeWithText(text = message).assertDoesNotExist() + mutableEventFlow.tryEmit(OtherEvent.ShowSnackbar(data = data)) + composeTestRule.onNodeWithText(text = message).assertIsDisplayed() + } + @Test fun `on clear clipboard row click should show show clipboard selection dialog`() { composeTestRule diff --git a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModelTest.kt b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModelTest.kt index c08f95309a..16d14a8aa5 100644 --- a/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModelTest.kt +++ b/app/src/test/kotlin/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModelTest.kt @@ -185,13 +185,13 @@ class OtherViewModelTest : BaseViewModelTest() { } @Test - fun `ManualVaultSyncReceive should emit ShowToast`() = runTest { + fun `ManualVaultSyncReceive should emit ShowSnackbar`() = runTest { val newSyncTime = Instant.parse("2023-10-27T12:00:00Z") val viewModel = createViewModel() viewModel.eventFlow.test { mutableVaultLastSyncStateFlow.tryEmit(newSyncTime) assertEquals( - OtherEvent.ShowToast(R.string.syncing_complete.asText()), + OtherEvent.ShowSnackbar(R.string.syncing_complete.asText()), awaitItem(), ) }