mirror of
https://github.com/bitwarden/android.git
synced 2024-11-27 12:00:19 +03:00
Adding Navigation to the verification code screen and skeleton UI (#697)
This commit is contained in:
parent
1a53178137
commit
cd1d326d45
8 changed files with 296 additions and 3 deletions
|
@ -6,6 +6,8 @@ import androidx.navigation.NavOptions
|
||||||
import androidx.navigation.navigation
|
import androidx.navigation.navigation
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.navigateToVaultItemListing
|
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.navigateToVaultItemListing
|
||||||
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.vaultItemListingDestination
|
import com.x8bit.bitwarden.ui.vault.feature.itemlisting.vaultItemListingDestination
|
||||||
|
import com.x8bit.bitwarden.ui.vault.feature.verificationcode.navigateToVerificationCodeScreen
|
||||||
|
import com.x8bit.bitwarden.ui.vault.feature.verificationcode.vaultVerificationCodeDestination
|
||||||
|
|
||||||
const val VAULT_GRAPH_ROUTE: String = "vault_graph"
|
const val VAULT_GRAPH_ROUTE: String = "vault_graph"
|
||||||
|
|
||||||
|
@ -28,6 +30,10 @@ fun NavGraphBuilder.vaultGraph(
|
||||||
onNavigateToVaultItemScreen = onNavigateToVaultItemScreen,
|
onNavigateToVaultItemScreen = onNavigateToVaultItemScreen,
|
||||||
onNavigateToVaultEditItemScreen = onNavigateToVaultEditItemScreen,
|
onNavigateToVaultEditItemScreen = onNavigateToVaultEditItemScreen,
|
||||||
onNavigateToVaultItemListingScreen = { navController.navigateToVaultItemListing(it) },
|
onNavigateToVaultItemListingScreen = { navController.navigateToVaultItemListing(it) },
|
||||||
|
onNavigateToVerificationCodeScreen = {
|
||||||
|
navController.navigateToVerificationCodeScreen()
|
||||||
|
},
|
||||||
|
|
||||||
onDimBottomNavBarRequest = onDimBottomNavBarRequest,
|
onDimBottomNavBarRequest = onDimBottomNavBarRequest,
|
||||||
)
|
)
|
||||||
vaultItemListingDestination(
|
vaultItemListingDestination(
|
||||||
|
@ -35,6 +41,11 @@ fun NavGraphBuilder.vaultGraph(
|
||||||
onNavigateToVaultItemScreen = onNavigateToVaultItemScreen,
|
onNavigateToVaultItemScreen = onNavigateToVaultItemScreen,
|
||||||
onNavigateToVaultAddItemScreen = onNavigateToVaultAddItemScreen,
|
onNavigateToVaultAddItemScreen = onNavigateToVaultAddItemScreen,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
vaultVerificationCodeDestination(
|
||||||
|
onNavigateBack = { navController.popBackStack() },
|
||||||
|
onNavigateToVaultItemScreen = onNavigateToVaultItemScreen,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,10 @@ const val VAULT_ROUTE: String = "vault"
|
||||||
/**
|
/**
|
||||||
* Add vault destination to the nav graph.
|
* Add vault destination to the nav graph.
|
||||||
*/
|
*/
|
||||||
|
@Suppress("LongParameterList")
|
||||||
fun NavGraphBuilder.vaultDestination(
|
fun NavGraphBuilder.vaultDestination(
|
||||||
onNavigateToVaultAddItemScreen: () -> Unit,
|
onNavigateToVaultAddItemScreen: () -> Unit,
|
||||||
|
onNavigateToVerificationCodeScreen: () -> Unit,
|
||||||
onNavigateToVaultItemScreen: (vaultItemId: String) -> Unit,
|
onNavigateToVaultItemScreen: (vaultItemId: String) -> Unit,
|
||||||
onNavigateToVaultEditItemScreen: (vaultItemId: String) -> Unit,
|
onNavigateToVaultEditItemScreen: (vaultItemId: String) -> Unit,
|
||||||
onNavigateToVaultItemListingScreen: (vaultItemType: VaultItemListingType) -> Unit,
|
onNavigateToVaultItemListingScreen: (vaultItemType: VaultItemListingType) -> Unit,
|
||||||
|
@ -26,6 +28,7 @@ fun NavGraphBuilder.vaultDestination(
|
||||||
onNavigateToVaultItemScreen = onNavigateToVaultItemScreen,
|
onNavigateToVaultItemScreen = onNavigateToVaultItemScreen,
|
||||||
onNavigateToVaultEditItemScreen = onNavigateToVaultEditItemScreen,
|
onNavigateToVaultEditItemScreen = onNavigateToVaultEditItemScreen,
|
||||||
onNavigateToVaultItemListingScreen = onNavigateToVaultItemListingScreen,
|
onNavigateToVaultItemListingScreen = onNavigateToVaultItemListingScreen,
|
||||||
|
onNavigateToVerificationCodeScreen = onNavigateToVerificationCodeScreen,
|
||||||
onDimBottomNavBarRequest = onDimBottomNavBarRequest,
|
onDimBottomNavBarRequest = onDimBottomNavBarRequest,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,6 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import com.x8bit.bitwarden.R
|
import com.x8bit.bitwarden.R
|
||||||
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
|
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
|
||||||
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.showNotYetImplementedToast
|
|
||||||
import com.x8bit.bitwarden.ui.platform.components.BasicDialogState
|
import com.x8bit.bitwarden.ui.platform.components.BasicDialogState
|
||||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenAccountActionItem
|
import com.x8bit.bitwarden.ui.platform.components.BitwardenAccountActionItem
|
||||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenAccountSwitcher
|
import com.x8bit.bitwarden.ui.platform.components.BitwardenAccountSwitcher
|
||||||
|
@ -70,6 +69,7 @@ fun VaultScreen(
|
||||||
onNavigateToVaultAddItemScreen: () -> Unit,
|
onNavigateToVaultAddItemScreen: () -> Unit,
|
||||||
onNavigateToVaultItemScreen: (vaultItemId: String) -> Unit,
|
onNavigateToVaultItemScreen: (vaultItemId: String) -> Unit,
|
||||||
onNavigateToVaultEditItemScreen: (vaultItemId: String) -> Unit,
|
onNavigateToVaultEditItemScreen: (vaultItemId: String) -> Unit,
|
||||||
|
onNavigateToVerificationCodeScreen: () -> Unit,
|
||||||
onNavigateToVaultItemListingScreen: (vaultItemType: VaultItemListingType) -> Unit,
|
onNavigateToVaultItemListingScreen: (vaultItemType: VaultItemListingType) -> Unit,
|
||||||
onDimBottomNavBarRequest: (shouldDim: Boolean) -> Unit,
|
onDimBottomNavBarRequest: (shouldDim: Boolean) -> Unit,
|
||||||
intentManager: IntentManager = LocalIntentManager.current,
|
intentManager: IntentManager = LocalIntentManager.current,
|
||||||
|
@ -96,8 +96,7 @@ fun VaultScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
is VaultEvent.NavigateToVerificationCodeScreen -> {
|
is VaultEvent.NavigateToVerificationCodeScreen -> {
|
||||||
// TODO Add Verification codes detail screen (BIT-1338)
|
onNavigateToVerificationCodeScreen()
|
||||||
showNotYetImplementedToast(context = context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is VaultEvent.NavigateToVaultItem -> onNavigateToVaultItemScreen(event.itemId)
|
is VaultEvent.NavigateToVaultItem -> onNavigateToVaultItemScreen(event.itemId)
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.x8bit.bitwarden.ui.vault.feature.verificationcode
|
||||||
|
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.NavGraphBuilder
|
||||||
|
import androidx.navigation.NavOptions
|
||||||
|
import com.x8bit.bitwarden.ui.platform.base.util.composableWithPushTransitions
|
||||||
|
|
||||||
|
private const val VERIFICATION_CODE_ROUTE: String = "verification_code"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the verification code screen to the nav graph.
|
||||||
|
*/
|
||||||
|
fun NavGraphBuilder.vaultVerificationCodeDestination(
|
||||||
|
onNavigateBack: () -> Unit,
|
||||||
|
onNavigateToVaultItemScreen: (String) -> Unit,
|
||||||
|
) {
|
||||||
|
composableWithPushTransitions(
|
||||||
|
route = VERIFICATION_CODE_ROUTE,
|
||||||
|
) {
|
||||||
|
VerificationCodeScreen(
|
||||||
|
onNavigateToVaultItemScreen = onNavigateToVaultItemScreen,
|
||||||
|
onNavigateBack = onNavigateBack,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate to the verification code screen.
|
||||||
|
*/
|
||||||
|
fun NavController.navigateToVerificationCodeScreen(
|
||||||
|
navOptions: NavOptions? = null,
|
||||||
|
) {
|
||||||
|
this.navigate(VERIFICATION_CODE_ROUTE, navOptions)
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.x8bit.bitwarden.ui.vault.feature.verificationcode
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.x8bit.bitwarden.R
|
||||||
|
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
|
||||||
|
import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold
|
||||||
|
import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the verification codes to the user.
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun VerificationCodeScreen(
|
||||||
|
onNavigateBack: () -> Unit,
|
||||||
|
onNavigateToVaultItemScreen: (String) -> Unit,
|
||||||
|
viewModel: VerificationCodeViewModel = hiltViewModel(),
|
||||||
|
) {
|
||||||
|
val state by viewModel.stateFlow.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
|
EventsEffect(viewModel = viewModel) { event ->
|
||||||
|
when (event) {
|
||||||
|
is VerificationCodeEvent.NavigateBack -> onNavigateBack.invoke()
|
||||||
|
is VerificationCodeEvent.NavigateToVaultItem -> onNavigateToVaultItemScreen(event.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||||
|
BitwardenScaffold(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
|
topBar = {
|
||||||
|
BitwardenTopAppBar(
|
||||||
|
title = stringResource(id = R.string.verification_codes),
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
|
navigationIcon = painterResource(id = R.drawable.ic_back),
|
||||||
|
navigationIconContentDescription = stringResource(id = R.string.back),
|
||||||
|
onNavigationIconClick = remember(viewModel) {
|
||||||
|
{ viewModel.trySendAction(VerificationCodeAction.BackClick) }
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) { innerPadding ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(innerPadding)
|
||||||
|
.fillMaxSize()
|
||||||
|
.verticalScroll(rememberScrollState()),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
Text(text = "Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
package com.x8bit.bitwarden.ui.vault.feature.verificationcode
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import androidx.lifecycle.SavedStateHandle
|
||||||
|
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
private const val KEY_STATE = "state"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles [VerificationCodeAction],
|
||||||
|
* and launches [VerificationCodeEvent] for the [VerificationCodeScreen].
|
||||||
|
*/
|
||||||
|
@HiltViewModel
|
||||||
|
class VerificationCodeViewModel @Inject constructor(
|
||||||
|
savedStateHandle: SavedStateHandle,
|
||||||
|
) : BaseViewModel<VerificationCodeState, VerificationCodeEvent, VerificationCodeAction>(
|
||||||
|
initialState = savedStateHandle[KEY_STATE]
|
||||||
|
?: VerificationCodeState(
|
||||||
|
viewState = VerificationCodeState.ViewState.Empty,
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
|
||||||
|
override fun handleAction(action: VerificationCodeAction) {
|
||||||
|
when (action) {
|
||||||
|
is VerificationCodeAction.BackClick -> handleBackClick()
|
||||||
|
is VerificationCodeAction.ItemClick -> handleItemClick(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleBackClick() {
|
||||||
|
sendEvent(
|
||||||
|
event = VerificationCodeEvent.NavigateBack,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleItemClick(action: VerificationCodeAction.ItemClick) {
|
||||||
|
sendEvent(
|
||||||
|
VerificationCodeEvent.NavigateToVaultItem(action.id),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models state of the verification code screen.
|
||||||
|
*
|
||||||
|
* @property viewState indicates what view state the screen is in.
|
||||||
|
*/
|
||||||
|
@Parcelize
|
||||||
|
data class VerificationCodeState(
|
||||||
|
val viewState: ViewState,
|
||||||
|
) : Parcelable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the specific view states for the [VerificationCodeScreen].
|
||||||
|
*/
|
||||||
|
@Parcelize
|
||||||
|
sealed class ViewState : Parcelable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an empty content state for the [VerificationCodeScreen].
|
||||||
|
*/
|
||||||
|
@Parcelize
|
||||||
|
data object Empty : ViewState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models events for the [VerificationCodeScreen].
|
||||||
|
*/
|
||||||
|
sealed class VerificationCodeEvent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate back.
|
||||||
|
*/
|
||||||
|
data object NavigateBack : VerificationCodeEvent()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates to the VaultItemScreen.
|
||||||
|
*
|
||||||
|
* @property id the id of the item to navigate to.
|
||||||
|
*/
|
||||||
|
data class NavigateToVaultItem(val id: String) : VerificationCodeEvent()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models actions for the [VerificationCodeScreen].
|
||||||
|
*/
|
||||||
|
sealed class VerificationCodeAction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click the back button.
|
||||||
|
*/
|
||||||
|
data object BackClick : VerificationCodeAction()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigates to an item.
|
||||||
|
*
|
||||||
|
* @property id the id of the item to navigate to.
|
||||||
|
*/
|
||||||
|
data class ItemClick(val id: String) : VerificationCodeAction()
|
||||||
|
}
|
|
@ -60,6 +60,7 @@ class VaultScreenTest : BaseComposeTest() {
|
||||||
private var onNavigateToVaultEditItemId: String? = null
|
private var onNavigateToVaultEditItemId: String? = null
|
||||||
private var onNavigateToVaultItemListingType: VaultItemListingType? = null
|
private var onNavigateToVaultItemListingType: VaultItemListingType? = null
|
||||||
private var onDimBottomNavBarRequestCalled = false
|
private var onDimBottomNavBarRequestCalled = false
|
||||||
|
private var onNavigateToVerificationCodeScreen = false
|
||||||
private val intentManager = mockk<IntentManager>(relaxed = true)
|
private val intentManager = mockk<IntentManager>(relaxed = true)
|
||||||
|
|
||||||
private val mutableEventFlow = bufferedMutableSharedFlow<VaultEvent>()
|
private val mutableEventFlow = bufferedMutableSharedFlow<VaultEvent>()
|
||||||
|
@ -79,6 +80,7 @@ class VaultScreenTest : BaseComposeTest() {
|
||||||
onNavigateToVaultEditItemScreen = { onNavigateToVaultEditItemId = it },
|
onNavigateToVaultEditItemScreen = { onNavigateToVaultEditItemId = it },
|
||||||
onNavigateToVaultItemListingScreen = { onNavigateToVaultItemListingType = it },
|
onNavigateToVaultItemListingScreen = { onNavigateToVaultItemListingType = it },
|
||||||
onDimBottomNavBarRequest = { onDimBottomNavBarRequestCalled = true },
|
onDimBottomNavBarRequest = { onDimBottomNavBarRequestCalled = true },
|
||||||
|
onNavigateToVerificationCodeScreen = { onNavigateToVerificationCodeScreen = true },
|
||||||
intentManager = intentManager,
|
intentManager = intentManager,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -533,6 +535,30 @@ class VaultScreenTest : BaseComposeTest() {
|
||||||
verify { viewModel.trySendAction(VaultAction.TryAgainClick) }
|
verify { viewModel.trySendAction(VaultAction.TryAgainClick) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `verification code click should call VerificationCodesClick `() {
|
||||||
|
mutableStateFlow.update {
|
||||||
|
it.copy(
|
||||||
|
viewState = DEFAULT_CONTENT_VIEW_STATE.copy(
|
||||||
|
totpItemsCount = 3,
|
||||||
|
),
|
||||||
|
isPremium = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule
|
||||||
|
.onNodeWithText("Verification codes")
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
verify { viewModel.trySendAction(VaultAction.VerificationCodesClick) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `NavigateToVerificationCodeScreen event should call onNavigateToVerificationCodeScreen`() {
|
||||||
|
mutableEventFlow.tryEmit(VaultEvent.NavigateToVerificationCodeScreen)
|
||||||
|
assertTrue(onNavigateToVerificationCodeScreen)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `search icon click should send SearchIconClick action`() {
|
fun `search icon click should send SearchIconClick action`() {
|
||||||
mutableStateFlow.update { it.copy(viewState = VaultState.ViewState.NoItems) }
|
mutableStateFlow.update { it.copy(viewState = VaultState.ViewState.NoItems) }
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.x8bit.bitwarden.ui.vault.feature.verificationcode
|
||||||
|
|
||||||
|
import androidx.lifecycle.SavedStateHandle
|
||||||
|
import app.cash.turbine.test
|
||||||
|
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class VerificationCodeViewModelTest : BaseViewModelTest() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `on BackClick should emit NavigateBack`() = runTest {
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
viewModel.eventFlow.test {
|
||||||
|
viewModel.trySendAction(VerificationCodeAction.BackClick)
|
||||||
|
assertEquals(VerificationCodeEvent.NavigateBack, awaitItem())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `on ItemClick should emit ItemClick`() = runTest {
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
val testId = "testId"
|
||||||
|
|
||||||
|
viewModel.eventFlow.test {
|
||||||
|
viewModel.trySendAction(VerificationCodeAction.ItemClick(testId))
|
||||||
|
assertEquals(VerificationCodeEvent.NavigateToVaultItem(testId), awaitItem())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createViewModel(
|
||||||
|
state: VerificationCodeState? = DEFAULT_STATE,
|
||||||
|
): VerificationCodeViewModel = VerificationCodeViewModel(
|
||||||
|
savedStateHandle = SavedStateHandle().apply { set("state", state) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val DEFAULT_STATE: VerificationCodeState = VerificationCodeState(
|
||||||
|
VerificationCodeState.ViewState.Empty,
|
||||||
|
)
|
Loading…
Reference in a new issue