From 9e108e45d128987eda815e422984441b6ef86871 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 26 Mar 2025 20:10:59 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../features/welcome/model/WelcomeModel.kt | 3 +- .../features/welcome/ui/WelcomeFragment.kt | 85 ----------- .../features/welcome/ui/WelcomeViewModel.kt | 134 ------------------ .../tangem/tap/routing/utils/ChildFactory.kt | 9 +- 4 files changed, 9 insertions(+), 222 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt delete mode 100644 app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt diff --git a/app/src/main/java/com/tangem/tap/features/welcome/model/WelcomeModel.kt b/app/src/main/java/com/tangem/tap/features/welcome/model/WelcomeModel.kt index 143654b18d..fd312671d9 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/model/WelcomeModel.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/model/WelcomeModel.kt @@ -14,6 +14,7 @@ import com.tangem.tap.features.welcome.redux.WelcomeAction import com.tangem.tap.features.welcome.redux.WelcomeState import com.tangem.tap.features.welcome.ui.WelcomeScreenState import com.tangem.tap.features.welcome.ui.model.WarningModel +import com.tangem.tap.mainScope import com.tangem.tap.store import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow @@ -39,7 +40,7 @@ internal class WelcomeModel @Inject constructor( val state: MutableStateFlow = MutableStateFlow(initialState) init { - store.dispatch(WelcomeAction.SetCoroutineScope(modelScope)) + store.dispatch(WelcomeAction.SetCoroutineScope(mainScope)) subscribeToStoreChanges() initGlobalState() diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt deleted file mode 100644 index 968b3776fa..0000000000 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.tangem.tap.features.welcome.ui - -import androidx.activity.compose.BackHandler -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.systemBarsPadding -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalLifecycleOwner -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.tangem.core.analytics.Analytics -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.res.TangemTheme -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.tap.common.analytics.events.SignIn -import com.tangem.tap.common.extensions.eraseContext -import com.tangem.tap.features.details.ui.cardsettings.resolveReference -import com.tangem.tap.features.welcome.ui.components.WarningDialog -import com.tangem.tap.features.welcome.ui.components.WelcomeScreenContent -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -internal class WelcomeFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - override fun onStart() { - super.onStart() - Analytics.eraseContext() - Analytics.send(SignIn.ScreenOpened()) - } - - @Composable - override fun ScreenContent(modifier: Modifier) { - val viewModel = hiltViewModel() - LocalLifecycleOwner.current.lifecycle.addObserver(viewModel) - - val state by viewModel.state.collectAsStateWithLifecycle() - val snackbarHostState = remember { SnackbarHostState() } - val errorMessage by rememberUpdatedState(newValue = state.error?.resolveReference()) - val warning by rememberUpdatedState(newValue = state.warning) - - BackHandler { - requireActivity().finish() - } - - Box( - modifier = modifier - .background(TangemTheme.colors.background.primary) - .systemBarsPadding(), - ) { - WelcomeScreenContent( - showUnlockProgress = state.showUnlockWithBiometricsProgress, - showScanCardProgress = state.showUnlockWithCardProgress, - onUnlockClick = viewModel::unlockWallets, - onScanCardClick = viewModel::scanCard, - ) - - SnackbarHost( - modifier = Modifier - .align(Alignment.BottomCenter) - .padding(vertical = TangemTheme.dimens.spacing16) - .fillMaxWidth(), - hostState = snackbarHostState, - ) - } - - WarningDialog(warning) - - LaunchedEffect(key1 = errorMessage) { - errorMessage?.let { - snackbarHostState.showSnackbar(it) - viewModel.closeError() - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt deleted file mode 100644 index 592678f735..0000000000 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt +++ /dev/null @@ -1,134 +0,0 @@ -package com.tangem.tap.features.welcome.ui - -import android.os.Bundle -import androidx.lifecycle.* -import com.tangem.common.core.TangemError -import com.tangem.common.routing.AppRoute -import com.tangem.common.routing.bundle.unbundle -import com.tangem.common.routing.entity.SerializableIntent -import com.tangem.core.analytics.Analytics -import com.tangem.domain.wallets.legacy.UserWalletsListError -import com.tangem.tap.common.analytics.events.SignIn -import com.tangem.tap.common.redux.global.GlobalAction -import com.tangem.tap.features.details.ui.cardsettings.TextReference -import com.tangem.tap.features.welcome.redux.WelcomeAction -import com.tangem.tap.features.welcome.redux.WelcomeState -import com.tangem.tap.features.welcome.ui.model.WarningModel -import com.tangem.tap.store -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.update -import org.rekotlin.StoreSubscriber -import javax.inject.Inject - -@HiltViewModel -internal class WelcomeViewModel @Inject constructor( - savedStateHandle: SavedStateHandle, -) : ViewModel(), - StoreSubscriber, - DefaultLifecycleObserver { - - private val initialIntent: SerializableIntent? = savedStateHandle.get(AppRoute.Welcome.INITIAL_INTENT_KEY) - ?.unbundle(SerializableIntent.serializer()) - - private val stateInternal = MutableStateFlow(WelcomeScreenState()) - val state: StateFlow = stateInternal - - override fun onCreate(owner: LifecycleOwner) { - store.dispatch(WelcomeAction.SetCoroutineScope(viewModelScope)) - - subscribeToStoreChanges() - initGlobalState() - - val welcomeAction = if (initialIntent != null) { - WelcomeAction.ProceedWithIntent(initialIntent.toIntent()) - } else { - WelcomeAction.ProceedWithBiometrics() - } - - store.dispatch(welcomeAction) - } - - fun unlockWallets() { - Analytics.send(SignIn.ButtonBiometricSignIn()) - store.dispatch(WelcomeAction.ProceedWithBiometrics()) - } - - fun scanCard() { - Analytics.send(SignIn.ButtonCardSignIn()) - store.dispatch(WelcomeAction.ProceedWithCard) - } - - fun closeError() { - store.dispatch(WelcomeAction.CloseError) - } - - // TODO: Refactor errors handling - override fun newState(state: WelcomeState) { - val warning = createWarningIfNeeded(state.error) - - stateInternal.update { prevState -> - prevState.copy( - showUnlockWithBiometricsProgress = state.isUnlockWithBiometricsInProgress, - showUnlockWithCardProgress = state.isUnlockWithCardInProgress, - warning = warning, - error = state.error - ?.takeIf { !it.silent && warning == null } - ?.let { e -> - e.messageResId?.let { TextReference.Res(it) } - ?: TextReference.Str(e.customMessage) - }, - ) - } - } - - override fun onDestroy(owner: LifecycleOwner) { - store.dispatch(WelcomeAction.ClearCoroutineScope) - store.unsubscribe(this) - super.onDestroy(owner) - } - - private fun createWarningIfNeeded(error: TangemError?): WarningModel? { - return when (error) { - is UserWalletsListError.BiometricsAuthenticationLockout -> WarningModel.BiometricsLockoutWarning( - isPermanent = error.isPermanent, - onDismiss = this::dismissWarning, - ) - is UserWalletsListError.AllKeysInvalidated, - is UserWalletsListError.NoUserWalletSelected, - -> WarningModel.KeyInvalidatedWarning( - onDismiss = this::dismissWarning, - ) - is UserWalletsListError.BiometricsAuthenticationDisabled -> WarningModel.BiometricsDisabledWarning( - onDismiss = this::clearUserWallets, - ) - else -> null - } - } - - private fun dismissWarning() { - stateInternal.update { prevState -> - prevState.copy( - warning = null, - ) - } - closeError() - } - - private fun clearUserWallets() { - store.dispatch(WelcomeAction.ClearUserWallets) - } - - private fun subscribeToStoreChanges() { - store.subscribe(this) { appState -> - appState.skip { old, new -> old.welcomeState == new.welcomeState } - .select { it.welcomeState } - } - } - - private fun initGlobalState() { - store.dispatch(GlobalAction.RestoreAppCurrency) - store.dispatch(GlobalAction.ExchangeManager.Init) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index 0ff58d9f5f..f437e1e6e9 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -34,7 +34,6 @@ import com.tangem.tap.features.onboarding.products.twins.ui.OnboardingTwinsFragm import com.tangem.tap.features.onboarding.products.wallet.ui.OnboardingWalletFragment import com.tangem.tap.features.saveWallet.ui.SaveWalletBottomSheetFragment import com.tangem.tap.features.welcome.component.WelcomeComponent -import com.tangem.tap.features.welcome.ui.WelcomeFragment import com.tangem.tap.routing.component.RoutingComponent.Child import com.tangem.tap.routing.toggle.RoutingFeatureToggles import com.tangem.utils.Provider @@ -549,7 +548,13 @@ internal class ChildFactory @Inject constructor( ) } is AppRoute.Welcome -> { - route.asFragmentChild(Provider { WelcomeFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = WelcomeComponent.Params( + intent = route.intent, + ), + componentFactory = welcomeComponentFactory, + ) } is AppRoute.TesterMenu -> { Child.LegacyIntent(testerRouter.getEntryIntent())