Updated on 2026-08-14

This commit is contained in:
Tangem 2025-01-27 12:22:44 +03:00
parent 04b7287332
commit 9d49f37de6
11 changed files with 90 additions and 38 deletions

View file

@ -9,6 +9,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.decompose.value.observe
import com.arkivanov.essenty.instancekeeper.getOrCreateSimple
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.context.childByContext
@ -25,13 +26,14 @@ import com.tangem.features.onboarding.v2.visa.impl.child.otherwallet.OnboardingV
import com.tangem.features.onboarding.v2.visa.impl.child.pincode.OnboardingVisaPinCodeComponent
import com.tangem.features.onboarding.v2.visa.impl.child.welcome.OnboardingVisaWelcomeComponent
import com.tangem.features.onboarding.v2.visa.impl.model.OnboardingVisaModel
import com.tangem.features.onboarding.v2.visa.impl.route.ONBOARDING_VISA_STEPS_COUNT
import com.tangem.features.onboarding.v2.visa.impl.route.OnboardingVisaRoute
import com.tangem.features.onboarding.v2.visa.impl.route.screenTitle
import com.tangem.features.onboarding.v2.visa.impl.route.stepNum
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
@Suppress("UnusedPrivateMember")
@ -43,12 +45,7 @@ internal class DefaultOnboardingVisaComponent @AssistedInject constructor(
private val model: OnboardingVisaModel = getOrCreateModel(params)
private val innerNavigationState = instanceKeeper.getOrCreateSimple(key = "innerNavigationState") {
MutableStateFlow(
OnboardingVisaInnerNavigationState(
stackSize = 1,
stackMaxSize = 7,
),
)
MutableStateFlow(OnboardingVisaInnerNavigationState(stackSize = model.initialStepNum))
}
private val currentChildBackEventHandle = instanceKeeper.getOrCreateSimple(key = "currentChildBackEventHandle") {
@ -84,6 +81,20 @@ internal class DefaultOnboardingVisaComponent @AssistedInject constructor(
}
}
init {
// sets title and stepper value
childStack.observe(lifecycle) { stack ->
val currentRoute = stack.active.configuration
params.titleProvider.changeTitle(currentRoute.screenTitle())
innerNavigationState.update { it.copy(stackSize = currentRoute.stepNum()) }
}
}
private val childParams = ChildParams(
onBack = ::onChildBack,
parentBackEvent = currentChildBackEventHandle,
)
private fun createChild(
route: OnboardingVisaRoute,
factoryContext: AppComponentContext,
@ -93,22 +104,21 @@ internal class DefaultOnboardingVisaComponent @AssistedInject constructor(
appComponentContext = factoryContext,
params = OnboardingVisaWelcomeComponent.Params(
isWelcomeBack = route.isWelcomeBack,
onBack = ::onChildBack,
childParams = childParams,
onDone = { stackNavigation.push(OnboardingVisaRoute.AccessCode) },
),
)
OnboardingVisaRoute.AccessCode -> OnboardingVisaAccessCodeComponent(
appComponentContext = factoryContext,
params = OnboardingVisaAccessCodeComponent.Params(
onBack = ::onChildBack,
parentBackEvent = currentChildBackEventHandle,
childParams = childParams,
onDone = { stackNavigation.push(OnboardingVisaRoute.ChooseWallet) },
),
)
OnboardingVisaRoute.ChooseWallet -> OnboardingVisaChooseWalletComponent(
appComponentContext = factoryContext,
params = OnboardingVisaChooseWalletComponent.Params(
onBack = ::onChildBack,
childParams = childParams,
onEvent = { event ->
stackNavigation.push(
when (event) {
@ -124,28 +134,28 @@ internal class DefaultOnboardingVisaComponent @AssistedInject constructor(
OnboardingVisaRoute.InProgress -> OnboardingVisaInProgressComponent(
appComponentContext = factoryContext,
params = OnboardingVisaInProgressComponent.Params(
onBack = ::onChildBack,
childParams = childParams,
onDone = { stackNavigation.push(OnboardingVisaRoute.PinCode) },
),
)
OnboardingVisaRoute.OtherWalletApproveOption -> OnboardingVisaOtherWalletComponent(
appComponentContext = factoryContext,
params = OnboardingVisaOtherWalletComponent.Params(
onBack = ::onChildBack,
childParams = childParams,
onDone = { stackNavigation.push(OnboardingVisaRoute.InProgress) },
),
)
OnboardingVisaRoute.PinCode -> OnboardingVisaPinCodeComponent(
appComponentContext = factoryContext,
params = OnboardingVisaPinCodeComponent.Params(
onBack = ::onChildBack,
childParams = childParams,
onDone = { params.onDone() },
),
)
OnboardingVisaRoute.TangemWalletApproveOption -> OnboardingVisaApproveComponent(
appComponentContext = factoryContext,
params = OnboardingVisaApproveComponent.Params(
onBack = ::onChildBack,
childParams = childParams,
onDone = { stackNavigation.push(OnboardingVisaRoute.InProgress) },
),
)
@ -180,6 +190,11 @@ internal class DefaultOnboardingVisaComponent @AssistedInject constructor(
}
}
data class ChildParams(
val onBack: () -> Unit,
val parentBackEvent: SharedFlow<Unit>,
)
@AssistedFactory
interface Factory : OnboardingVisaComponent.Factory {
override fun create(
@ -189,7 +204,8 @@ internal class DefaultOnboardingVisaComponent @AssistedInject constructor(
}
}
data class OnboardingVisaInnerNavigationState(
internal data class OnboardingVisaInnerNavigationState(
override val stackSize: Int,
override val stackMaxSize: Int?,
) : InnerNavigationState
) : InnerNavigationState {
override val stackMaxSize: Int = ONBOARDING_VISA_STEPS_COUNT
}

View file

@ -9,9 +9,9 @@ import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.security.DisableScreenshotsDisposableEffect
import com.tangem.features.onboarding.v2.visa.impl.DefaultOnboardingVisaComponent
import com.tangem.features.onboarding.v2.visa.impl.child.accesscode.model.OnboardingVisaAccessCodeModel
import com.tangem.features.onboarding.v2.visa.impl.child.accesscode.ui.OnboardingVisaAccessCode
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.launch
internal class OnboardingVisaAccessCodeComponent(
@ -23,10 +23,10 @@ internal class OnboardingVisaAccessCodeComponent(
init {
componentScope.launch {
model.onBack.collect { params.onBack() }
model.onBack.collect { params.childParams.onBack() }
}
componentScope.launch {
params.parentBackEvent.collect {
params.childParams.parentBackEvent.collect {
model.onBack()
}
}
@ -47,8 +47,7 @@ internal class OnboardingVisaAccessCodeComponent(
}
data class Params(
val parentBackEvent: SharedFlow<Unit>,
val onBack: () -> Unit,
val childParams: DefaultOnboardingVisaComponent.ChildParams,
val onDone: () -> Unit,
)
}

View file

@ -9,6 +9,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.features.onboarding.v2.visa.impl.DefaultOnboardingVisaComponent
import com.tangem.features.onboarding.v2.visa.impl.child.approve.model.OnboardingVisaApproveModel
import com.tangem.features.onboarding.v2.visa.impl.child.approve.ui.OnboardingVisaApprove
import kotlinx.coroutines.launch
@ -30,7 +31,7 @@ internal class OnboardingVisaApproveComponent(
override fun Content(modifier: Modifier) {
val state by model.uiState.collectAsStateWithLifecycle()
BackHandler(onBack = remember(this) { { params.onBack() } })
BackHandler(onBack = remember(this) { { params.childParams.onBack() } })
OnboardingVisaApprove(
state = state,
@ -39,7 +40,7 @@ internal class OnboardingVisaApproveComponent(
}
data class Params(
val onBack: () -> Unit,
val childParams: DefaultOnboardingVisaComponent.ChildParams,
val onDone: () -> Unit,
)
}

View file

@ -9,6 +9,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.features.onboarding.v2.visa.impl.DefaultOnboardingVisaComponent
import com.tangem.features.onboarding.v2.visa.impl.child.choosewallet.model.OnboardingVisaChooseWalletModel
import com.tangem.features.onboarding.v2.visa.impl.child.choosewallet.ui.OnboardingVisaChooseWallet
import kotlinx.coroutines.flow.launchIn
@ -31,7 +32,7 @@ internal class OnboardingVisaChooseWalletComponent(
override fun Content(modifier: Modifier) {
val state by model.uiState.collectAsStateWithLifecycle()
BackHandler(onBack = remember(this) { { params.onBack() } })
BackHandler(onBack = remember(this) { { params.childParams.onBack() } })
OnboardingVisaChooseWallet(
modifier = modifier,
@ -40,7 +41,7 @@ internal class OnboardingVisaChooseWalletComponent(
}
data class Params(
val onBack: () -> Unit,
val childParams: DefaultOnboardingVisaComponent.ChildParams,
val onEvent: (Event) -> Unit,
) {
enum class Event {

View file

@ -7,12 +7,13 @@ import androidx.compose.ui.Modifier
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.features.onboarding.v2.visa.impl.DefaultOnboardingVisaComponent
import com.tangem.features.onboarding.v2.visa.impl.child.inprogress.model.OnboardingVisaInProgressModel
import com.tangem.features.onboarding.v2.visa.impl.child.inprogress.ui.OnboardingVisaInProgress
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
class OnboardingVisaInProgressComponent(
internal class OnboardingVisaInProgressComponent(
appComponentContext: AppComponentContext,
private val params: Params,
) : ComposableContentComponent, AppComponentContext by appComponentContext {
@ -27,7 +28,7 @@ class OnboardingVisaInProgressComponent(
@Composable
override fun Content(modifier: Modifier) {
BackHandler(onBack = remember(this) { { params.onBack() } })
BackHandler(onBack = remember(this) { { params.childParams.onBack() } })
OnboardingVisaInProgress(
modifier = modifier,
@ -35,7 +36,7 @@ class OnboardingVisaInProgressComponent(
}
data class Params(
val onBack: () -> Unit,
val childParams: DefaultOnboardingVisaComponent.ChildParams,
val onDone: () -> Unit,
)
}

View file

@ -9,6 +9,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.features.onboarding.v2.visa.impl.DefaultOnboardingVisaComponent
import com.tangem.features.onboarding.v2.visa.impl.child.otherwallet.model.OnboardingVisaOtherWalletModel
import com.tangem.features.onboarding.v2.visa.impl.child.otherwallet.ui.OnboardingVisaOtherWallet
import kotlinx.coroutines.flow.launchIn
@ -31,7 +32,7 @@ internal class OnboardingVisaOtherWalletComponent(
override fun Content(modifier: Modifier) {
val state by model.uiState.collectAsStateWithLifecycle()
BackHandler(onBack = remember(this) { { params.onBack() } })
BackHandler(onBack = remember(this) { { params.childParams.onBack() } })
OnboardingVisaOtherWallet(
modifier = modifier,
@ -40,7 +41,7 @@ internal class OnboardingVisaOtherWalletComponent(
}
data class Params(
val onBack: () -> Unit,
val childParams: DefaultOnboardingVisaComponent.ChildParams,
val onDone: () -> Unit,
)
}

View file

@ -10,6 +10,7 @@ import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.core.ui.security.DisableScreenshotsDisposableEffect
import com.tangem.features.onboarding.v2.visa.impl.DefaultOnboardingVisaComponent
import com.tangem.features.onboarding.v2.visa.impl.child.pincode.model.OnboardingVisaPinCodeModel
import com.tangem.features.onboarding.v2.visa.impl.child.pincode.ui.OnboardingVisaPinCode
import kotlinx.coroutines.launch
@ -31,7 +32,7 @@ internal class OnboardingVisaPinCodeComponent(
override fun Content(modifier: Modifier) {
val state by model.uiState.collectAsStateWithLifecycle()
BackHandler(onBack = remember(this) { { params.onBack() } })
BackHandler(onBack = remember(this) { { params.childParams.onBack() } })
DisableScreenshotsDisposableEffect()
@ -42,7 +43,7 @@ internal class OnboardingVisaPinCodeComponent(
}
data class Params(
val onBack: () -> Unit,
val childParams: DefaultOnboardingVisaComponent.ChildParams,
val onDone: () -> Unit,
)
}

View file

@ -6,6 +6,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.features.onboarding.v2.visa.impl.DefaultOnboardingVisaComponent
import com.tangem.features.onboarding.v2.visa.impl.child.welcome.ui.OnboardingVisaWelcome
import com.tangem.features.onboarding.v2.visa.impl.child.welcome.ui.state.OnboardingVisaWelcomeUM
@ -28,7 +29,7 @@ internal class OnboardingVisaWelcomeComponent(
)
}
BackHandler(onBack = remember(this) { { params.onBack() } })
BackHandler(onBack = remember(this) { { params.childParams.onBack() } })
OnboardingVisaWelcome(
modifier = modifier,
@ -37,8 +38,8 @@ internal class OnboardingVisaWelcomeComponent(
}
data class Params(
val childParams: DefaultOnboardingVisaComponent.ChildParams,
val isWelcomeBack: Boolean,
val onBack: () -> Unit,
val onDone: () -> Unit,
)
}

View file

@ -6,6 +6,7 @@ import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.features.onboarding.v2.visa.api.OnboardingVisaComponent
import com.tangem.features.onboarding.v2.visa.impl.route.OnboardingVisaRoute
import com.tangem.features.onboarding.v2.visa.impl.route.stepNum
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import javax.inject.Inject
@ -20,4 +21,6 @@ internal class OnboardingVisaModel @Inject constructor(
private val params = paramsContainer.require<OnboardingVisaComponent.Params>()
val initialRoute = OnboardingVisaRoute.Welcome(isWelcomeBack = false)
val initialStepNum = initialRoute.stepNum()
}

View file

@ -0,0 +1,14 @@
package com.tangem.features.onboarding.v2.visa.impl.route
@Suppress("MagicNumber")
internal fun OnboardingVisaRoute.stepNum() = when (this) {
is OnboardingVisaRoute.Welcome -> 1
OnboardingVisaRoute.AccessCode -> 2
OnboardingVisaRoute.ChooseWallet -> 3
OnboardingVisaRoute.OtherWalletApproveOption -> 4
OnboardingVisaRoute.TangemWalletApproveOption -> 4
OnboardingVisaRoute.InProgress -> 5
OnboardingVisaRoute.PinCode -> 6
}
internal const val ONBOARDING_VISA_STEPS_COUNT = 7

View file

@ -0,0 +1,14 @@
package com.tangem.features.onboarding.v2.visa.impl.route
import com.tangem.core.ui.extensions.TextReference
// TODO add translations [REDACTED_TASK_KEY]
internal fun OnboardingVisaRoute.screenTitle(): TextReference = when (this) {
OnboardingVisaRoute.AccessCode -> TextReference.Str("Access code")
OnboardingVisaRoute.ChooseWallet -> TextReference.Str("Account activation")
OnboardingVisaRoute.InProgress -> TextReference.Str("In progress")
OnboardingVisaRoute.OtherWalletApproveOption -> TextReference.Str("Wallet connection")
OnboardingVisaRoute.PinCode -> TextReference.Str("PIN code")
OnboardingVisaRoute.TangemWalletApproveOption -> TextReference.Str("Wallet connection")
is OnboardingVisaRoute.Welcome -> TextReference.Str("Getting started")
}