mirror of
https://github.com/bitwarden/android.git
synced 2025-12-11 13:57:03 -06:00
PM-27136: Replace FirstTimeSyncSnackbarHost with BitwardenSnackbarHost (#6058)
This commit is contained in:
parent
31e7e05eda
commit
97bb93c18e
@ -1,69 +0,0 @@
|
|||||||
package com.bitwarden.authenticator.ui.authenticator.feature.itemlisting
|
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.SnackbarHost
|
|
||||||
import androidx.compose.material3.SnackbarHostState
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.shadow
|
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
|
||||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a snackbar that says "Account synced from Bitwarden app" with a close action.
|
|
||||||
*
|
|
||||||
* @param state Snackbar state used to show/hide. The message and title from this state are unused.
|
|
||||||
*/
|
|
||||||
@Composable
|
|
||||||
fun FirstTimeSyncSnackbarHost(
|
|
||||||
state: SnackbarHostState,
|
|
||||||
) {
|
|
||||||
SnackbarHost(
|
|
||||||
hostState = state,
|
|
||||||
snackbar = {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(16.dp)
|
|
||||||
.fillMaxWidth()
|
|
||||||
.shadow(elevation = 6.dp)
|
|
||||||
.background(
|
|
||||||
color = BitwardenTheme.colorScheme.background.alert,
|
|
||||||
shape = BitwardenTheme.shapes.snackbar,
|
|
||||||
),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(16.dp)
|
|
||||||
.weight(1f, fill = true),
|
|
||||||
text = stringResource(BitwardenString.account_synced_from_bitwarden_app),
|
|
||||||
style = BitwardenTheme.typography.bodyLarge,
|
|
||||||
color = BitwardenTheme.colorScheme.text.reversed,
|
|
||||||
)
|
|
||||||
IconButton(
|
|
||||||
onClick = { state.currentSnackbarData?.dismiss() },
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(id = BitwardenDrawable.ic_close),
|
|
||||||
contentDescription = stringResource(id = BitwardenString.close),
|
|
||||||
tint = BitwardenTheme.colorScheme.icon.reversed,
|
|
||||||
modifier = Modifier
|
|
||||||
.size(24.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -17,7 +17,6 @@ import androidx.compose.foundation.rememberScrollState
|
|||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.SnackbarHostState
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.rememberTopAppBarState
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
@ -25,7 +24,6 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@ -70,6 +68,8 @@ import com.bitwarden.ui.platform.components.fab.model.ExpandableFabOption
|
|||||||
import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText
|
import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText
|
||||||
import com.bitwarden.ui.platform.components.icon.model.IconData
|
import com.bitwarden.ui.platform.components.icon.model.IconData
|
||||||
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
|
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
|
||||||
|
import com.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarHost
|
||||||
|
import com.bitwarden.ui.platform.components.snackbar.model.rememberBitwardenSnackbarHostState
|
||||||
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
|
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
|
||||||
import com.bitwarden.ui.platform.composition.LocalIntentManager
|
import com.bitwarden.ui.platform.composition.LocalIntentManager
|
||||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||||
@ -79,7 +79,6 @@ import com.bitwarden.ui.platform.resource.BitwardenString
|
|||||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||||
import com.bitwarden.ui.util.asText
|
import com.bitwarden.ui.util.asText
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the item listing screen.
|
* Displays the item listing screen.
|
||||||
@ -108,9 +107,7 @@ fun ItemListingScreen(
|
|||||||
viewModel.trySendAction(ItemListingAction.EnterSetupKeyClick)
|
viewModel.trySendAction(ItemListingAction.EnterSetupKeyClick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = rememberBitwardenSnackbarHostState()
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
EventsEffect(viewModel = viewModel) { event ->
|
EventsEffect(viewModel = viewModel) { event ->
|
||||||
when (event) {
|
when (event) {
|
||||||
is ItemListingEvent.NavigateBack -> onNavigateBack()
|
is ItemListingEvent.NavigateBack -> onNavigateBack()
|
||||||
@ -140,11 +137,8 @@ fun ItemListingScreen(
|
|||||||
intentManager.startBitwardenAccountSettings()
|
intentManager.startBitwardenAccountSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
is ItemListingEvent.ShowFirstTimeSyncSnackbar -> {
|
is ItemListingEvent.ShowSnackbar -> {
|
||||||
// Message property is overridden by FirstTimeSyncSnackbarHost:
|
snackbarHostState.showSnackbar(snackbarData = event.data)
|
||||||
coroutineScope.launch {
|
|
||||||
snackbarHostState.showSnackbar("")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,7 +208,7 @@ fun ItemListingScreen(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
snackbarHost = { FirstTimeSyncSnackbarHost(state = snackbarHostState) },
|
snackbarHost = { BitwardenSnackbarHost(bitwardenHostState = snackbarHostState) },
|
||||||
) {
|
) {
|
||||||
when (val currentState = state.viewState) {
|
when (val currentState = state.viewState) {
|
||||||
is ItemListingState.ViewState.Content -> {
|
is ItemListingState.ViewState.Content -> {
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import com.bitwarden.authenticator.ui.platform.components.listitem.model.Verific
|
|||||||
import com.bitwarden.authenticatorbridge.manager.AuthenticatorBridgeManager
|
import com.bitwarden.authenticatorbridge.manager.AuthenticatorBridgeManager
|
||||||
import com.bitwarden.core.data.repository.model.DataState
|
import com.bitwarden.core.data.repository.model.DataState
|
||||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||||
|
import com.bitwarden.ui.platform.components.snackbar.model.BitwardenSnackbarData
|
||||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||||
import com.bitwarden.ui.util.Text
|
import com.bitwarden.ui.util.Text
|
||||||
@ -263,7 +264,12 @@ class ItemListingViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleFirstTimeUserSync() {
|
private fun handleFirstTimeUserSync() {
|
||||||
sendEvent(ItemListingEvent.ShowFirstTimeSyncSnackbar)
|
sendEvent(
|
||||||
|
event = ItemListingEvent.ShowSnackbar(
|
||||||
|
message = BitwardenString.account_synced_from_bitwarden_app.asText(),
|
||||||
|
withDismissAction = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleAppThemeChangeReceive(appTheme: AppTheme) {
|
private fun handleAppThemeChangeReceive(appTheme: AppTheme) {
|
||||||
@ -887,9 +893,25 @@ sealed class ItemListingEvent {
|
|||||||
) : ItemListingEvent()
|
) : ItemListingEvent()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a Snackbar letting the user know accounts have synced.
|
* Show a Snackbar with the given [data].
|
||||||
*/
|
*/
|
||||||
data object ShowFirstTimeSyncSnackbar : ItemListingEvent()
|
data class ShowSnackbar(
|
||||||
|
val data: BitwardenSnackbarData,
|
||||||
|
) : ItemListingEvent() {
|
||||||
|
constructor(
|
||||||
|
message: Text,
|
||||||
|
messageHeader: Text? = null,
|
||||||
|
actionLabel: Text? = null,
|
||||||
|
withDismissAction: Boolean = false,
|
||||||
|
) : this(
|
||||||
|
data = BitwardenSnackbarData(
|
||||||
|
message = message,
|
||||||
|
messageHeader = messageHeader,
|
||||||
|
actionLabel = actionLabel,
|
||||||
|
withDismissAction = withDismissAction,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -418,8 +418,10 @@ class ItemListingScreenTest : AuthenticatorComposeTest() {
|
|||||||
.onNodeWithText("Account synced from Bitwarden app")
|
.onNodeWithText("Account synced from Bitwarden app")
|
||||||
.assertIsNotDisplayed()
|
.assertIsNotDisplayed()
|
||||||
|
|
||||||
// Send ShowFirstTimeSyncSnackbar event
|
// Send ShowSnackbar event
|
||||||
mutableEventFlow.tryEmit(ItemListingEvent.ShowFirstTimeSyncSnackbar)
|
mutableEventFlow.tryEmit(
|
||||||
|
ItemListingEvent.ShowSnackbar(message = "Account synced from Bitwarden app".asText()),
|
||||||
|
)
|
||||||
|
|
||||||
// Make sure the snackbar is showing:
|
// Make sure the snackbar is showing:
|
||||||
composeTestRule
|
composeTestRule
|
||||||
|
|||||||
@ -442,11 +442,17 @@ class ItemListingViewModelTest : BaseViewModelTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `on FirstTimeUserSyncReceive should emit ShowFirstTimeSyncSnackbar`() = runTest {
|
fun `on FirstTimeUserSyncReceive should emit ShowSnackbar`() = runTest {
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
viewModel.eventFlow.test {
|
viewModel.eventFlow.test {
|
||||||
firstTimeAccountSyncChannel.send(Unit)
|
firstTimeAccountSyncChannel.send(Unit)
|
||||||
assertEquals(ItemListingEvent.ShowFirstTimeSyncSnackbar, awaitItem())
|
assertEquals(
|
||||||
|
ItemListingEvent.ShowSnackbar(
|
||||||
|
message = BitwardenString.account_synced_from_bitwarden_app.asText(),
|
||||||
|
withDismissAction = true,
|
||||||
|
),
|
||||||
|
awaitItem(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.displayCutout
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.offset
|
|
||||||
import androidx.compose.foundation.layout.only
|
import androidx.compose.foundation.layout.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.union
|
import androidx.compose.foundation.layout.union
|
||||||
@ -73,10 +72,13 @@ fun BitwardenSnackbar(
|
|||||||
.clickable(
|
.clickable(
|
||||||
enabled = !bitwardenSnackbarData.withDismissAction,
|
enabled = !bitwardenSnackbarData.withDismissAction,
|
||||||
onClick = onDismiss,
|
onClick = onDismiss,
|
||||||
)
|
),
|
||||||
.padding(16.dp),
|
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.weight(weight = 1f)) {
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 16.dp, bottom = 16.dp, start = 16.dp)
|
||||||
|
.weight(weight = 1f),
|
||||||
|
) {
|
||||||
bitwardenSnackbarData.messageHeader?.let {
|
bitwardenSnackbarData.messageHeader?.let {
|
||||||
Text(
|
Text(
|
||||||
text = it(),
|
text = it(),
|
||||||
@ -111,7 +113,6 @@ fun BitwardenSnackbar(
|
|||||||
vectorIconRes = BitwardenDrawable.ic_close,
|
vectorIconRes = BitwardenDrawable.ic_close,
|
||||||
contentDescription = stringResource(BitwardenString.close),
|
contentDescription = stringResource(BitwardenString.close),
|
||||||
contentColor = BitwardenTheme.colorScheme.icon.reversed,
|
contentColor = BitwardenTheme.colorScheme.icon.reversed,
|
||||||
modifier = Modifier.offset(x = 12.dp, y = (-12).dp),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user