From a80542d5dac166966bcd2f349545fcaed77f36bd Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 18 Nov 2024 16:30:50 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../DefaultOnboardingMultiWalletComponent.kt | 96 ++++++++++++++----- .../backup/MultiWalletBackupComponent.kt | 8 +- .../backup/model/MultiWalletBackupModel.kt | 67 ++++++------- .../impl/child/backup/ui/MultiWalletBackup.kt | 82 ++++------------ .../backup/ui/state/MultiWalletBackupUM.kt | 38 +++----- .../Wallet1ChooseOptionComponent.kt | 26 +++++ .../chooseoption/ui/Wallet1ChooseOption.kt | 67 +++++++++++++ .../MultiWalletCreateWalletComponent.kt | 5 +- .../model/MultiWalletCreateWalletModel.kt | 31 +++++- .../ui/MultiWalletCreateWallet.kt | 51 ++++++++-- .../ui/state/MultiWalletCreateWalletUM.kt | 4 +- .../impl/model/OnboardingMultiWalletState.kt | 13 ++- .../v2/multiwallet/impl/model/Utils.kt | 2 + .../impl/ui/OnboardingMultiWallet.kt | 10 +- .../v2/multiwallet/impl/ui/WalletArtwork.kt | 23 +++++ 15 files changed, 354 insertions(+), 169 deletions(-) create mode 100644 features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/Wallet1ChooseOptionComponent.kt create mode 100644 features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/ui/Wallet1ChooseOption.kt diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/DefaultOnboardingMultiWalletComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/DefaultOnboardingMultiWalletComponent.kt index 846e1f0d53..97c2f1e5df 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/DefaultOnboardingMultiWalletComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/DefaultOnboardingMultiWalletComponent.kt @@ -10,6 +10,7 @@ import com.arkivanov.decompose.extensions.compose.jetpack.stack.animation.stackA import com.arkivanov.decompose.extensions.compose.jetpack.subscribeAsState import com.arkivanov.decompose.router.stack.* import com.arkivanov.decompose.value.Value +import com.arkivanov.essenty.instancekeeper.getOrCreateSimple import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.decompose.context.childByContext import com.tangem.core.decompose.model.getOrCreateModel @@ -19,10 +20,13 @@ import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletCo import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.MultiWalletBackupComponent +import com.tangem.features.onboarding.v2.multiwallet.impl.child.chooseoption.Wallet1ChooseOptionComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.MultiWalletCreateWalletComponent import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletModel import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState +import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState.Step.* import com.tangem.features.onboarding.v2.multiwallet.impl.ui.OnboardingMultiWallet +import com.tangem.features.onboarding.v2.multiwallet.impl.ui.WalletArtworksState import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -35,6 +39,18 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor private val model: OnboardingMultiWalletModel = getOrCreateModel(params) private val stackNavigation = StackNavigation() + private val artworksState = instanceKeeper.getOrCreateSimple { + MutableStateFlow( + when (model.state.value.currentStep) { + CreateWallet -> WalletArtworksState.Folded + ChooseBackupOption -> WalletArtworksState.Fan + SeedPhrase -> WalletArtworksState.Hidden + AddBackupDevice -> WalletArtworksState.Unfold(WalletArtworksState.Unfold.Step.First) + FinishBackup -> WalletArtworksState.Stack() + Done -> error("Done state should not be used as starting state") + }, + ) + } override val innerNavigation: InnerNavigation = object : InnerNavigation { override val state = MutableStateFlow( @@ -47,50 +63,84 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor } } - private val childStack: Value> = childStack( - key = "innerStack", - source = stackNavigation, - serializer = null, - initialConfiguration = model.state.value.currentStep, - handleBackButton = true, - childFactory = { configuration, factoryContext -> createChild(configuration, childByContext(factoryContext)) }, - ) + private val childStack: Value> = + childStack( + key = "innerStack", + source = stackNavigation, + serializer = null, + initialConfiguration = model.state.value.currentStep, + handleBackButton = true, + childFactory = { configuration, factoryContext -> + createChild( + configuration, + childByContext(factoryContext), + ) + }, + ) private fun createChild( step: OnboardingMultiWalletState.Step, childContext: AppComponentContext, ): MultiWalletChildComponent { return when (step) { - OnboardingMultiWalletState.Step.CreateWallet -> MultiWalletCreateWalletComponent( + CreateWallet -> MultiWalletCreateWalletComponent( context = childContext, params = MultiWalletChildParams( multiWalletState = model.state, parentParams = params, ), - onDone = ::onStepDone, + onNextStep = ::handleNavigationEvent, ) - OnboardingMultiWalletState.Step.AddBackupDevice -> MultiWalletBackupComponent( + ChooseBackupOption -> Wallet1ChooseOptionComponent( + context = childContext, + onNextStep = ::handleNavigationEvent, + ) + SeedPhrase -> TODO() + AddBackupDevice -> MultiWalletBackupComponent( context = childContext, params = MultiWalletChildParams( multiWalletState = model.state, parentParams = params, ), - onDone = ::onStepDone, + onEvent = ::handleBackupComponentEvent, ) - OnboardingMultiWalletState.Step.FinishBackup -> TODO() - OnboardingMultiWalletState.Step.Done -> TODO() + FinishBackup -> TODO() + Done -> TODO() } } - private fun onStepDone() { - when (model.state.value.currentStep) { - OnboardingMultiWalletState.Step.CreateWallet -> { - stackNavigation.push(OnboardingMultiWalletState.Step.AddBackupDevice) - // innerNavigation.state.value TODO + fun handleNavigationEvent(nextStep: OnboardingMultiWalletState.Step) { + when (nextStep) { + ChooseBackupOption -> { + artworksState.value = WalletArtworksState.Fan + } + SeedPhrase -> { + artworksState.value = WalletArtworksState.Hidden + } + AddBackupDevice -> { + artworksState.value = WalletArtworksState.Unfold(WalletArtworksState.Unfold.Step.First) + } + FinishBackup -> { + } + Done -> { + // TODO + } + else -> return + } + stackNavigation.push(nextStep) + } + + fun handleBackupComponentEvent(event: MultiWalletBackupComponent.Event) { + when (event) { + MultiWalletBackupComponent.Event.Done -> { + // TODO navigate to finalize + } + MultiWalletBackupComponent.Event.OneDeviceAdded -> { + artworksState.value = WalletArtworksState.Unfold(WalletArtworksState.Unfold.Step.Second) + } + MultiWalletBackupComponent.Event.TwoDeviceAdded -> { + artworksState.value = WalletArtworksState.Unfold(WalletArtworksState.Unfold.Step.Third) } - OnboardingMultiWalletState.Step.AddBackupDevice -> TODO() - OnboardingMultiWalletState.Step.FinishBackup -> TODO() - OnboardingMultiWalletState.Step.Done -> TODO() } } @@ -98,10 +148,12 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor override fun Content(modifier: Modifier) { val stackState by childStack.subscribeAsState() val state by model.uiState.collectAsStateWithLifecycle() + val artworksState by artworksState.collectAsStateWithLifecycle() OnboardingMultiWallet( state = state, modifier = modifier, + artworksState = artworksState, childContent = { mdfr -> Children( stack = stackState, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/MultiWalletBackupComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/MultiWalletBackupComponent.kt index f68f4741b3..a60cfcb3fa 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/MultiWalletBackupComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/MultiWalletBackupComponent.kt @@ -18,7 +18,7 @@ import kotlinx.coroutines.launch class MultiWalletBackupComponent( context: AppComponentContext, params: MultiWalletChildParams, - onDone: () -> Unit, + onEvent: (event: Event) -> Unit, ) : AppComponentContext by context, MultiWalletChildComponent { private val model: MultiWalletBackupModel = getOrCreateModel(params) @@ -29,7 +29,7 @@ class MultiWalletBackupComponent( ) componentScope.launch { - model.onDoneFlow.collect { onDone() } + model.eventFlow.collect(onEvent) } } @@ -42,4 +42,8 @@ class MultiWalletBackupComponent( state = state, ) } + + enum class Event { + Done, OneDeviceAdded, TwoDeviceAdded + } } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt index 66ffa8ff7f..59ea93d2be 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt @@ -11,6 +11,7 @@ import com.tangem.domain.card.repository.CardSdkConfigRepository import com.tangem.domain.models.scan.ProductType import com.tangem.features.onboarding.v2.impl.R import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams +import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.MultiWalletBackupComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.backupCardAttestationFailedDialog import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.resetBackupCardDialog import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.state.MultiWalletBackupUM @@ -45,35 +46,31 @@ class MultiWalletBackupModel @Inject constructor( private val _uiState = MutableStateFlow( when (scanResponse.productType) { - ProductType.Wallet -> getWallet1State() + ProductType.Wallet, ProductType.Wallet2, ProductType.Ring, - -> MultiWalletBackupUM.Wallet2( - isRing = scanResponse.productType == ProductType.Ring, - backupAdded = false, // backupService.hasIncompletedBackup, - onAddBackupClick = {}, - onFinalizeButtonClick = {}, - ) + -> getInitState() else -> error("Type: ${scanResponse.productType.name} is not supported!") }, ) val uiState: StateFlow = _uiState - val onDoneFlow = MutableSharedFlow() + val eventFlow = MutableSharedFlow() - private fun getWallet1State(): MultiWalletBackupUM.Wallet1 { + private fun getInitState(): MultiWalletBackupUM { return when (backupService.currentState) { BackupService.State.Preparing -> { - MultiWalletBackupUM.Wallet1( + MultiWalletBackupUM( title = resourceReference(R.string.onboarding_title_no_backup_cards), bodyText = resourceReference(R.string.onboarding_subtitle_no_backup_cards), - showFinalizeButton = false, + finalizeButtonEnabled = false, addBackupButtonEnabled = true, addBackupButtonLoading = false, - artworkNumberOfBackupCards = 0, - onAddBackupClick = ::startBackupWallet1, + onAddBackupClick = ::startBackupWallet, onFinalizeButtonClick = {}, - onSkipButtonClick = { onDoneFlow.tryEmit(Unit) }, + onSkipButtonClick = { + // eventFlow.tryEmit(Unit) + }, ) } is BackupService.State.FinalizingBackupCard -> TODO() @@ -82,7 +79,7 @@ class MultiWalletBackupModel @Inject constructor( } } - private fun startBackupWallet1() { + private fun startBackupWallet() { backupService.discardSavedBackup() val primaryCard = scanResponse.primaryCard @@ -95,35 +92,37 @@ class MultiWalletBackupModel @Inject constructor( } } - private fun setNumberOfBackupCardsWallet1(number: Int) { - // set state for Wallet1 for adding backup cards and disable button if there is more than 2 backup cards + private fun setNumberOfBackupCards(number: Int) { + // set state for adding backup cards and disable button if there is more than 2 backup cards _uiState.update { st -> - if (st !is MultiWalletBackupUM.Wallet1) return@update st - when (number) { 0 -> { st.copy( title = resourceReference(R.string.onboarding_title_no_backup_cards), bodyText = resourceReference(R.string.onboarding_subtitle_no_backup_cards), - artworkNumberOfBackupCards = 0, addBackupButtonEnabled = true, ) } 1 -> { + modelScope.launch { + eventFlow.emit(MultiWalletBackupComponent.Event.OneDeviceAdded) + } st.copy( title = resourceReference(R.string.onboarding_title_one_backup_card), bodyText = resourceReference(R.string.onboarding_subtitle_one_backup_card), - artworkNumberOfBackupCards = 1, addBackupButtonEnabled = true, - showFinalizeButton = true, + finalizeButtonEnabled = true, ) } 2 -> { + modelScope.launch { + eventFlow.emit(MultiWalletBackupComponent.Event.TwoDeviceAdded) + } st.copy( title = resourceReference(R.string.onboarding_title_two_backup_cards), bodyText = resourceReference(R.string.onboarding_subtitle_two_backup_cards), - artworkNumberOfBackupCards = 2, addBackupButtonEnabled = false, + finalizeButtonEnabled = true, ) } else -> st.copy(addBackupButtonEnabled = false) @@ -132,7 +131,7 @@ class MultiWalletBackupModel @Inject constructor( } private fun addBackupCardWithService() { - updateWallet1State { st -> + _uiState.update { st -> st.copy(addBackupButtonLoading = true) } @@ -140,38 +139,37 @@ class MultiWalletBackupModel @Inject constructor( backupService.skipCompatibilityChecks = false cardSdkConfigRepository.sdk.config.filter.cardIdFilter = null - updateWallet1State { st -> + _uiState.update { st -> st.copy(addBackupButtonLoading = false) } when (result) { is CompletionResult.Success -> { - // TODO change artwork state.update { it.copy( backupCards = it.backupCards + result.data, backupCardsNumber = it.backupCardsNumber + 1, ) } - setNumberOfBackupCardsWallet1(state.value.backupCardsNumber) + setNumberOfBackupCards(state.value.backupCardsNumber) } is CompletionResult.Failure -> { when (val error = result.error) { is TangemSdkError.BackupFailedNotEmptyWallets -> { - updateWallet1State { st -> + _uiState.update { st -> st.copy( dialog = resetBackupCardDialog( onReset = { resetBackupCard(cardId = error.cardId) }, - onDismiss = { updateWallet1State { it.copy(dialog = null) } }, + onDismiss = { _uiState.update { it.copy(dialog = null) } }, ), ) } } is TangemSdkError.IssuerSignatureLoadingFailed -> { - updateWallet1State { st -> + _uiState.update { st -> st.copy( dialog = backupCardAttestationFailedDialog( - onDismiss = { updateWallet1State { it.copy(dialog = null) } }, + onDismiss = { _uiState.update { it.copy(dialog = null) } }, ), ) } @@ -191,11 +189,4 @@ class MultiWalletBackupModel @Inject constructor( ) } } - - private fun updateWallet1State(block: (MultiWalletBackupUM.Wallet1) -> MultiWalletBackupUM.Wallet1) { - _uiState.update { state -> - if (state !is MultiWalletBackupUM.Wallet1) return@update state - block(state) - } - } } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/ui/MultiWalletBackup.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/ui/MultiWalletBackup.kt index a8a1e22522..9bf7b55ef5 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/ui/MultiWalletBackup.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/ui/MultiWalletBackup.kt @@ -24,10 +24,7 @@ fun MultiWalletBackup(state: MultiWalletBackupUM, modifier: Modifier = Modifier) .fillMaxSize() .navigationBarsPadding(), ) { - when (state) { - is MultiWalletBackupUM.Wallet1 -> Wallet1Content(state) - is MultiWalletBackupUM.Wallet2 -> TODO() - } + Content(state) } val dialog = state.dialog @@ -54,7 +51,7 @@ fun MultiWalletBackup(state: MultiWalletBackupUM, modifier: Modifier = Modifier) } @Composable -private fun ColumnScope.Wallet1Content(state: MultiWalletBackupUM.Wallet1) { +private fun ColumnScope.Content(state: MultiWalletBackupUM) { Column( Modifier .fillMaxWidth() @@ -62,8 +59,6 @@ private fun ColumnScope.Wallet1Content(state: MultiWalletBackupUM.Wallet1) { .weight(1f), horizontalAlignment = Alignment.CenterHorizontally, ) { - // artwork - Text( text = state.title.resolveReference(), style = TangemTheme.typography.h2, @@ -81,45 +76,25 @@ private fun ColumnScope.Wallet1Content(state: MultiWalletBackupUM.Wallet1) { ) } - if (state.showFinalizeButton) { - SecondaryButtonIconEnd( - modifier = Modifier - .padding(start = 16.dp, end = 16.dp, bottom = 12.dp) - .fillMaxWidth(), - iconResId = R.drawable.ic_tangem_24, - enabled = state.addBackupButtonEnabled, - showProgress = state.addBackupButtonLoading, - text = stringResource(R.string.onboarding_button_add_backup_card), - onClick = state.onAddBackupClick, - ) + SecondaryButtonIconEnd( + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 12.dp) + .fillMaxWidth(), + iconResId = R.drawable.ic_tangem_24, + enabled = state.addBackupButtonEnabled, + showProgress = state.addBackupButtonLoading, + text = stringResource(R.string.onboarding_button_add_backup_card), + onClick = state.onAddBackupClick, + ) - PrimaryButton( - modifier = Modifier - .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) - .fillMaxWidth(), - text = stringResource(R.string.onboarding_button_finalize_backup), - onClick = state.onFinalizeButtonClick, - ) - } else { - PrimaryButtonIconEnd( - modifier = Modifier - .padding(start = 16.dp, end = 16.dp, bottom = 12.dp) - .fillMaxWidth(), - iconResId = R.drawable.ic_tangem_24, - enabled = state.addBackupButtonEnabled, - showProgress = state.addBackupButtonLoading, - text = stringResource(R.string.onboarding_button_add_backup_card), - onClick = state.onAddBackupClick, - ) - - SecondaryButton( - modifier = Modifier - .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) - .fillMaxWidth(), - text = stringResource(R.string.onboarding_button_skip_backup), - onClick = state.onSkipButtonClick, - ) - } + PrimaryButton( + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) + .fillMaxWidth(), + text = stringResource(R.string.onboarding_button_finalize_backup), + enabled = state.finalizeButtonEnabled, + onClick = state.onFinalizeButtonClick, + ) } @Preview @@ -127,25 +102,10 @@ private fun ColumnScope.Wallet1Content(state: MultiWalletBackupUM.Wallet1) { private fun PreviewWallet1() { TangemThemePreview { MultiWalletBackup( - state = MultiWalletBackupUM.Wallet1( + state = MultiWalletBackupUM( title = stringReference("Title"), bodyText = stringReference("Body body body"), ), ) } -} - -@Preview -@Composable -private fun PreviewWallet2() { - TangemThemePreview { - MultiWalletBackup( - state = MultiWalletBackupUM.Wallet2( - isRing = false, - backupAdded = true, - onAddBackupClick = {}, - onFinalizeButtonClick = {}, - ), - ) - } } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/ui/state/MultiWalletBackupUM.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/ui/state/MultiWalletBackupUM.kt index cb3351c3db..96cc144862 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/ui/state/MultiWalletBackupUM.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/ui/state/MultiWalletBackupUM.kt @@ -1,37 +1,21 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.state -import androidx.annotation.IntRange import androidx.compose.runtime.Immutable import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.stringReference @Immutable -sealed class MultiWalletBackupUM { - - abstract val dialog: MultiWalletBackupUMDialog? - - data class Wallet1( - val title: TextReference = stringReference(""), - val bodyText: TextReference = stringReference(""), - val addBackupButtonEnabled: Boolean = true, - val addBackupButtonLoading: Boolean = false, - val showFinalizeButton: Boolean = false, - val oneBackupAdded: Boolean = false, - @IntRange(0, 2) val artworkNumberOfBackupCards: Int = 0, // highlights cards on 0, 1, 2 - val onAddBackupClick: () -> Unit = {}, - val onFinalizeButtonClick: () -> Unit = {}, - val onSkipButtonClick: () -> Unit = {}, - override val dialog: MultiWalletBackupUMDialog? = null, - ) : MultiWalletBackupUM() - - data class Wallet2( - val isRing: Boolean, - val backupAdded: Boolean, - val onAddBackupClick: () -> Unit, - val onFinalizeButtonClick: () -> Unit, - override val dialog: MultiWalletBackupUMDialog? = null, - ) : MultiWalletBackupUM() -} +data class MultiWalletBackupUM( + val title: TextReference = stringReference(""), + val bodyText: TextReference = stringReference(""), + val addBackupButtonEnabled: Boolean = true, + val addBackupButtonLoading: Boolean = false, + val finalizeButtonEnabled: Boolean = false, + val onAddBackupClick: () -> Unit = {}, + val onFinalizeButtonClick: () -> Unit = {}, + val onSkipButtonClick: () -> Unit = {}, + val dialog: MultiWalletBackupUMDialog? = null, +) data class MultiWalletBackupUMDialog( val title: TextReference, diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/Wallet1ChooseOptionComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/Wallet1ChooseOptionComponent.kt new file mode 100644 index 0000000000..11b7cacc0e --- /dev/null +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/Wallet1ChooseOptionComponent.kt @@ -0,0 +1,26 @@ +package com.tangem.features.onboarding.v2.multiwallet.impl.child.chooseoption + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildComponent +import com.tangem.features.onboarding.v2.multiwallet.impl.child.chooseoption.ui.Wallet1ChooseOption +import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState + +class Wallet1ChooseOptionComponent( + context: AppComponentContext, + private val onNextStep: (OnboardingMultiWalletState.Step) -> Unit, +) : AppComponentContext by context, MultiWalletChildComponent { + + @Composable + override fun Content(modifier: Modifier) { + Wallet1ChooseOption( + onBackupClick = { + onNextStep(OnboardingMultiWalletState.Step.AddBackupDevice) + }, + onScipClick = { + onNextStep(OnboardingMultiWalletState.Step.Done) + }, + ) + } +} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/ui/Wallet1ChooseOption.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/ui/Wallet1ChooseOption.kt new file mode 100644 index 0000000000..d2aa92ed93 --- /dev/null +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/chooseoption/ui/Wallet1ChooseOption.kt @@ -0,0 +1,67 @@ +package com.tangem.features.onboarding.v2.multiwallet.impl.child.chooseoption.ui + +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.PrimaryButtonIconEnd +import com.tangem.core.ui.components.SecondaryButton +import com.tangem.core.ui.res.TangemTheme +import com.tangem.features.onboarding.v2.impl.R + +@Composable +fun Wallet1ChooseOption(onScipClick: () -> Unit, onBackupClick: () -> Unit, modifier: Modifier = Modifier) { + Column( + modifier = modifier + .fillMaxSize() + .navigationBarsPadding(), + verticalArrangement = Arrangement.Bottom, + ) { + // val pagerState = rememberPagerState(pageCount = { 10 }) // TODO [REDACTED_TASK_KEY] + + Column( + Modifier + .fillMaxWidth() + .padding(start = 32.dp, end = 32.dp, bottom = 24.dp) + .weight(1f), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = stringResource(R.string.onboarding_create_wallet_header), + style = TangemTheme.typography.h2, + color = TangemTheme.colors.text.primary1, + textAlign = TextAlign.Center, + modifier = Modifier.padding(top = 16.dp), + ) + + Text( + text = stringResource(R.string.onboarding_create_wallet_body), + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.secondary, + textAlign = TextAlign.Center, + modifier = Modifier.padding(top = 12.dp), + ) + } + + PrimaryButtonIconEnd( + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 12.dp) + .fillMaxWidth(), + iconResId = R.drawable.ic_tangem_24, + text = stringResource(R.string.onboarding_button_backup_now), + onClick = onBackupClick, + ) + + SecondaryButton( + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) + .fillMaxWidth(), + text = stringResource(R.string.onboarding_button_skip_backup), + onClick = onScipClick, + ) + } +} \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/MultiWalletCreateWalletComponent.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/MultiWalletCreateWalletComponent.kt index 713eb54a50..0ab365e362 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/MultiWalletCreateWalletComponent.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/MultiWalletCreateWalletComponent.kt @@ -12,12 +12,13 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChild import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildComponent import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.model.MultiWalletCreateWalletModel import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui.MultiWalletCreateWallet +import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState import kotlinx.coroutines.launch class MultiWalletCreateWalletComponent( context: AppComponentContext, params: MultiWalletChildParams, - onDone: () -> Unit, + onNextStep: (OnboardingMultiWalletState.Step) -> Unit, ) : AppComponentContext by context, MultiWalletChildComponent { private val model: MultiWalletCreateWalletModel = getOrCreateModel(params) @@ -28,7 +29,7 @@ class MultiWalletCreateWalletComponent( ) componentScope.launch { - model.onDone.collect { onDone() } + model.onDone.collect(onNextStep) } } diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt index e32cbde7d2..88bb4abd0d 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/model/MultiWalletCreateWalletModel.kt @@ -5,12 +5,15 @@ import com.tangem.common.core.TangemSdkError import com.tangem.core.decompose.di.ComponentScoped import com.tangem.core.decompose.model.Model import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.core.ui.extensions.resourceReference import com.tangem.domain.card.repository.CardRepository import com.tangem.domain.feedback.GetCardInfoUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.FeedbackEmailType +import com.tangem.features.onboarding.v2.impl.R import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui.state.MultiWalletCreateWalletUM +import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState import com.tangem.sdk.api.TangemSdkManager import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableSharedFlow @@ -36,15 +39,29 @@ class MultiWalletCreateWalletModel @Inject constructor( private val _uiState = MutableStateFlow( MultiWalletCreateWalletUM( + title = if (params.parentParams.withSeedPhraseFlow) { + resourceReference(R.string.onboarding_create_wallet_options_title) + } else { + resourceReference(R.string.onboarding_create_wallet_header) + }, + bodyText = if (params.parentParams.withSeedPhraseFlow) { + resourceReference(R.string.onboarding_create_wallet_options_message) + } else { + resourceReference(R.string.onboarding_create_wallet_body) + }, onCreateWalletClick = { createWallet(false) }, - showSeedPhraseOption = params.parentParams.withSeedPhraseFlow, - onOtherOptionsClick = { /* navigate */ }, + showOtherOptionsButton = params.parentParams.withSeedPhraseFlow, + onOtherOptionsClick = { + modelScope.launch { + onDone.emit(OnboardingMultiWalletState.Step.SeedPhrase) + } + }, dialog = null, ), ) val uiState: StateFlow = _uiState - val onDone = MutableSharedFlow() + val onDone = MutableSharedFlow() private fun createWallet(shouldReset: Boolean) { modelScope.launch { @@ -66,7 +83,13 @@ class MultiWalletCreateWalletModel @Inject constructor( } cardRepository.startCardActivation(cardId = result.data.card.cardId) - onDone.emit(Unit) + + if (params.parentParams.withSeedPhraseFlow) { + onDone.emit(OnboardingMultiWalletState.Step.AddBackupDevice) + } else { + onDone.emit(OnboardingMultiWalletState.Step.ChooseBackupOption) + } + // TODO // Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully()) } diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/MultiWalletCreateWallet.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/MultiWalletCreateWallet.kt index b20e13c3af..6c881297c3 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/MultiWalletCreateWallet.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/MultiWalletCreateWallet.kt @@ -1,9 +1,12 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui import androidx.compose.foundation.layout.* +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.tangem.core.ui.components.BasicDialog @@ -11,6 +14,8 @@ import com.tangem.core.ui.components.DialogButtonUM import com.tangem.core.ui.components.PrimaryButtonIconEnd import com.tangem.core.ui.components.SecondaryButton import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.features.onboarding.v2.impl.R import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui.state.MultiWalletCreateWalletUM @@ -40,6 +45,30 @@ fun MultiWalletCreateWallet(state: MultiWalletCreateWalletUM, modifier: Modifier .navigationBarsPadding(), verticalArrangement = Arrangement.Bottom, ) { + Column( + Modifier + .fillMaxWidth() + .padding(start = 32.dp, end = 32.dp, bottom = 24.dp) + .weight(1f), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = state.title.resolveReference(), + style = TangemTheme.typography.h2, + color = TangemTheme.colors.text.primary1, + textAlign = TextAlign.Center, + modifier = Modifier.padding(top = 16.dp), + ) + + Text( + text = state.bodyText.resolveReference(), + style = TangemTheme.typography.body1, + color = TangemTheme.colors.text.secondary, + textAlign = TextAlign.Center, + modifier = Modifier.padding(top = 12.dp), + ) + } + PrimaryButtonIconEnd( modifier = Modifier .padding(start = 16.dp, end = 16.dp, bottom = 12.dp) @@ -49,24 +78,28 @@ fun MultiWalletCreateWallet(state: MultiWalletCreateWalletUM, modifier: Modifier onClick = state.onCreateWalletClick, ) - SecondaryButton( - modifier = Modifier - .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) - .fillMaxWidth(), - text = stringResource(R.string.onboarding_create_wallet_options_button_options), - onClick = state.onOtherOptionsClick, - ) + if (state.showOtherOptionsButton) { + SecondaryButton( + modifier = Modifier + .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) + .fillMaxWidth(), + text = stringResource(R.string.onboarding_create_wallet_options_button_options), + onClick = state.onOtherOptionsClick, + ) + } } } -@Preview +@Preview(showBackground = true) @Composable private fun Preview() { TangemThemePreview { MultiWalletCreateWallet( state = MultiWalletCreateWalletUM( + title = stringReference("Title"), + bodyText = stringReference("Body body body"), onCreateWalletClick = {}, - showSeedPhraseOption = true, + showOtherOptionsButton = true, onOtherOptionsClick = {}, dialog = null, ), diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/state/MultiWalletCreateWalletUM.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/state/MultiWalletCreateWalletUM.kt index c761e1f481..59a5a9ace0 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/state/MultiWalletCreateWalletUM.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/createwallet/ui/state/MultiWalletCreateWalletUM.kt @@ -3,8 +3,10 @@ package com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui import com.tangem.core.ui.extensions.TextReference data class MultiWalletCreateWalletUM( + val title: TextReference, + val bodyText: TextReference, + val showOtherOptionsButton: Boolean, val onCreateWalletClick: () -> Unit, - val showSeedPhraseOption: Boolean, val onOtherOptionsClick: () -> Unit, val dialog: Dialog?, ) { diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletState.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletState.kt index 0c3ecc83ea..14260553a8 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletState.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/OnboardingMultiWalletState.kt @@ -6,7 +6,18 @@ data class OnboardingMultiWalletState( val currentStep: Step, val currentScanResponse: ScanResponse, ) { + /** + * Wallet1 + * CreateWallet -> ChooseBackupOption -> AddBackupDevice -> FinishBackup -> [Done] + * | + * -> [Done] + * + * Wallet2/Ring + * CreateWallet -> SeedPhrase -> AddBackupDevice -> FinishBackup -> [Done] + * | + * -> AddBackupDevice -> FinishBackup -> [Done] + */ enum class Step { - CreateWallet, AddBackupDevice, FinishBackup, Done + CreateWallet, ChooseBackupOption, SeedPhrase, AddBackupDevice, FinishBackup, Done } } \ No newline at end of file diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/Utils.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/Utils.kt index 73573ab2a6..ec2a1c3848 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/Utils.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/model/Utils.kt @@ -7,6 +7,8 @@ import com.tangem.features.onboarding.v2.impl.R fun screenTitleByStep(step: OnboardingMultiWalletState.Step): TextReference = when (step) { OnboardingMultiWalletState.Step.CreateWallet -> resourceReference(R.string.onboarding_create_wallet_header) + OnboardingMultiWalletState.Step.ChooseBackupOption -> TODO() + OnboardingMultiWalletState.Step.SeedPhrase -> TODO() OnboardingMultiWalletState.Step.AddBackupDevice -> resourceReference(R.string.onboarding_navbar_title_creating_backup) OnboardingMultiWalletState.Step.FinishBackup -> TODO() diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/OnboardingMultiWallet.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/OnboardingMultiWallet.kt index 9a3b0efcec..f26fbb2cd4 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/OnboardingMultiWallet.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/OnboardingMultiWallet.kt @@ -17,6 +17,7 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.ui.state.OnboardingMul @Suppress("MagicNumber") internal fun OnboardingMultiWallet( state: OnboardingMultiWalletUM, + artworksState: WalletArtworksState, modifier: Modifier = Modifier, childContent: @Composable (Modifier) -> Unit = {}, ) { @@ -32,11 +33,15 @@ internal fun OnboardingMultiWallet( .padding(horizontal = 34.dp) .padding(top = 20.dp) .fillMaxWidth(), - state = WalletArtworksState.Folded, + state = artworksState, ) Box( - modifier = Modifier.weight(.44f), + modifier = if (artworksState == WalletArtworksState.Hidden) { + Modifier.fillMaxSize() + } else { + Modifier.weight(.44f) + }, contentAlignment = Alignment.BottomStart, ) { childContent(Modifier) @@ -50,6 +55,7 @@ private fun Preview() { TangemThemePreview { OnboardingMultiWallet( state = OnboardingMultiWalletUM(artworkUrl = null), + artworksState = WalletArtworksState.Folded, childContent = { md -> Box( modifier = md diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/WalletArtwork.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/WalletArtwork.kt index fa5c1643a7..2c1b7f784c 100644 --- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/WalletArtwork.kt +++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/ui/WalletArtwork.kt @@ -1,9 +1,11 @@ @file:Suppress("MagicNumber", "UnnecessaryParentheses", "CyclomaticComplexMethod", "LongMethod") + package com.tangem.features.onboarding.v2.multiwallet.impl.ui import androidx.compose.animation.core.Transition import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.updateTransition +import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.* import androidx.compose.material3.Button import androidx.compose.material3.Text @@ -20,12 +22,15 @@ import androidx.compose.ui.util.fastForEach import androidx.compose.ui.zIndex import coil.compose.AsyncImage import coil.request.ImageRequest +import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.features.onboarding.v2.impl.R import kotlinx.coroutines.delay import java.util.concurrent.TimeUnit sealed class WalletArtworksState { + data object Hidden : WalletArtworksState() + data object Folded : WalletArtworksState() data object Fan : WalletArtworksState() @@ -54,6 +59,8 @@ sealed class WalletArtworksState { @Composable fun WalletArtworks(url: String?, state: WalletArtworksState, modifier: Modifier = Modifier) { + if (state is WalletArtworksState.Hidden) return + BoxWithConstraints( modifier .heightIn(min = 180.dp) @@ -93,6 +100,21 @@ fun WalletArtworks(url: String?, state: WalletArtworksState, modifier: Modifier } } + val circleColor = TangemTheme.colors.background.secondary + + Canvas( + modifier = Modifier + .align(Alignment.Center) + .size(254.dp) + .fillMaxSize(), + ) { + drawCircle( + color = circleColor, + radius = size.width / 2, + center = center, + ) + } + AnimatedWalletCards( url = url, modifier = Modifier @@ -225,6 +247,7 @@ private fun WalletCard(url: String?, modifier: Modifier = Modifier) { private fun WalletArtworksState.toTransitionSetState(maxWidthDp: Float, maxHeightDp: Float, density: Float) = when (this) { + WalletArtworksState.Hidden -> listOf() is WalletArtworksState.Folded -> listOf( CardsTransitionState( WalletCardTransitionState(),