From 5899f9ea8d6118246d6058582a9444152df86fe0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 19 Feb 2025 12:25:53 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 4 - .../tangem/tap/routing/utils/ChildFactory.kt | 25 ++- core/deep-links/build.gradle.kts | 2 + .../tangem/core/deeplink/DeepLinksRegistry.kt | 19 --- .../deeplink/impl/DefaultDeepLinksRegistry.kt | 16 -- .../utils/AppComponentContextExtensions.kt | 21 +++ .../utils/DeepLinksLifecycleObserver.kt | 20 --- features/tokendetails/api/build.gradle.kts | 9 +- .../tokendetails/TokenDetailsComponent.kt | 16 ++ .../navigation/TokenDetailsRouter.kt | 8 - .../DefaultTokenDetailsComponent.kt | 78 +++++++++ .../tokendetails/di/TokenDetailsModule.kt | 38 +++++ .../di/TokenDetailsRouterModule.kt | 27 ---- .../presentation/TokenDetailsFragment.kt | 105 ------------ .../router/DefaultTokenDetailsRouter.kt | 9 +- .../router/InnerTokenDetailsRouter.kt | 3 +- .../TokenDetailsClickIntents.kt | 2 +- .../TokenDetailsModel.kt} | 150 ++++++++---------- .../TokenDetailsActionButtonsConverter.kt | 2 +- .../TokenDetailsLoadedBalanceConverter.kt | 2 +- .../TokenDetailsNotificationConverter.kt | 2 +- ...nDetailsOnrampTransactionStateConverter.kt | 2 +- .../TokenDetailsSkeletonStateConverter.kt | 2 +- .../state/factory/TokenDetailsStateFactory.kt | 2 +- ...enDetailsSwapTransactionsStateConverter.kt | 2 +- .../factory/express/ExchangeStatusFactory.kt | 2 +- .../factory/express/ExpressStatusFactory.kt | 2 +- .../factory/express/OnrampStatusFactory.kt | 2 +- .../TokenDetailsLoadedTxHistoryConverter.kt | 2 +- .../TokenDetailsLoadingTxHistoryConverter.kt | 2 +- .../TokenDetailsTxHistoryItemFlowConverter.kt | 2 +- ...tailsTxHistoryTransactionStateConverter.kt | 2 +- 32 files changed, 265 insertions(+), 315 deletions(-) create mode 100644 core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/AppComponentContextExtensions.kt delete mode 100644 core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/DeepLinksLifecycleObserver.kt create mode 100644 features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt delete mode 100644 features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/navigation/TokenDetailsRouter.kt create mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt create mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsRouterModule.kt delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt rename features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/{viewmodels => model}/TokenDetailsClickIntents.kt (99%) rename features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/{viewmodels/TokenDetailsViewModel.kt => model/TokenDetailsModel.kt} (91%) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index c96a550db8..72b9f67d82 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -64,7 +64,6 @@ import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnaly import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION -import com.tangem.features.tokendetails.navigation.TokenDetailsRouter import com.tangem.features.wallet.navigation.WalletRouter import com.tangem.google.GoogleServicesHelper import com.tangem.operations.backup.BackupService @@ -140,9 +139,6 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac @Inject lateinit var walletRouter: WalletRouter - @Inject - lateinit var tokenDetailsRouter: TokenDetailsRouter - @Inject lateinit var walletConnectInteractor: WalletConnectInteractor 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 d8483ca2db..09e825ea06 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 @@ -18,7 +18,7 @@ import com.tangem.features.send.api.SendComponent import com.tangem.features.swap.SwapComponent import com.tangem.features.staking.api.StakingComponent import com.tangem.features.tester.api.TesterRouter -import com.tangem.features.tokendetails.navigation.TokenDetailsRouter +import com.tangem.features.tokendetails.TokenDetailsComponent import com.tangem.features.wallet.navigation.WalletRouter import com.tangem.tap.features.details.ui.appcurrency.AppCurrencySelectorFragment import com.tangem.tap.features.details.ui.appsettings.AppSettingsFragment @@ -62,7 +62,7 @@ internal class ChildFactory @Inject constructor( private val stakingComponentFactory: StakingComponent.Factory, private val swapComponentFactory: SwapComponent.Factory, private val homeComponentFactory: HomeComponent.Factory, - private val tokenDetailsRouter: TokenDetailsRouter, + private val tokenDetailsComponentFactory: TokenDetailsComponent.Factory, private val walletRouter: WalletRouter, private val qrScanningRouter: QrScanningRouter, private val testerRouter: TesterRouter, @@ -213,6 +213,16 @@ internal class ChildFactory @Inject constructor( componentFactory = storiesComponentFactory, ) } + is AppRoute.CurrencyDetails -> { + createComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = TokenDetailsComponent.Params( + userWalletId = route.userWalletId, + currency = route.currency, + ), + componentFactory = tokenDetailsComponentFactory, + ) + } is AppRoute.Staking -> { createComponentChild( contextProvider = contextProvider(route, contextFactory), @@ -263,7 +273,6 @@ internal class ChildFactory @Inject constructor( is AppRoute.AppSettings, is AppRoute.CardSettings, is AppRoute.DetailsSecurity, - is AppRoute.OnboardingNote, is AppRoute.OnboardingOther, is AppRoute.OnboardingTwins, @@ -273,7 +282,6 @@ internal class ChildFactory @Inject constructor( is AppRoute.ResetToFactory, is AppRoute.Wallet, is AppRoute.WalletConnectSessions, - is AppRoute.CurrencyDetails, is AppRoute.PushNotification, -> error("Unsupported route: $route") } @@ -395,7 +403,14 @@ internal class ChildFactory @Inject constructor( route.asFragmentChild(Provider { WalletConnectFragment() }) } is AppRoute.CurrencyDetails -> { - route.asFragmentChild(Provider { tokenDetailsRouter.getEntryFragment() }) + route.asComponentChild( + contextProvider = contextProvider(route, contextFactory), + params = TokenDetailsComponent.Params( + userWalletId = route.userWalletId, + currency = route.currency, + ), + componentFactory = tokenDetailsComponentFactory, + ) } is AppRoute.Welcome -> { route.asFragmentChild(Provider { WelcomeFragment() }) diff --git a/core/deep-links/build.gradle.kts b/core/deep-links/build.gradle.kts index 9d43ab04df..c086d8f8d6 100644 --- a/core/deep-links/build.gradle.kts +++ b/core/deep-links/build.gradle.kts @@ -10,6 +10,8 @@ android { } dependencies { + /* Core */ + implementation(projects.core.decompose) /* Libs - AndroidX */ implementation(deps.lifecycle.runtime.ktx) diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt index 105ddbc940..fc56ae10a0 100644 --- a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt +++ b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/DeepLinksRegistry.kt @@ -1,8 +1,6 @@ package com.tangem.core.deeplink import android.content.Intent -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.ViewModel // TODO: Add tests /** @@ -21,17 +19,11 @@ interface DeepLinksRegistry { /** * Registers the given [deepLink]. - * - * @see registerWithLifecycle - * @see registerWithViewModel */ fun register(deepLink: DeepLink) /** * Registers the given [deepLinks]. - * - * @see registerWithLifecycle - * @see registerWithViewModel */ fun register(deepLinks: Collection) @@ -50,17 +42,6 @@ interface DeepLinksRegistry { * */ fun unregisterByIds(ids: Collection) - /** - * Registers the [deepLinks] when the [owner] is resumed and ensures that they are unregistered when the [owner] is - * stopped. - */ - fun registerWithLifecycle(owner: LifecycleOwner, deepLinks: Collection) - - /** - * Registers the [deepLinks] and ensures that they are unregistered when the [ViewModel] is closed. - */ - fun registerWithViewModel(viewModel: ViewModel, deepLinks: Collection) - /** * Triggers run last launched [Intent] with deeplink handlers that can handle delayed deeplink * after handle [Intent] clear that and second time no intent will be handled diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt index e51f6b8b37..63f6f60d78 100644 --- a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt +++ b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/impl/DefaultDeepLinksRegistry.kt @@ -3,11 +3,8 @@ package com.tangem.core.deeplink.impl import android.content.Intent import android.net.Uri import androidx.core.net.toUri -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.ViewModel import com.tangem.core.deeplink.DeepLink import com.tangem.core.deeplink.DeepLinksRegistry -import com.tangem.core.deeplink.utils.DeepLinksLifecycleObserver import timber.log.Timber internal class DefaultDeepLinksRegistry : DeepLinksRegistry { @@ -103,19 +100,6 @@ internal class DefaultDeepLinksRegistry : DeepLinksRegistry { ) } - override fun registerWithLifecycle(owner: LifecycleOwner, deepLinks: Collection) { - val observer = DeepLinksLifecycleObserver(deepLinksRegistry = this, deepLinks) - owner.lifecycle.addObserver(observer) - } - - override fun registerWithViewModel(viewModel: ViewModel, deepLinks: Collection) { - viewModel.addCloseable { - unregister(deepLinks) - } - - register(deepLinks) - } - override fun triggerDelayedDeeplink() { if (lastIntent != null) { val intent = lastIntent diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/AppComponentContextExtensions.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/AppComponentContextExtensions.kt new file mode 100644 index 0000000000..594b8305ca --- /dev/null +++ b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/AppComponentContextExtensions.kt @@ -0,0 +1,21 @@ +package com.tangem.core.deeplink.utils + +import com.arkivanov.essenty.lifecycle.subscribe +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.deeplink.DeepLink +import com.tangem.core.deeplink.DeepLinksRegistry + +fun AppComponentContext.registerDeepLinks(registry: DeepLinksRegistry, vararg deepLinks: DeepLink) { + registerDeepLinks(registry, deepLinks.toList()) +} + +fun AppComponentContext.registerDeepLinks(registry: DeepLinksRegistry, deepLinks: Collection) { + lifecycle.subscribe( + onCreate = { + registry.register(deepLinks) + }, + onDestroy = { + registry.unregister(deepLinks) + }, + ) +} \ No newline at end of file diff --git a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/DeepLinksLifecycleObserver.kt b/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/DeepLinksLifecycleObserver.kt deleted file mode 100644 index ae1580e17e..0000000000 --- a/core/deep-links/src/main/kotlin/com/tangem/core/deeplink/utils/DeepLinksLifecycleObserver.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.tangem.core.deeplink.utils - -import androidx.lifecycle.DefaultLifecycleObserver -import androidx.lifecycle.LifecycleOwner -import com.tangem.core.deeplink.DeepLink -import com.tangem.core.deeplink.DeepLinksRegistry - -internal class DeepLinksLifecycleObserver( - private val deepLinksRegistry: DeepLinksRegistry, - private val deepLinks: Collection, -) : DefaultLifecycleObserver { - - override fun onResume(owner: LifecycleOwner) { - deepLinksRegistry.register(deepLinks) - } - - override fun onPause(owner: LifecycleOwner) { - deepLinksRegistry.unregister(deepLinks) - } -} \ No newline at end of file diff --git a/features/tokendetails/api/build.gradle.kts b/features/tokendetails/api/build.gradle.kts index 26d2527cd2..dc22e4ffbb 100644 --- a/features/tokendetails/api/build.gradle.kts +++ b/features/tokendetails/api/build.gradle.kts @@ -10,8 +10,11 @@ android { } dependencies { - implementation(projects.domain.tokens.models) + /** Core */ + implementation(projects.core.decompose) + implementation(projects.core.ui) - /** AndroidX */ - implementation(deps.androidx.fragment.ktx) + /** Domain models */ + implementation(projects.domain.tokens.models) + implementation(projects.domain.wallets.models) } \ No newline at end of file diff --git a/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt b/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt new file mode 100644 index 0000000000..a057fcb984 --- /dev/null +++ b/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/TokenDetailsComponent.kt @@ -0,0 +1,16 @@ +package com.tangem.features.tokendetails + +import com.tangem.core.decompose.factory.ComponentFactory +import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.wallets.models.UserWalletId + +interface TokenDetailsComponent : ComposableContentComponent { + + data class Params( + val userWalletId: UserWalletId, + val currency: CryptoCurrency, + ) + + interface Factory : ComponentFactory +} \ No newline at end of file diff --git a/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/navigation/TokenDetailsRouter.kt b/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/navigation/TokenDetailsRouter.kt deleted file mode 100644 index a361d75438..0000000000 --- a/features/tokendetails/api/src/main/kotlin/com/tangem/features/tokendetails/navigation/TokenDetailsRouter.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.features.tokendetails.navigation - -import androidx.fragment.app.Fragment - -interface TokenDetailsRouter { - - fun getEntryFragment(): Fragment -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt new file mode 100644 index 0000000000..5d4274694f --- /dev/null +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/DefaultTokenDetailsComponent.kt @@ -0,0 +1,78 @@ +package com.tangem.feature.tokendetails + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.arkivanov.essenty.lifecycle.subscribe +import com.tangem.core.decompose.context.AppComponentContext +import com.tangem.core.decompose.context.child +import com.tangem.core.decompose.model.getOrCreateModel +import com.tangem.core.deeplink.DeepLinksRegistry +import com.tangem.core.deeplink.global.BuyCurrencyDeepLink +import com.tangem.core.deeplink.utils.registerDeepLinks +import com.tangem.core.ui.components.NavigationBar3ButtonsScrim +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsModel +import com.tangem.feature.tokendetails.presentation.tokendetails.ui.TokenDetailsScreen +import com.tangem.features.markets.token.block.TokenMarketBlockComponent +import com.tangem.features.tokendetails.TokenDetailsComponent +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +internal class DefaultTokenDetailsComponent @AssistedInject constructor( + @Assisted appComponentContext: AppComponentContext, + @Assisted params: TokenDetailsComponent.Params, + tokenMarketBlockComponentFactory: TokenMarketBlockComponent.Factory, + deepLinksRegistry: DeepLinksRegistry, +) : TokenDetailsComponent, AppComponentContext by appComponentContext { + + private val model: TokenDetailsModel = getOrCreateModel(params) + + init { + lifecycle.subscribe( + onPause = model::onPause, + onResume = model::onResume, + ) + + registerDeepLinks( + registry = deepLinksRegistry, + BuyCurrencyDeepLink( + onReceive = model::onBuyCurrencyDeepLink, + ), + ) + } + + private val tokenMarketBlockComponent = params.currency.toTokenMarketParam()?.let { tokenMarketParams -> + tokenMarketBlockComponentFactory.create( + appComponentContext = child("tokenMarketBlockComponent"), + params = tokenMarketParams, + ) + } + + @Composable + override fun Content(modifier: Modifier) { + val state by model.uiState.collectAsStateWithLifecycle() + + NavigationBar3ButtonsScrim() + TokenDetailsScreen( + state = state, + tokenMarketBlockComponent = tokenMarketBlockComponent, + ) + } + + private fun CryptoCurrency.toTokenMarketParam(): TokenMarketBlockComponent.Params? { + id.rawCurrencyId ?: return null // token price is not available + + return TokenMarketBlockComponent.Params(cryptoCurrency = this) + } + + @AssistedFactory + interface Factory : TokenDetailsComponent.Factory { + override fun create( + context: AppComponentContext, + params: TokenDetailsComponent.Params, + ): DefaultTokenDetailsComponent + } +} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt new file mode 100644 index 0000000000..a7ad3dd026 --- /dev/null +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsModule.kt @@ -0,0 +1,38 @@ +package com.tangem.feature.tokendetails.di + +import com.tangem.core.decompose.di.ComponentScoped +import com.tangem.core.decompose.di.DecomposeComponent +import com.tangem.core.decompose.model.Model +import com.tangem.feature.tokendetails.DefaultTokenDetailsComponent +import com.tangem.feature.tokendetails.presentation.router.DefaultTokenDetailsRouter +import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsModel +import com.tangem.features.tokendetails.TokenDetailsComponent +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@InstallIn(SingletonComponent::class) +internal interface TokenDetailsModule { + + @Binds + fun bindComponentFactory(factory: DefaultTokenDetailsComponent.Factory): TokenDetailsComponent.Factory + + @Binds + @IntoMap + @ClassKey(TokenDetailsModel::class) + fun bindModel(model: TokenDetailsModel): Model +} + +@Module +@InstallIn(DecomposeComponent::class) +internal interface StakingComponentModule { + + @Binds + @ComponentScoped + fun bindRouter(impl: DefaultTokenDetailsRouter): InnerTokenDetailsRouter +} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsRouterModule.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsRouterModule.kt deleted file mode 100644 index 94147e5592..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/di/TokenDetailsRouterModule.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.tangem.feature.tokendetails.di - -import com.tangem.common.routing.AppRouter -import com.tangem.core.navigation.share.ShareManager -import com.tangem.core.navigation.url.UrlOpener -import com.tangem.feature.tokendetails.presentation.router.DefaultTokenDetailsRouter -import com.tangem.features.tokendetails.navigation.TokenDetailsRouter -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.components.ActivityComponent -import dagger.hilt.android.scopes.ActivityScoped - -@Module -@InstallIn(ActivityComponent::class) -internal object TokenDetailsRouterModule { - - @Provides - @ActivityScoped - fun provideTokenDetailsRouter( - appRouter: AppRouter, - urlOpener: UrlOpener, - shareManager: ShareManager, - ): TokenDetailsRouter { - return DefaultTokenDetailsRouter(appRouter, urlOpener, shareManager) - } -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt deleted file mode 100644 index 2c787270d1..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/TokenDetailsFragment.kt +++ /dev/null @@ -1,105 +0,0 @@ -package com.tangem.feature.tokendetails.presentation - -import android.os.Bundle -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.fragment.app.viewModels -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.arkivanov.decompose.defaultComponentContext -import com.tangem.common.routing.AppRoute -import com.tangem.common.routing.AppRouter -import com.tangem.common.routing.bundle.unbundle -import com.tangem.common.routing.utils.asRouter -import com.tangem.core.decompose.context.DefaultAppComponentContext -import com.tangem.core.decompose.di.DecomposeComponent -import com.tangem.core.decompose.di.GlobalUiMessageSender -import com.tangem.core.decompose.ui.UiMessageSender -import com.tangem.core.ui.UiDependencies -import com.tangem.core.ui.components.NavigationBar3ButtonsScrim -import com.tangem.core.ui.screen.ComposeFragment -import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter -import com.tangem.feature.tokendetails.presentation.tokendetails.ui.TokenDetailsScreen -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsViewModel -import com.tangem.features.markets.token.block.TokenMarketBlockComponent -import com.tangem.features.tokendetails.navigation.TokenDetailsRouter -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject - -@AndroidEntryPoint -internal class TokenDetailsFragment : ComposeFragment() { - - @Inject - override lateinit var uiDependencies: UiDependencies - - @Inject - @GlobalUiMessageSender - internal lateinit var messageSender: UiMessageSender - - @Inject - internal lateinit var tokenDetailsRouter: TokenDetailsRouter - - @Inject - internal lateinit var coroutineDispatcherProvider: CoroutineDispatcherProvider - - @Inject - internal lateinit var componentBuilder: DecomposeComponent.Builder - - @Inject - internal lateinit var tokenMarketBlockComponentFactory: TokenMarketBlockComponent.Factory - - @Inject - internal lateinit var appRouter: AppRouter - - private val viewModel by viewModels() - - private var tokenMarketBlockComponent: TokenMarketBlockComponent? = null - - private val internalTokenDetailsRouter: InnerTokenDetailsRouter - get() = requireNotNull(tokenDetailsRouter as? InnerTokenDetailsRouter) { - "internalTokenDetailsRouter should be instance of InnerTokenDetailsRouter" - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - viewModel.router = internalTokenDetailsRouter - lifecycle.addObserver(viewModel) - - val cryptoCurrency: CryptoCurrency = arguments - ?.getBundle(AppRoute.CurrencyDetails.CRYPTO_CURRENCY_KEY) - ?.unbundle(CryptoCurrency.serializer()) - ?: error("Token Details screen can't be opened without `CryptoCurrency`") - - val param = cryptoCurrency.toParam() ?: return - - val appContext = DefaultAppComponentContext( - componentContext = defaultComponentContext(requireActivity().onBackPressedDispatcher), - messageSender = messageSender, - dispatchers = coroutineDispatcherProvider, - hiltComponentBuilder = componentBuilder, - replaceRouter = appRouter.asRouter(), - ) - - tokenMarketBlockComponent = tokenMarketBlockComponentFactory.create( - appComponentContext = appContext, - params = param, - ) - } - - private fun CryptoCurrency.toParam(): TokenMarketBlockComponent.Params? { - id.rawCurrencyId ?: return null // token price is not available - - return TokenMarketBlockComponent.Params(cryptoCurrency = this) - } - - @Composable - override fun ScreenContent(modifier: Modifier) { - NavigationBar3ButtonsScrim() - TokenDetailsScreen( - state = viewModel.uiState.collectAsStateWithLifecycle().value, - tokenMarketBlockComponent = tokenMarketBlockComponent, - ) - } -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt index d8a3eb4733..4ffdf4c587 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/DefaultTokenDetailsRouter.kt @@ -1,23 +1,22 @@ package com.tangem.feature.tokendetails.presentation.router -import androidx.fragment.app.Fragment import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter +import com.tangem.core.decompose.di.ComponentScoped import com.tangem.core.navigation.share.ShareManager import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.feature.tokendetails.presentation.TokenDetailsFragment +import javax.inject.Inject -internal class DefaultTokenDetailsRouter( +@ComponentScoped +internal class DefaultTokenDetailsRouter @Inject constructor( private val router: AppRouter, private val urlOpener: UrlOpener, private val shareManager: ShareManager, ) : InnerTokenDetailsRouter { - override fun getEntryFragment(): Fragment = TokenDetailsFragment() - override fun popBackStack() { router.pop() } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/InnerTokenDetailsRouter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/InnerTokenDetailsRouter.kt index e4a143ccd1..156a7c60c1 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/InnerTokenDetailsRouter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/router/InnerTokenDetailsRouter.kt @@ -3,9 +3,8 @@ package com.tangem.feature.tokendetails.presentation.router import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.wallets.models.UserWalletId -import com.tangem.features.tokendetails.navigation.TokenDetailsRouter -internal interface InnerTokenDetailsRouter : TokenDetailsRouter { +internal interface InnerTokenDetailsRouter { /** Pop back stack */ fun popBackStack() diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsClickIntents.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt similarity index 99% rename from features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsClickIntents.kt rename to features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt index 8806affc45..c716c21445 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsClickIntents.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt @@ -1,4 +1,4 @@ -package com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels +package com.tangem.feature.tokendetails.presentation.tokendetails.model import com.tangem.core.ui.components.bottomsheets.tokenreceive.AddressModel import com.tangem.core.ui.extensions.TextReference diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt similarity index 91% rename from features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt rename to features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index 744218305e..2f6219c24e 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -1,21 +1,20 @@ -package com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels +package com.tangem.feature.tokendetails.presentation.tokendetails.model -import android.os.Bundle -import androidx.lifecycle.* +import androidx.compose.runtime.Stable import androidx.paging.cachedIn import arrow.core.getOrElse import com.tangem.blockchain.common.address.AddressType import com.tangem.common.routing.AppRoute import com.tangem.common.routing.AppRouter -import com.tangem.common.routing.bundle.unbundle import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateUM import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.decompose.di.ComponentScoped import com.tangem.core.decompose.di.GlobalUiMessageSender +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.ui.UiMessageSender -import com.tangem.core.deeplink.DeepLinksRegistry -import com.tangem.core.deeplink.global.BuyCurrencyDeepLink import com.tangem.core.navigation.share.ShareManager import com.tangem.core.ui.clipboard.ClipboardManager import com.tangem.core.ui.components.bottomsheets.tokenreceive.AddressModel @@ -36,6 +35,7 @@ import com.tangem.domain.card.NetworkHasDerivationUseCase import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.onramp.model.OnrampSource +import com.tangem.domain.promo.ShouldShowSwapPromoTokenUseCase import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.staking.GetStakingAvailabilityUseCase import com.tangem.domain.staking.GetStakingEntryInfoUseCase @@ -73,12 +73,11 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenBala import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsStateFactory import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.express.ExpressStatusFactory -import com.tangem.domain.promo.ShouldShowSwapPromoTokenUseCase import com.tangem.features.onramp.OnrampFeatureToggles +import com.tangem.features.tokendetails.TokenDetailsComponent import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider import com.tangem.utils.coroutines.* -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.async @@ -89,9 +88,10 @@ import timber.log.Timber import javax.inject.Inject @Suppress("LongParameterList", "LargeClass", "TooManyFunctions") -@HiltViewModel -internal class TokenDetailsViewModel @Inject constructor( - private val dispatchers: CoroutineDispatcherProvider, +@Stable +@ComponentScoped +internal class TokenDetailsModel @Inject constructor( + override val dispatchers: CoroutineDispatcherProvider, private val getCurrencyStatusUpdatesUseCase: GetCurrencyStatusUpdatesUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase, @@ -122,26 +122,19 @@ internal class TokenDetailsViewModel @Inject constructor( private val onrampFeatureToggles: OnrampFeatureToggles, private val shareManager: ShareManager, @GlobalUiMessageSender private val uiMessageSender: UiMessageSender, + paramsContainer: ParamsContainer, expressStatusFactory: ExpressStatusFactory.Factory, getUserWalletUseCase: GetUserWalletUseCase, getStakingIntegrationIdUseCase: GetStakingIntegrationIdUseCase, - deepLinksRegistry: DeepLinksRegistry, - savedStateHandle: SavedStateHandle, private val appRouter: AppRouter, -) : ViewModel(), DefaultLifecycleObserver, TokenDetailsClickIntents { + private val router: InnerTokenDetailsRouter, +) : Model(), TokenDetailsClickIntents { - private val userWalletId: UserWalletId = savedStateHandle.get(AppRoute.CurrencyDetails.USER_WALLET_ID_KEY) - ?.unbundle(UserWalletId.serializer()) - ?: error("This screen can't be opened without `UserWalletId`") + private val params = paramsContainer.require() + private val userWalletId: UserWalletId = params.userWalletId + private val cryptoCurrency: CryptoCurrency = params.currency - private val cryptoCurrency: CryptoCurrency = - savedStateHandle.get(AppRoute.CurrencyDetails.CRYPTO_CURRENCY_KEY) - ?.unbundle(CryptoCurrency.serializer()) - ?: error("This screen can't be opened without `CryptoCurrency`") - - private val userWallet: UserWallet - - lateinit var router: InnerTokenDetailsRouter + private val userWallet: UserWallet = getUserWalletUseCase(userWalletId).getOrNull() ?: error("UserWallet not found") private val marketPriceJobHolder = JobHolder() private val refreshStateJobHolder = JobHolder() @@ -195,18 +188,16 @@ internal class TokenDetailsViewModel @Inject constructor( val uiState: StateFlow = internalUiState init { - deepLinksRegistry.registerWithViewModel( - viewModel = this, - deepLinks = listOf( - BuyCurrencyDeepLink( - onReceive = ::onBuyCurrencyDeepLink, - ), - ), + analyticsEventsHandler.send( + event = TokenScreenAnalyticsEvent.DetailsScreenOpened(token = cryptoCurrency.symbol), ) - userWallet = getUserWalletUseCase(userWalletId).getOrNull() ?: error("UserWallet not found") + updateTopBarMenu() + initButtons() + updateContent() + handleBalanceHiding() } - private fun onBuyCurrencyDeepLink(externalTxId: String) { + fun onBuyCurrencyDeepLink(externalTxId: String) { if (onrampFeatureToggles.isFeatureEnabled) { router.openOnrampSuccess(externalTxId) } else { @@ -215,36 +206,24 @@ internal class TokenDetailsViewModel @Inject constructor( } } - override fun onCreate(owner: LifecycleOwner) { - analyticsEventsHandler.send( - event = TokenScreenAnalyticsEvent.DetailsScreenOpened(token = cryptoCurrency.symbol), - ) - updateTopBarMenu() - initButtons() - updateContent() - handleBalanceHiding(owner) - } - - override fun onPause(owner: LifecycleOwner) { + fun onPause() { expressTxStatusTaskScheduler.cancelTask() expressTxJobHolder.cancel() - super.onPause(owner) } - override fun onResume(owner: LifecycleOwner) { + fun onResume() { subscribeOnExpressTransactionsUpdates() - super.onResume(owner) } - override fun onCleared() { + override fun onDestroy() { expressTxStatusTaskScheduler.cancelTask() expressTxJobHolder.cancel() - super.onCleared() + super.onDestroy() } private fun initButtons() { // we need also init buttons before start all loading to avoid buttons blocking - viewModelScope.launch { + modelScope.launch { val currentCryptoCurrencyStatus = getCryptoCurrencySyncUseCase.invoke( userWalletId = userWalletId, cryptoCurrencyId = cryptoCurrency.id, @@ -266,15 +245,14 @@ internal class TokenDetailsViewModel @Inject constructor( updateStakingInfo() } - private fun handleBalanceHiding(owner: LifecycleOwner) { + private fun handleBalanceHiding() { getBalanceHidingSettingsUseCase() - .flowWithLifecycle(owner.lifecycle) .onEach { internalUiState.value = stateFactory.getStateWithUpdatedHidden( isBalanceHidden = it.isBalanceHidden, ) } - .launchIn(viewModelScope) + .launchIn(modelScope) } private suspend fun updateButtons(currencyStatus: CryptoCurrencyStatus) { @@ -288,11 +266,11 @@ internal class TokenDetailsViewModel @Inject constructor( internalUiState.value = stateFactory.getManageButtonsState(actions = it.states) } .flowOn(dispatchers.main) - .launchIn(viewModelScope) + .launchIn(modelScope) } private fun updateWarnings(cryptoCurrencyStatus: CryptoCurrencyStatus) { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { getCurrencyWarningsUseCase.invoke( userWalletId = userWalletId, currencyStatus = cryptoCurrencyStatus, @@ -305,13 +283,13 @@ internal class TokenDetailsViewModel @Inject constructor( notificationsAnalyticsSender.send(internalUiState.value, updatedState.notifications) internalUiState.value = updatedState } - .launchIn(viewModelScope) + .launchIn(modelScope) .saveIn(warningsJobHolder) } } private fun subscribeOnCurrencyStatusUpdates() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { getCurrencyStatusUpdatesUseCase( userWalletId = userWalletId, currencyId = cryptoCurrency.id, @@ -328,13 +306,13 @@ internal class TokenDetailsViewModel @Inject constructor( currencyStatusAnalyticsSender.send(maybeCurrencyStatus) } .flowOn(dispatchers.main) - .launchIn(viewModelScope) + .launchIn(modelScope) .saveIn(marketPriceJobHolder) } } private fun subscribeOnExpressTransactionsUpdates() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { expressTxStatusTaskScheduler.cancelTask() expressStatusFactory .getExpressStatuses() @@ -345,7 +323,7 @@ internal class TokenDetailsViewModel @Inject constructor( ::updateNetworkToSwapBalance, ) expressTxStatusTaskScheduler.scheduleTask( - viewModelScope, + modelScope, PeriodicTask( isDelayFirst = false, delay = EXPRESS_STATUS_UPDATE_DELAY, @@ -365,13 +343,13 @@ internal class TokenDetailsViewModel @Inject constructor( ) } .flowOn(dispatchers.main) - .launchIn(viewModelScope) + .launchIn(modelScope) .saveIn(expressTxJobHolder) } } private fun updateNetworkToSwapBalance(toCryptoCurrency: CryptoCurrency) { - viewModelScope.launch { + modelScope.launch { updateDelayedCurrencyStatusUseCase( userWalletId = userWalletId, network = toCryptoCurrency.network, @@ -385,7 +363,7 @@ internal class TokenDetailsViewModel @Inject constructor( * @param showItemsLoading - show loading items placeholder. */ private fun updateTxHistory(refresh: Boolean, showItemsLoading: Boolean) { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { val txHistoryItemsCountEither = txHistoryItemsCountUseCase( userWalletId = userWalletId, currency = cryptoCurrency, @@ -404,7 +382,7 @@ internal class TokenDetailsViewModel @Inject constructor( userWalletId = userWalletId, currency = cryptoCurrency, refresh = refresh, - ).map { it.cachedIn(viewModelScope) } + ).map { it.cachedIn(modelScope) } internalUiState.value = stateFactory.getLoadedTxHistoryState(maybeTxHistory) } @@ -412,7 +390,7 @@ internal class TokenDetailsViewModel @Inject constructor( } private fun updateStakingInfo() { - viewModelScope.launch { + modelScope.launch { val availability = getStakingAvailabilityUseCase( userWalletId = userWalletId, cryptoCurrency = cryptoCurrency, @@ -432,7 +410,7 @@ internal class TokenDetailsViewModel @Inject constructor( } private fun updateTopBarMenu() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { val hasDerivations = networkHasDerivationUseCase(userWallet.scanResponse, cryptoCurrency.network).getOrElse { false } @@ -452,7 +430,7 @@ internal class TokenDetailsViewModel @Inject constructor( maybeAppCurrency.getOrElse { AppCurrency.Default } } .stateIn( - scope = viewModelScope, + scope = modelScope, started = SharingStarted.Eagerly, initialValue = AppCurrency.Default, ) @@ -476,7 +454,7 @@ internal class TokenDetailsViewModel @Inject constructor( val status = cryptoCurrencyStatus ?: return if (onrampFeatureToggles.isFeatureEnabled) { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { reduxStateHolder.dispatch( TradeCryptoAction.Buy( userWallet = userWallet, @@ -488,7 +466,7 @@ internal class TokenDetailsViewModel @Inject constructor( } } else { showErrorIfDemoModeOrElse { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { reduxStateHolder.dispatch( TradeCryptoAction.Buy( userWallet = userWallet, @@ -554,7 +532,7 @@ internal class TokenDetailsViewModel @Inject constructor( return } - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonReceive(cryptoCurrency.symbol)) analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ReceiveScreenOpened(cryptoCurrency.symbol)) @@ -587,7 +565,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onGenerateExtendedKey() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { val extendedKey = getExtendedPublicKeyForCurrencyUseCase( userWalletId, cryptoCurrency.network, @@ -655,7 +633,7 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onHideClick() { analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonRemoveToken(cryptoCurrency.symbol)) - viewModelScope.launch { + modelScope.launch { val hasLinkedTokens = removeCurrencyUseCase.hasLinkedTokens(userWalletId, cryptoCurrency) internalUiState.value = if (hasLinkedTokens) { stateFactory.getStateWithLinkedTokensDialog(cryptoCurrency) @@ -666,7 +644,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onHideConfirmed() { - viewModelScope.launch { + modelScope.launch { removeCurrencyUseCase.invoke(userWalletId, cryptoCurrency) .onLeft { Timber.e(it) } .onRight { router.popBackStack() } @@ -681,7 +659,7 @@ internal class TokenDetailsViewModel @Inject constructor( private fun openExplorer() { val currencyStatus = cryptoCurrencyStatus ?: return - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { when (val addresses = currencyStatus.value.networkAddress) { is NetworkAddress.Selectable -> { internalUiState.value = stateFactory.getStateWithChooseAddressBottomSheet(cryptoCurrency, addresses) @@ -713,7 +691,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onAddressTypeSelected(addressModel: AddressModel) { - viewModelScope.launch { + modelScope.launch { router.openUrl( url = getExploreUrlUseCase( userWalletId = userWalletId, @@ -738,7 +716,7 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onRefreshSwipe(isRefreshing: Boolean) { internalUiState.value = stateFactory.getRefreshingState() - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { listOf( async { fetchCurrencyStatusUseCase( @@ -762,7 +740,7 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onDismissBottomSheet() { when (val bsContent = internalUiState.value.bottomSheetConfig?.content) { is ExpressStatusBottomSheetConfig -> { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { expressStatusFactory.removeTransactionOnBottomSheetClosed(bsContent.value) } } @@ -792,7 +770,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onSwapPromoDismiss() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { shouldShowSwapPromoTokenUseCase.neverToShow() analyticsEventsHandler.send( TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( @@ -805,7 +783,7 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onSwapPromoClick() { - viewModelScope.launch(dispatchers.main) { + modelScope.launch(dispatchers.main) { shouldShowSwapPromoTokenUseCase.neverToShow() analyticsEventsHandler.send( TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( @@ -836,7 +814,7 @@ internal class TokenDetailsViewModel @Inject constructor( blockchain = cryptoCurrency.network.name, ), ) - viewModelScope.launch { + modelScope.launch { retryIncompleteTransactionUseCase( userWalletId = userWalletId, currency = cryptoCurrency, @@ -877,13 +855,13 @@ internal class TokenDetailsViewModel @Inject constructor( blockchain = cryptoCurrency.network.name, ), ) - viewModelScope.launch { + modelScope.launch { internalUiState.value = stateFactory.getStateWithDismissIncompleteTransactionConfirmDialog() } } override fun onConfirmDismissIncompleteTransactionClick() { - viewModelScope.launch { + modelScope.launch { dismissIncompleteTransactionUseCase( userWalletId = userWalletId, currency = cryptoCurrency, @@ -908,7 +886,7 @@ internal class TokenDetailsViewModel @Inject constructor( blockchain = cryptoCurrency.network.name, ), ) - viewModelScope.launch(dispatchers.io) { + modelScope.launch(dispatchers.io) { associateAssetUseCase( userWalletId = userWalletId, currency = cryptoCurrency, @@ -947,7 +925,7 @@ internal class TokenDetailsViewModel @Inject constructor( override fun onDisposeExpressStatus() { val bottomSheetState = internalUiState.value.bottomSheetConfig?.content if (bottomSheetState is ExpressStatusBottomSheetConfig) { - viewModelScope.launch { + modelScope.launch { expressStatusFactory.removeTransactionOnBottomSheetClosed( expressState = bottomSheetState.value, isForceDispose = true, @@ -979,7 +957,7 @@ internal class TokenDetailsViewModel @Inject constructor( } private fun openStaking() { - viewModelScope.launch { + modelScope.launch { val yield = getYieldUseCase.invoke( cryptoCurrencyId = cryptoCurrency.id, symbol = cryptoCurrency.symbol, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt index c68c1e3be2..50052f3557 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsActionButtonsConverter.kt @@ -4,7 +4,7 @@ import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason import com.tangem.domain.tokens.model.TokenActionsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter import kotlinx.collections.immutable.ImmutableList diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt index 91ac3d6a00..75bb0ebc77 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt @@ -22,7 +22,7 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.* import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsTxHistoryTransactionStateConverter import com.tangem.feature.tokendetails.presentation.tokendetails.state.utils.getBalance -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.lib.crypto.BlockchainUtils.isBSC import com.tangem.lib.crypto.BlockchainUtils.isSolana diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt index 1c0e9869ad..f8d51e82c0 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsNotificationConverter.kt @@ -13,7 +13,7 @@ import com.tangem.domain.tokens.model.warnings.KaspaWarnings import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification.* -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.converter.Converter import com.tangem.utils.extensions.removeBy diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsOnrampTransactionStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsOnrampTransactionStateConverter.kt index ec6b983685..c585e6e3cd 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsOnrampTransactionStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsOnrampTransactionStateConverter.kt @@ -26,7 +26,7 @@ import com.tangem.domain.tokens.model.analytics.TokenOnrampAnalyticsEvent import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateIconUM import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateInfoUM import com.tangem.common.ui.expressStatus.state.ExpressTransactionStateUM -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider import com.tangem.utils.converter.Converter diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt index 44798192e1..d4f23daa2d 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt @@ -16,7 +16,7 @@ import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.feature.tokendetails.presentation.tokendetails.state.* import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.lib.crypto.BlockchainUtils.isBitcoin import com.tangem.utils.converter.Converter diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt index e88c1cc061..a76e681373 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt @@ -33,7 +33,7 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.component import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadedTxHistoryConverter import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadingTxHistoryConverter import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadingTxHistoryConverter.TokenDetailsLoadingTxHistoryModel -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider import kotlinx.collections.immutable.toImmutableList diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt index e8e7415770..d13c0cab28 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSwapTransactionsStateConverter.kt @@ -27,7 +27,7 @@ import com.tangem.feature.swap.domain.models.domain.SavedSwapTransactionModel import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.ExchangeStatusNotifications import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeStatusState import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider import com.tangem.utils.converter.Converter diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt index 3bf62b35de..8596a83abd 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExchangeStatusFactory.kt @@ -18,7 +18,7 @@ import com.tangem.feature.swap.domain.models.domain.* import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsSwapTransactionsStateConverter -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import dagger.assisted.Assisted import dagger.assisted.AssistedFactory diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt index 5f1c18949f..289cfffede 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/ExpressStatusFactory.kt @@ -13,7 +13,7 @@ import com.tangem.domain.wallets.models.UserWalletId import com.tangem.feature.swap.domain.models.domain.ExchangeStatus import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.express.ExchangeUM -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.assisted.Assisted diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt index 79328454af..e25e788d52 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/express/OnrampStatusFactory.kt @@ -17,7 +17,7 @@ import com.tangem.domain.tokens.model.analytics.TokenOnrampAnalyticsEvent import com.tangem.domain.wallets.models.UserWalletId import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsOnrampTransactionStateConverter -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import dagger.assisted.Assisted import dagger.assisted.AssistedFactory diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadedTxHistoryConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadedTxHistoryConverter.kt index efcc958a22..cb5e434ccf 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadedTxHistoryConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadedTxHistoryConverter.kt @@ -6,7 +6,7 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.domain.txhistory.models.TxHistoryListError import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter import kotlinx.coroutines.flow.Flow diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadingTxHistoryConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadingTxHistoryConverter.kt index e7c0cd2e1b..479a510db6 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadingTxHistoryConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsLoadingTxHistoryConverter.kt @@ -7,7 +7,7 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.domain.txhistory.models.TxHistoryStateError import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadingTxHistoryConverter.TokenDetailsLoadingTxHistoryModel -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter import kotlinx.collections.immutable.toImmutableList diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt index 6a8bc163c7..2dc64a9aef 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt @@ -7,7 +7,7 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState.TxHistory import com.tangem.core.ui.utils.toDateFormatWithTodayYesterday import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter import kotlinx.coroutines.CoroutineScope diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt index 360126d91d..8bc7cf05cd 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt @@ -12,7 +12,7 @@ import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.utils.toTimeFormat import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.domain.txhistory.models.TxHistoryItem.* -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents +import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.StringsSigns.MINUS import com.tangem.utils.StringsSigns.PLUS