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 ebdf08b11a..7115c1f18b 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 @@ -200,7 +200,7 @@ internal class ChildFactory @Inject constructor( createComponentChild( context = context, params = OnrampComponent.Params( - userWalletId = route.userWalletId, + userWalletId = route.portfolioId.userWalletId, // todo account portfolioId param, cryptoCurrency = route.currency, source = route.source, launchSepa = route.launchSepa, @@ -274,7 +274,7 @@ internal class ChildFactory @Inject constructor( createComponentChild( context = context, params = TokenDetailsComponent.Params( - userWalletId = route.userWalletId, + userWalletId = route.portfolioId.userWalletId, // todo account portfolioId param currency = route.currency, ), componentFactory = tokenDetailsComponentFactory, @@ -284,7 +284,7 @@ internal class ChildFactory @Inject constructor( createComponentChild( context = context, params = StakingComponent.Params( - userWalletId = route.userWalletId, + userWalletId = route.portfolioId.userWalletId, // todo account portfolioId param, cryptoCurrencyId = route.cryptoCurrencyId, yieldId = route.yieldId, ), @@ -297,7 +297,7 @@ internal class ChildFactory @Inject constructor( params = SwapComponent.Params( currencyFrom = route.currencyFrom, currencyTo = route.currencyTo, - userWalletId = route.userWalletId, + userWalletId = route.portfolioId.userWalletId, // todo account portfolioId param, isInitialReverseOrder = route.isInitialReverseOrder, screenSource = route.screenSource, ), @@ -308,7 +308,7 @@ internal class ChildFactory @Inject constructor( createComponentChild( context = context, params = SendComponent.Params( - userWalletId = route.userWalletId, + userWalletId = route.portfolioId.userWalletId, // todo account portfolioId param, currency = route.currency, transactionId = route.transactionId, amount = route.amount, diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index 0a8969253b..c7f93ffccc 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -1,5 +1,6 @@ package com.tangem.common.routing +import android.annotation.SuppressLint import android.os.Bundle import com.tangem.common.routing.bundle.RouteBundleParams import com.tangem.common.routing.bundle.bundle @@ -8,6 +9,7 @@ import com.tangem.core.decompose.navigation.Route import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.feedback.models.WalletMetaInfo import com.tangem.domain.markets.TokenMarketParams +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.scan.ScanResponse @@ -16,6 +18,7 @@ import com.tangem.domain.nft.models.NFTAsset import com.tangem.domain.onramp.model.OnrampSource import kotlinx.serialization.Serializable +@SuppressLint("UnsafeOptInUsageError") @Serializable sealed class AppRoute(val path: String) : Route { @@ -46,25 +49,50 @@ sealed class AppRoute(val path: String) : Route { @Serializable data class CurrencyDetails( - val userWalletId: UserWalletId, + val portfolioId: PortfolioId, val currency: CryptoCurrency, - ) : AppRoute(path = "/currency_details/${userWalletId.stringValue}/${currency.id.value}") + ) : AppRoute(path = "/currency_details/${portfolioId.stringValue}/${currency.id.value}") { + companion object { + operator fun invoke(userWalletId: UserWalletId, currency: CryptoCurrency) = CurrencyDetails( + portfolioId = PortfolioId(userWalletId), + currency = currency, + ) + } + } @Serializable data class Send( - val userWalletId: UserWalletId, + val portfolioId: PortfolioId, val currency: CryptoCurrency, val transactionId: String? = null, val amount: String? = null, val tag: String? = null, val destinationAddress: String? = null, ) : AppRoute( - path = "/send/${userWalletId.stringValue}/${currency.id.value}?" + + path = "/send/${portfolioId.stringValue}/${currency.id.value}?" + "&$transactionId" + "&$amount" + "&$tag" + "&$destinationAddress", - ) + ) { + companion object { + operator fun invoke( + userWalletId: UserWalletId, + currency: CryptoCurrency, + transactionId: String? = null, + amount: String? = null, + tag: String? = null, + destinationAddress: String? = null, + ) = Send( + portfolioId = PortfolioId(userWalletId), + currency = currency, + transactionId = transactionId, + amount = amount, + tag = tag, + destinationAddress = destinationAddress, + ) + } + } @Serializable data class Details( @@ -169,26 +197,51 @@ sealed class AppRoute(val path: String) : Route { data class Swap( val currencyFrom: CryptoCurrency, val currencyTo: CryptoCurrency? = null, - val userWalletId: UserWalletId, + val portfolioId: PortfolioId, val isInitialReverseOrder: Boolean = false, val screenSource: String, ) : AppRoute( path = "/swap" + "/${currencyFrom.id.value}" + "/${currencyTo?.id?.value}" + - "/${userWalletId.stringValue}" + + "/${portfolioId.stringValue}" + "/$isInitialReverseOrder", - ) + ) { + companion object { + operator fun invoke( + userWalletId: UserWalletId, + currencyFrom: CryptoCurrency, + currencyTo: CryptoCurrency? = null, + isInitialReverseOrder: Boolean = false, + screenSource: String, + ) = Swap( + portfolioId = PortfolioId(userWalletId), + currencyFrom = currencyFrom, + currencyTo = currencyTo, + isInitialReverseOrder = isInitialReverseOrder, + screenSource = screenSource, + ) + } + } @Serializable data object AppCurrencySelector : AppRoute(path = "/app_currency_selector") @Serializable data class Staking( - val userWalletId: UserWalletId, + val portfolioId: PortfolioId, val cryptoCurrencyId: CryptoCurrency.ID, val yieldId: String, - ) : AppRoute(path = "/staking/${userWalletId.stringValue}/${cryptoCurrencyId.value}/$yieldId") + ) : AppRoute(path = "/staking/${portfolioId.stringValue}/${cryptoCurrencyId.value}/$yieldId") { + companion object { + operator fun invoke(userWalletId: UserWalletId, cryptoCurrencyId: CryptoCurrency.ID, yieldId: String) = + Staking( + portfolioId = PortfolioId(userWalletId), + cryptoCurrencyId = cryptoCurrencyId, + yieldId = yieldId, + ) + } + } @Serializable data class PushNotification( @@ -232,11 +285,25 @@ sealed class AppRoute(val path: String) : Route { @Serializable data class Onramp( val source: OnrampSource, - val userWalletId: UserWalletId, + val portfolioId: PortfolioId, val currency: CryptoCurrency, val launchSepa: Boolean = false, - ) : AppRoute(path = "/onramp/${userWalletId.stringValue}/${currency.symbol}"), RouteBundleParams { + ) : AppRoute(path = "/onramp/${portfolioId.stringValue}/${currency.symbol}"), RouteBundleParams { override fun getBundle(): Bundle = bundle(serializer()) + + companion object { + operator fun invoke( + source: OnrampSource, + userWalletId: UserWalletId, + currency: CryptoCurrency, + launchSepa: Boolean = false, + ) = Onramp( + source = source, + portfolioId = PortfolioId(userWalletId), + currency = currency, + launchSepa = launchSepa, + ) + } } @Serializable diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/PortfolioId.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/PortfolioId.kt new file mode 100644 index 0000000000..07b9e3d022 --- /dev/null +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/PortfolioId.kt @@ -0,0 +1,38 @@ +package com.tangem.domain.models + +import com.tangem.domain.models.account.AccountId +import com.tangem.domain.models.wallet.UserWalletId +import kotlinx.serialization.Serializable + +/** + * Temporary wrapper over ID to support a gradual migration between two modes: + * + * - [Wallet] — legacy flow, wallet design; used when the [AccountsFeatureToggles] is disabled. + * - [Account] — new flow, wallet/account design; used when the [AccountsFeatureToggles] is enabled. + * + * ⚠️ When an [Account] you must verify the current app mode with [IsAccountsModeEnabledUseCase] + * and then use wallet/account design + * + * Intended to be removed after the full migration to the new mode. + */ +@Serializable +sealed interface PortfolioId { + val userWalletId: UserWalletId + val stringValue: String + + @Serializable + data class Wallet(override val userWalletId: UserWalletId) : PortfolioId { + override val stringValue: String = userWalletId.stringValue + } + + @Serializable + data class Account(val accountId: AccountId) : PortfolioId { + override val userWalletId: UserWalletId get() = accountId.userWalletId + override val stringValue: String = accountId.value + } + + companion object { + operator fun invoke(accountId: AccountId) = Account(accountId) + operator fun invoke(userWalletId: UserWalletId) = Wallet(userWalletId) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt index 02797b8594..eb07bc02f7 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt @@ -4,6 +4,7 @@ import arrow.core.getOrElse import com.tangem.common.ui.expressStatus.ExpressStatusBottomSheetConfig import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.decompose.di.ModelScoped +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet @@ -44,9 +45,9 @@ internal interface WalletContentClickIntents { fun onDismissMarketsOnboarding() - fun onTokenItemClick(currencyStatus: CryptoCurrencyStatus) + fun onTokenItemClick(portfolioId: PortfolioId, currencyStatus: CryptoCurrencyStatus) - fun onTokenItemLongClick(cryptoCurrencyStatus: CryptoCurrencyStatus) + fun onTokenItemLongClick(portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus) fun onAccountExpandClick(account: Account) @@ -137,13 +138,13 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( } } - override fun onTokenItemClick(currencyStatus: CryptoCurrencyStatus) { - router.openTokenDetails(stateHolder.getSelectedWalletId(), currencyStatus) + override fun onTokenItemClick(portfolioId: PortfolioId, currencyStatus: CryptoCurrencyStatus) { + router.openTokenDetails(portfolioId, currencyStatus) } - override fun onTokenItemLongClick(cryptoCurrencyStatus: CryptoCurrencyStatus) { + override fun onTokenItemLongClick(portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus) { modelScope.launch(dispatchers.main) { - val userWalletId = stateHolder.getSelectedWalletId() + val userWalletId = portfolioId.userWalletId val userWallet = getUserWalletUseCase(userWalletId).getOrElse { Timber.e( """ @@ -159,7 +160,7 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( getCryptoCurrencyActionsUseCase(userWallet = userWallet, cryptoCurrencyStatus = cryptoCurrencyStatus) .take(count = 1) .collectLatest { - showActionsBottomSheet(it, userWallet) + showActionsBottomSheet(it, userWallet, portfolioId) } } } @@ -174,12 +175,17 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( accountDependencies.expandedAccountsHolder.collapseAccount(userWalletId, account.accountId) } - private fun showActionsBottomSheet(tokenActionsState: TokenActionsState, userWallet: UserWallet) { + private fun showActionsBottomSheet( + tokenActionsState: TokenActionsState, + userWallet: UserWallet, + portfolioId: PortfolioId, + ) { stateHolder.showBottomSheet( ActionsBottomSheetConfig( actions = MultiWalletCurrencyActionsConverter( userWallet = userWallet, clickIntents = currencyActionsClickIntents, + portfolioId = portfolioId, ).convert(tokenActionsState), ), userWallet.walletId, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt index e7876af2a1..621784608c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletCurrencyActionsClickIntents.kt @@ -29,6 +29,7 @@ import com.tangem.domain.core.utils.lceError import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.exchange.RampStateManager import com.tangem.domain.markets.TokenMarketParams +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.ReceiveAddressModel import com.tangem.domain.models.TokenReceiveConfig import com.tangem.domain.models.currency.CryptoCurrency @@ -44,8 +45,6 @@ import com.tangem.domain.redux.ReduxStateHolder import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.GetViewedTokenReceiveWarningUseCase -import com.tangem.domain.tokens.IsCryptoCurrencyCoinCouldHideUseCase -import com.tangem.domain.tokens.RemoveCurrencyUseCase import com.tangem.domain.tokens.legacy.TradeCryptoAction import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason import com.tangem.domain.tokens.model.analytics.TokenReceiveAnalyticsEvent @@ -67,6 +66,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState import com.tangem.feature.wallet.presentation.wallet.state.transformers.CloseBottomSheetTransformer import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender +import com.tangem.feature.wallet.presentation.wallet.utils.WalletFeatureUseCasesFacade import com.tangem.features.tokenreceive.TokenReceiveFeatureToggle import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.collections.immutable.toImmutableList @@ -78,29 +78,41 @@ import javax.inject.Inject interface WalletCurrencyActionsClickIntents { - fun onSendClick(cryptoCurrencyStatus: CryptoCurrencyStatus, unavailabilityReason: ScenarioUnavailabilityReason) - - fun onSellClick(cryptoCurrencyStatus: CryptoCurrencyStatus, unavailabilityReason: ScenarioUnavailabilityReason) - - fun onBuyClick(cryptoCurrencyStatus: CryptoCurrencyStatus, unavailabilityReason: ScenarioUnavailabilityReason) - - fun onSwapClick( + fun onSendClick( + portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus, - userWalletId: UserWalletId, unavailabilityReason: ScenarioUnavailabilityReason, ) - fun onReceiveClick(cryptoCurrencyStatus: CryptoCurrencyStatus, event: AnalyticsEvent? = null) + fun onSellClick(cryptoCurrencyStatus: CryptoCurrencyStatus, unavailabilityReason: ScenarioUnavailabilityReason) - fun onStakeClick(cryptoCurrencyStatus: CryptoCurrencyStatus, yield: Yield?) + fun onBuyClick( + portfolioId: PortfolioId, + cryptoCurrencyStatus: CryptoCurrencyStatus, + unavailabilityReason: ScenarioUnavailabilityReason, + ) + + fun onSwapClick( + cryptoCurrencyStatus: CryptoCurrencyStatus, + portfolioId: PortfolioId, + unavailabilityReason: ScenarioUnavailabilityReason, + ) + + fun onReceiveClick( + portfolioId: PortfolioId, + cryptoCurrencyStatus: CryptoCurrencyStatus, + event: AnalyticsEvent? = null, + ) + + fun onStakeClick(portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus, yield: Yield?) fun onCopyAddressLongClick(cryptoCurrencyStatus: CryptoCurrencyStatus): TextReference? - fun onCopyAddressClick(cryptoCurrencyStatus: CryptoCurrencyStatus) + fun onCopyAddressClick(portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus) - fun onHideTokensClick(cryptoCurrencyStatus: CryptoCurrencyStatus) + fun onHideTokensClick(portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus) - fun onPerformHideToken(cryptoCurrencyStatus: CryptoCurrencyStatus) + fun onPerformHideToken(portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus) fun onExploreClick() @@ -122,8 +134,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( private val walletManagersFacade: WalletManagersFacade, private val isDemoCardUseCase: IsDemoCardUseCase, private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, - private val isCryptoCurrencyCoinCouldHide: IsCryptoCurrencyCoinCouldHideUseCase, - private val removeCurrencyUseCase: RemoveCurrencyUseCase, + private val useCasesFacade: WalletFeatureUseCasesFacade, private val getExploreUrlUseCase: GetExploreUrlUseCase, private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, private val getStoryContentUseCase: GetStoryContentUseCase, @@ -141,11 +152,10 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( ) : BaseWalletClickIntents(), WalletCurrencyActionsClickIntents { override fun onSendClick( + portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus, unavailabilityReason: ScenarioUnavailabilityReason, ) { - val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return - analyticsEventHandler.send( event = TokenScreenAnalyticsEvent.ButtonWithParams.ButtonSend( token = cryptoCurrencyStatus.currency.symbol, @@ -156,17 +166,25 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( if (handleUnavailabilityReason(unavailabilityReason)) return - stateHolder.update(CloseBottomSheetTransformer(userWalletId = userWallet.walletId)) + stateHolder.update(CloseBottomSheetTransformer(userWalletId = portfolioId.userWalletId)) val route = AppRoute.Send( currency = cryptoCurrencyStatus.currency, - userWalletId = userWallet.walletId, + portfolioId = portfolioId, ) appRouter.push(route) } - override fun onReceiveClick(cryptoCurrencyStatus: CryptoCurrencyStatus, event: AnalyticsEvent?) { - val userWalletId = stateHolder.getSelectedWalletId() + override fun onReceiveClick( + portfolioId: PortfolioId, + cryptoCurrencyStatus: CryptoCurrencyStatus, + event: AnalyticsEvent?, + ) { + val userWalletId = portfolioId.userWalletId + if (portfolioId is PortfolioId.Account) { + // todo account find address + TODO("account") + } analyticsEventHandler.send( event = TokenScreenAnalyticsEvent.ButtonWithParams.ButtonReceive( @@ -240,7 +258,12 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( ) } - override fun onCopyAddressClick(cryptoCurrencyStatus: CryptoCurrencyStatus) { + override fun onCopyAddressClick(portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus) { + val userWalletId = portfolioId.userWalletId + if (portfolioId is PortfolioId.Account) { + // todo account find address + TODO("account") + } analyticsEventHandler.send( event = TokenReceiveNewAnalyticsEvent.ButtonCopyAddress( token = cryptoCurrencyStatus.currency.symbol, @@ -251,10 +274,10 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( modelScope.launch(dispatchers.main) { walletManagersFacade.getDefaultAddress( - userWalletId = stateHolder.getSelectedWalletId(), + userWalletId = userWalletId, network = cryptoCurrencyStatus.currency.network, )?.let { address -> - stateHolder.update(CloseBottomSheetTransformer(userWalletId = stateHolder.getSelectedWalletId())) + stateHolder.update(CloseBottomSheetTransformer(userWalletId = userWalletId)) clipboardManager.setText(text = address, isSensitive = true) walletEventSender.send(event = WalletEvent.CopyAddress) @@ -262,7 +285,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( } } - override fun onHideTokensClick(cryptoCurrencyStatus: CryptoCurrencyStatus) { + override fun onHideTokensClick(portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus) { analyticsEventHandler.send( event = TokenScreenAnalyticsEvent.ButtonRemoveToken(cryptoCurrencyStatus.currency.symbol), ) @@ -270,18 +293,20 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( modelScope.launch(dispatchers.main) { walletEventSender.send( event = WalletEvent.ShowAlert( - state = getHideTokeAlertConfig(stateHolder.getSelectedWalletId(), cryptoCurrencyStatus), + state = getHideTokeAlertConfig(portfolioId, cryptoCurrencyStatus), ), ) } } private suspend fun getHideTokeAlertConfig( - userWalletId: UserWalletId, + portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus, ): WalletAlertState.DefaultAlert { val currency = cryptoCurrencyStatus.currency - return if (currency is CryptoCurrency.Coin && !isCryptoCurrencyCoinCouldHide(userWalletId, currency)) { + val isCryptoCurrencyCoinCouldHide = currency is CryptoCurrency.Coin && + !useCasesFacade.isCryptoCurrencyCoinCouldHide(portfolioId = portfolioId, cryptoCurrencyCoin = currency) + return if (isCryptoCurrencyCoinCouldHide) { WalletAlertState.DefaultAlert( title = resourceReference( id = R.string.token_details_unable_hide_alert_title, @@ -306,16 +331,14 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( formatArgs = WrappedList(listOf(cryptoCurrencyStatus.currency.name)), ), message = resourceReference(R.string.token_details_hide_alert_message), - onConfirmClick = { onPerformHideToken(cryptoCurrencyStatus) }, + onConfirmClick = { onPerformHideToken(portfolioId, cryptoCurrencyStatus) }, ) } } - override fun onPerformHideToken(cryptoCurrencyStatus: CryptoCurrencyStatus) { - val userWalletId = stateHolder.getSelectedWalletId() - + override fun onPerformHideToken(portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus) { modelScope.launch(dispatchers.io) { - removeCurrencyUseCase(userWalletId, cryptoCurrencyStatus.currency) + useCasesFacade.removeCurrencyUseCase(portfolioId, cryptoCurrencyStatus.currency) .fold( ifLeft = { walletEventSender.send( @@ -323,7 +346,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( ) }, ifRight = { - stateHolder.update(CloseBottomSheetTransformer(userWalletId = userWalletId)) + stateHolder.update(CloseBottomSheetTransformer(userWalletId = portfolioId.userWalletId)) }, ) } @@ -356,11 +379,10 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( } override fun onBuyClick( + portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus, unavailabilityReason: ScenarioUnavailabilityReason, ) { - val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return - analyticsEventHandler.send( event = TokenScreenAnalyticsEvent.ButtonWithParams.ButtonBuy( token = cryptoCurrencyStatus.currency.symbol, @@ -373,7 +395,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( appRouter.push( AppRoute.Onramp( - userWalletId = userWallet.walletId, + portfolioId = portfolioId, currency = cryptoCurrencyStatus.currency, source = OnrampSource.TOKEN_LONG_TAP, ), @@ -382,7 +404,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( override fun onSwapClick( cryptoCurrencyStatus: CryptoCurrencyStatus, - userWalletId: UserWalletId, + portfolioId: PortfolioId, unavailabilityReason: ScenarioUnavailabilityReason, ) { analyticsEventHandler.send( @@ -398,7 +420,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( appRouter.push( AppRoute.Swap( currencyFrom = cryptoCurrencyStatus.currency, - userWalletId = userWalletId, + portfolioId = portfolioId, screenSource = AnalyticsParam.ScreensSources.LongTap.value, ), ) @@ -440,17 +462,15 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor( } } - override fun onStakeClick(cryptoCurrencyStatus: CryptoCurrencyStatus, yield: Yield?) { - val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return - stateHolder.update(CloseBottomSheetTransformer(userWalletId = userWallet.walletId)) + override fun onStakeClick(portfolioId: PortfolioId, cryptoCurrencyStatus: CryptoCurrencyStatus, yield: Yield?) { + stateHolder.update(CloseBottomSheetTransformer(userWalletId = portfolioId.userWalletId)) modelScope.launch { - val userWalletId = stateHolder.getSelectedWalletId() val cryptoCurrency = cryptoCurrencyStatus.currency appRouter.push( AppRoute.Staking( - userWalletId = userWalletId, + portfolioId = portfolioId, cryptoCurrencyId = cryptoCurrency.id, yieldId = yield?.id ?: return@launch, ), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt index 602de14421..2ac5b6e73f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt @@ -7,6 +7,7 @@ import com.tangem.common.routing.AppRoute.ManageTokens.Source import com.tangem.common.routing.AppRouter import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.navigation.url.UrlOpener +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.TokenReceiveConfig import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.scan.ScanResponse @@ -64,12 +65,12 @@ internal class DefaultWalletRouter @Inject constructor( urlOpener.openUrl(url) } - override fun openTokenDetails(userWalletId: UserWalletId, currencyStatus: CryptoCurrencyStatus) { + override fun openTokenDetails(portfolioId: PortfolioId, currencyStatus: CryptoCurrencyStatus) { val networkAddress = currencyStatus.value.networkAddress if (networkAddress != null && networkAddress.defaultAddress.value.isNotEmpty()) { router.push( AppRoute.CurrencyDetails( - userWalletId = userWalletId, + portfolioId = portfolioId, currency = currencyStatus.currency, ), ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt index 946a3e7692..c04b7026ce 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt @@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.router import androidx.compose.runtime.Stable import com.arkivanov.decompose.router.slot.SlotNavigation +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.TokenReceiveConfig import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.scan.ScanResponse @@ -39,7 +40,7 @@ internal interface InnerWalletRouter { fun openUrl(url: String) /** Open token details screen */ - fun openTokenDetails(userWalletId: UserWalletId, currencyStatus: CryptoCurrencyStatus) + fun openTokenDetails(portfolioId: PortfolioId, currencyStatus: CryptoCurrencyStatus) /** Open stories screen */ fun openStoriesScreen() diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt index b6d7259fc8..f4d089e864 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoader.kt @@ -12,6 +12,7 @@ import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents +import com.tangem.feature.wallet.presentation.account.AccountDependencies import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController @@ -35,6 +36,7 @@ internal class SingleWalletContentLoader( private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val analyticsEventHandler: AnalyticsEventHandler, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, + private val accountDependencies: AccountDependencies, ) : WalletContentLoader(id = userWallet.walletId) { override fun create(): List { @@ -53,6 +55,7 @@ internal class SingleWalletContentLoader( clickIntents = clickIntents, getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase, getCryptoCurrencyActionsUseCase = getCryptoCurrencyActionsUseCase, + accountDependencies = accountDependencies, ), SingleWalletNotificationsSubscriber( userWallet = userWallet, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt index a764909269..e5fe7a2155 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/SingleWalletContentLoaderFactory.kt @@ -13,6 +13,7 @@ import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.wallets.usecase.ShouldSaveUserWalletsUseCase import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents +import com.tangem.feature.wallet.presentation.account.AccountDependencies import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController @@ -34,12 +35,14 @@ internal class SingleWalletContentLoaderFactory @Inject constructor( private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase, private val analyticsEventHandler: AnalyticsEventHandler, private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender, + private val accountDependencies: AccountDependencies, ) { fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader { return SingleWalletContentLoader( userWallet = userWallet, clickIntents = clickIntents, + accountDependencies = accountDependencies, isRefresh = isRefresh, stateHolder = stateHolder, getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetCryptoCurrencyActionsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetCryptoCurrencyActionsTransformer.kt index 43f812b0dd..9565609246 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetCryptoCurrencyActionsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetCryptoCurrencyActionsTransformer.kt @@ -1,6 +1,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers import com.tangem.domain.card.common.util.cardTypesResolver +import com.tangem.domain.models.PortfolioId import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason import com.tangem.domain.tokens.model.TokenActionsState import com.tangem.domain.models.wallet.UserWallet @@ -14,6 +15,7 @@ import timber.log.Timber internal class SetCryptoCurrencyActionsTransformer( private val tokenActionsState: TokenActionsState, private val userWallet: UserWallet, + private val portfolioId: PortfolioId, private val clickIntents: WalletClickIntents, ) : WalletStateTransformer(userWallet.walletId) { @@ -48,6 +50,7 @@ internal class SetCryptoCurrencyActionsTransformer( dimContent = action.unavailabilityReason != ScenarioUnavailabilityReason.None, onClick = { clickIntents.onBuyClick( + portfolioId = portfolioId, cryptoCurrencyStatus = cryptoCurrencyStatus, unavailabilityReason = action.unavailabilityReason, ) @@ -59,7 +62,7 @@ internal class SetCryptoCurrencyActionsTransformer( enabled = true, dimContent = action.unavailabilityReason != ScenarioUnavailabilityReason.None, onClick = { - clickIntents.onReceiveClick(cryptoCurrencyStatus = cryptoCurrencyStatus) + clickIntents.onReceiveClick(portfolioId, cryptoCurrencyStatus = cryptoCurrencyStatus) }, onLongClick = { clickIntents.onCopyAddressLongClick(cryptoCurrencyStatus = cryptoCurrencyStatus) @@ -84,6 +87,7 @@ internal class SetCryptoCurrencyActionsTransformer( dimContent = action.unavailabilityReason != ScenarioUnavailabilityReason.None, onClick = { clickIntents.onSendClick( + portfolioId = portfolioId, cryptoCurrencyStatus = cryptoCurrencyStatus, unavailabilityReason = action.unavailabilityReason, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetVisaInfoTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetVisaInfoTransformer.kt index 751185ccf4..2435c086e7 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetVisaInfoTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetVisaInfoTransformer.kt @@ -9,6 +9,7 @@ import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.fiat import com.tangem.core.ui.format.bigdecimal.format import com.tangem.domain.card.common.util.getCardsCount +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.visa.exception.RefreshTokenExpiredException @@ -148,7 +149,11 @@ internal class SetVisaInfoTransformer( enabled = true, dimContent = false, onClick = { - clickIntents.onReceiveClick(cryptoCurrencyStatus, MainScreenAnalyticsEvent.ButtonReceive) + clickIntents.onReceiveClick( + portfolioId = PortfolioId(userWalletId), // todo account Visa use Main account? + cryptoCurrencyStatus = cryptoCurrencyStatus, + event = MainScreenAnalyticsEvent.ButtonReceive, + ) }, onLongClick = { clickIntents.onCopyAddressLongClick(cryptoCurrencyStatus) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/TokenConverterParams.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/TokenConverterParams.kt index 36fff6baf9..fd8229e5e8 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/TokenConverterParams.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/TokenConverterParams.kt @@ -1,11 +1,13 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers import com.tangem.domain.account.models.AccountStatusList +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.tokenlist.TokenList sealed interface TokenConverterParams { data class Wallet( + val portfolioId: PortfolioId, val tokenList: TokenList, ) : TokenConverterParams diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/MultiWalletCurrencyActionsConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/MultiWalletCurrencyActionsConverter.kt index 97a13ed361..6a88f70616 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/MultiWalletCurrencyActionsConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/MultiWalletCurrencyActionsConverter.kt @@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers.convert import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.domain.card.common.util.cardTypesResolver +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason @@ -17,6 +18,7 @@ import kotlinx.collections.immutable.toImmutableList internal class MultiWalletCurrencyActionsConverter( private val userWallet: UserWallet, + private val portfolioId: PortfolioId, private val clickIntents: WalletCurrencyActionsClickIntents, ) : Converter> { @@ -46,7 +48,7 @@ internal class MultiWalletCurrencyActionsConverter( if (actionsState is TokenActionsState.ActionState.Send && cryptoCurrencyStatus.value.amount.isNullOrZero()) { return null } - + val noneReason = ScenarioUnavailabilityReason.None val title: TextReference val icon: Int val action: () -> Unit @@ -54,27 +56,27 @@ internal class MultiWalletCurrencyActionsConverter( is TokenActionsState.ActionState.Buy -> { title = resourceReference(R.string.common_buy) icon = R.drawable.ic_plus_24 - action = { clickIntents.onBuyClick(cryptoCurrencyStatus, ScenarioUnavailabilityReason.None) } + action = { clickIntents.onBuyClick(portfolioId, cryptoCurrencyStatus, noneReason) } } is TokenActionsState.ActionState.Receive -> { title = resourceReference(R.string.common_receive) icon = R.drawable.ic_arrow_down_24 - action = { clickIntents.onReceiveClick(cryptoCurrencyStatus) } + action = { clickIntents.onReceiveClick(portfolioId, cryptoCurrencyStatus) } } is TokenActionsState.ActionState.Stake -> { title = resourceReference(R.string.common_stake) icon = R.drawable.ic_staking_24 - action = { clickIntents.onStakeClick(cryptoCurrencyStatus, actionsState.yield) } + action = { clickIntents.onStakeClick(portfolioId, cryptoCurrencyStatus, actionsState.yield) } } is TokenActionsState.ActionState.Sell -> { title = resourceReference(R.string.common_sell) icon = R.drawable.ic_currency_24 - action = { clickIntents.onSellClick(cryptoCurrencyStatus, ScenarioUnavailabilityReason.None) } + action = { clickIntents.onSellClick(cryptoCurrencyStatus, noneReason) } } is TokenActionsState.ActionState.Send -> { title = resourceReference(R.string.common_send) icon = R.drawable.ic_arrow_up_24 - action = { clickIntents.onSendClick(cryptoCurrencyStatus, ScenarioUnavailabilityReason.None) } + action = { clickIntents.onSendClick(portfolioId, cryptoCurrencyStatus, noneReason) } } is TokenActionsState.ActionState.Swap -> { title = resourceReference(R.string.swapping_swap_action) @@ -82,20 +84,20 @@ internal class MultiWalletCurrencyActionsConverter( action = { clickIntents.onSwapClick( cryptoCurrencyStatus = cryptoCurrencyStatus, - userWalletId = userWallet.walletId, - unavailabilityReason = ScenarioUnavailabilityReason.None, + portfolioId = portfolioId, + unavailabilityReason = noneReason, ) } } is TokenActionsState.ActionState.CopyAddress -> { title = resourceReference(R.string.common_copy_address) icon = R.drawable.ic_copy_24 - action = { clickIntents.onCopyAddressClick(cryptoCurrencyStatus) } + action = { clickIntents.onCopyAddressClick(portfolioId, cryptoCurrencyStatus) } } is TokenActionsState.ActionState.HideToken -> { title = resourceReference(R.string.token_details_hide_token) icon = R.drawable.ic_hide_24 - action = { clickIntents.onHideTokensClick(cryptoCurrencyStatus) } + action = { clickIntents.onHideTokensClick(portfolioId, cryptoCurrencyStatus) } } is TokenActionsState.ActionState.Analytics -> { title = resourceReference(R.string.common_analytics) @@ -109,7 +111,7 @@ internal class MultiWalletCurrencyActionsConverter( iconResId = icon, onClick = action, isWarning = actionsState is TokenActionsState.ActionState.HideToken, - enabled = actionsState.unavailabilityReason == ScenarioUnavailabilityReason.None, + enabled = actionsState.unavailabilityReason == noneReason, ) } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt index 4726ebf77a..449ecf2c3b 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/converter/TokenListStateConverter.kt @@ -8,8 +8,10 @@ import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.card.common.util.cardTypesResolver +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.TotalFiatBalance import com.tangem.domain.models.account.Account +import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.account.AccountStatus import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.tokenlist.TokenList @@ -34,34 +36,46 @@ internal class TokenListStateConverter( private val clickIntents: WalletClickIntents, ) : Converter { - private val tokenStatusConverter = when (params) { - is TokenConverterParams.Account, // todo account Click with accountId param - is TokenConverterParams.Wallet, - -> TokenItemStateConverter( - appCurrency = appCurrency, - onItemClick = { _, status -> clickIntents.onTokenItemClick(status) }, - onItemLongClick = { _, status -> clickIntents.onTokenItemLongClick(status) }, - ) - } + private val onTokenClick: (accountId: AccountId?, currencyStatus: CryptoCurrencyStatus) -> Unit = + { accountId, currencyStatus -> + val id = accountId?.let { PortfolioId(accountId) } ?: PortfolioId(selectedWallet.walletId) + clickIntents.onTokenItemClick(id, currencyStatus) + } + + private val onTokenLongClick: (accountId: AccountId?, currencyStatus: CryptoCurrencyStatus) -> Unit = + { accountId, currencyStatus -> + val id = accountId?.let { PortfolioId(accountId) } ?: PortfolioId(selectedWallet.walletId) + clickIntents.onTokenItemLongClick(id, currencyStatus) + } + + private fun tokenStatusConverter(accountId: AccountId? = null) = TokenItemStateConverter( + appCurrency = appCurrency, + onItemClick = { _, status -> onTokenClick(accountId, status) }, + onItemLongClick = { _, status -> onTokenLongClick(accountId, status) }, + ) override fun convert(value: WalletTokensListState): WalletTokensListState { return when (params) { is TokenConverterParams.Account -> convertAccountList(params) - is TokenConverterParams.Wallet -> convertTokenList(params.tokenList) + is TokenConverterParams.Wallet -> convertTokenList( + tokenConverter = tokenStatusConverter((params.portfolioId as? PortfolioId.Account)?.accountId), + tokenList = params.tokenList, + ) } } - private fun convertTokenList(tokenList: TokenList): WalletTokensListState = when (tokenList) { - is TokenList.Empty -> WalletTokensListState.Empty - is TokenList.GroupedByNetwork -> WalletTokensListState.ContentState.Content( - items = tokenList.toGroupedItems(), - organizeTokensButtonConfig = getOrganizeTokensButtonState(tokenList = tokenList), - ) - is TokenList.Ungrouped -> WalletTokensListState.ContentState.Content( - items = tokenList.toUngroupedItems(), - organizeTokensButtonConfig = getOrganizeTokensButtonState(tokenList = tokenList), - ) - } + private fun convertTokenList(tokenConverter: TokenItemStateConverter, tokenList: TokenList): WalletTokensListState = + when (tokenList) { + is TokenList.Empty -> WalletTokensListState.Empty + is TokenList.GroupedByNetwork -> WalletTokensListState.ContentState.Content( + items = tokenList.toGroupedItems(tokenConverter), + organizeTokensButtonConfig = getOrganizeTokensButtonState(tokenList = tokenList), + ) + is TokenList.Ungrouped -> WalletTokensListState.ContentState.Content( + items = tokenList.toUngroupedItems(tokenConverter), + organizeTokensButtonConfig = getOrganizeTokensButtonState(tokenList = tokenList), + ) + } private fun convertAccountList(params: TokenConverterParams.Account): WalletTokensListState { val accountList = params.accountList @@ -85,7 +99,8 @@ internal class TokenListStateConverter( onItemClick = onItemClick, ) val accountItem = converter.convert(tokenList.totalFiatBalance) - val tokensListState = convertTokenList(tokenList) + val tokenConverter = tokenStatusConverter(account.accountId) + val tokensListState = convertTokenList(tokenConverter, tokenList) val items = when (tokensListState) { is WalletTokensListState.ContentState.PortfolioContent -> tokensListState.items is WalletTokensListState.ContentState.Content -> tokensListState.items @@ -112,19 +127,26 @@ internal class TokenListStateConverter( ) } - private fun TokenList.GroupedByNetwork.toGroupedItems(): PersistentList { + private fun TokenList.GroupedByNetwork.toGroupedItems( + tokenConverter: TokenItemStateConverter, + ): PersistentList { return groups.fold(initial = persistentListOf()) { acc, group -> - acc.mutate { it.addGroup(group) } + acc.mutate { it.addGroup(tokenConverter, group) } } } - private fun TokenList.Ungrouped.toUngroupedItems(): PersistentList { + private fun TokenList.Ungrouped.toUngroupedItems( + tokenConverter: TokenItemStateConverter, + ): PersistentList { return currencies.fold(initial = persistentListOf()) { acc, token -> - acc.mutate { it.addToken(token) } + acc.mutate { it.addToken(tokenConverter, token) } } } - private fun MutableList.addGroup(group: NetworkGroup): List { + private fun MutableList.addGroup( + tokenConverter: TokenItemStateConverter, + group: NetworkGroup, + ): List { val groupTitle = TokensListItemUM.GroupTitle( id = group.network.hashCode(), text = resourceReference( @@ -134,13 +156,16 @@ internal class TokenListStateConverter( ) add(groupTitle) - group.currencies.forEach { token -> addToken(token) } + group.currencies.forEach { token -> addToken(tokenConverter, token) } return this } - private fun MutableList.addToken(token: CryptoCurrencyStatus): List { - val tokenItemState = tokenStatusConverter.convert(token) + private fun MutableList.addToken( + tokenConverter: TokenItemStateConverter, + token: CryptoCurrencyStatus, + ): List { + val tokenItemState = tokenConverter.convert(token) add(TokensListItemUM.Token(tokenItemState)) return this diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt index 6b4a53b2b5..6f7cb91a9f 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/BasicTokenListSubscriber.kt @@ -7,6 +7,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.core.lce.Lce import com.tangem.domain.core.lce.LceFlow import com.tangem.domain.core.utils.getOrElse +import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.account.AccountStatus import com.tangem.domain.models.tokenlist.TokenList import com.tangem.domain.models.wallet.UserWallet @@ -72,13 +73,16 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { coroutineScope.launch { startCheck(maybeTokenList) } }, flow2 = appCurrencyFlow(), - transform = { maybeTokenList, appCurrency -> singleAccountTransform(maybeTokenList, appCurrency) }, + transform = { maybeTokenList, appCurrency -> + singleAccountTransform(maybeTokenList, appCurrency, PortfolioId(userWallet.walletId)) + }, ) } private suspend fun singleAccountTransform( maybeTokenList: Lce, appCurrency: AppCurrency, + portfolioId: PortfolioId, ) { val tokenList = maybeTokenList.getOrElse( ifLoading = { maybeContent -> @@ -102,8 +106,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { return }, ) - - updateContent(TokenConverterParams.Wallet(tokenList), appCurrency) + updateContent(TokenConverterParams.Wallet(portfolioId, tokenList), appCurrency) walletWithFundsChecker.check(tokenList) } @@ -150,7 +153,7 @@ internal abstract class BasicTokenListSubscriber : WalletSubscriber() { } suspend fun singleAccountTransform(maybeTokenList: Lce) = - this.singleAccountTransform(maybeTokenList, appCurrency) + this.singleAccountTransform(maybeTokenList, appCurrency, PortfolioId(mainAccount.account.accountId)) when { !isAccountMode -> when (mainAccount.tokenList.flattenCurrencies().isEmpty()) { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletButtonsSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletButtonsSubscriber.kt index 3257952b84..830f1f9b69 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletButtonsSubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/SingleWalletButtonsSubscriber.kt @@ -1,10 +1,13 @@ package com.tangem.feature.wallet.presentation.wallet.subscribers +import com.tangem.domain.models.PortfolioId +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase import com.tangem.domain.tokens.model.TokenActionsState -import com.tangem.domain.models.wallet.UserWallet import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents +import com.tangem.feature.wallet.presentation.account.AccountDependencies import com.tangem.feature.wallet.presentation.wallet.domain.collectLatest import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController import com.tangem.feature.wallet.presentation.wallet.state.transformers.SetCryptoCurrencyActionsTransformer @@ -17,28 +20,39 @@ internal class SingleWalletButtonsSubscriber( private val clickIntents: WalletClickIntents, private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase, private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase, + private val accountDependencies: AccountDependencies, ) : WalletSubscriber() { override fun create(coroutineScope: CoroutineScope): Flow { return channelFlow { getSingleCryptoCurrencyStatusUseCase.collectLatest(userWalletId = userWallet.walletId) { status -> - getCryptoCurrencyActionsUseCase(userWallet = userWallet, cryptoCurrencyStatus = status) - .conflate() - .distinctUntilChanged() - .firstOrNull() + getCryptoCurrencyActionsUseCase(userWallet = userWallet, status = status) ?.let { send(it) } } } - .onEach(::updateContent) + .onEach { actions -> + val portfolioId = when (accountDependencies.accountsFeatureToggles.isFeatureEnabled) { + true -> TODO("account") // get main account id for single wallet + false -> PortfolioId(userWallet.walletId) + } + updateContent(actions, portfolioId) + } } - private fun updateContent(tokenActionsState: TokenActionsState) { + private fun updateContent(tokenActionsState: TokenActionsState, portfolioId: PortfolioId) { stateHolder.update( SetCryptoCurrencyActionsTransformer( tokenActionsState = tokenActionsState, userWallet = userWallet, clickIntents = clickIntents, + portfolioId = portfolioId, ), ) } + + private suspend fun getCryptoCurrencyActionsUseCase(userWallet: UserWallet, status: CryptoCurrencyStatus) = + this.getCryptoCurrencyActionsUseCase(userWallet = userWallet, cryptoCurrencyStatus = status) + .conflate() + .distinctUntilChanged() + .firstOrNull() } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/WalletFeatureUseCasesFacade.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/WalletFeatureUseCasesFacade.kt new file mode 100644 index 0000000000..8ab07acad0 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/utils/WalletFeatureUseCasesFacade.kt @@ -0,0 +1,24 @@ +package com.tangem.feature.wallet.presentation.wallet.utils + +import com.tangem.domain.models.PortfolioId +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.tokens.IsCryptoCurrencyCoinCouldHideUseCase +import com.tangem.domain.tokens.RemoveCurrencyUseCase +import javax.inject.Inject + +class WalletFeatureUseCasesFacade @Inject constructor( + private val isCryptoCurrencyCoinCouldHide: IsCryptoCurrencyCoinCouldHideUseCase, + private val removeCurrencyUseCase: RemoveCurrencyUseCase, +) { + + suspend fun isCryptoCurrencyCoinCouldHide(portfolioId: PortfolioId, cryptoCurrencyCoin: CryptoCurrency.Coin) = + when (portfolioId) { + is PortfolioId.Account -> TODO("account") + is PortfolioId.Wallet -> isCryptoCurrencyCoinCouldHide(portfolioId.userWalletId, cryptoCurrencyCoin) + } + + suspend fun removeCurrencyUseCase(portfolioId: PortfolioId, currency: CryptoCurrency) = when (portfolioId) { + is PortfolioId.Account -> TODO("account") + is PortfolioId.Wallet -> removeCurrencyUseCase(portfolioId.userWalletId, currency) + } +} \ No newline at end of file