Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-16 13:35:48 +03:00
parent 20efecd9ee
commit f08687d985
16 changed files with 70 additions and 45 deletions

View file

@ -13,6 +13,9 @@ android {
dependencies {
implementation(deps.compose.foundation)
/* Project - API */
api(projects.features.account.api)
/* Project - Core */
implementation(projects.core.decompose)
implementation(projects.core.ui)

View file

@ -1,17 +1,20 @@
package com.tangem.features.feed.components.market.details.portfolio.add.api
package com.tangem.features.feed.components.market.details.portfolio.add
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.domain.models.currency.CryptoCurrency
internal interface AddToPortfolioComponent : ComposableBottomSheetComponent {
interface AddToPortfolioComponent : ComposableBottomSheetComponent {
data class Params(
val addToPortfolioManager: AddToPortfolioManager,
val callback: Callback,
val shouldSkipTokenActionsScreen: Boolean = false,
)
interface Callback {
fun onDismiss()
fun onSuccess(addedToken: CryptoCurrency)
}
interface Factory : ComponentFactory<Params, AddToPortfolioComponent>

View file

@ -1,17 +1,17 @@
package com.tangem.features.feed.components.market.details.portfolio.add.api
package com.tangem.features.feed.components.market.details.portfolio.add
import com.tangem.domain.markets.TokenMarketInfo
import com.tangem.domain.markets.TokenMarketParams
import com.tangem.features.account.PortfolioFetcher
import com.tangem.features.feed.components.market.details.portfolio.api.MarketsPortfolioComponent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.serialization.Serializable
internal interface AddToPortfolioManager {
interface AddToPortfolioManager {
val token: TokenMarketParams
val analyticsParams: MarketsPortfolioComponent.AnalyticsParams?
val analyticsParams: AnalyticsParams?
val portfolioFetcher: PortfolioFetcher
val state: StateFlow<State>
@ -28,11 +28,16 @@ internal interface AddToPortfolioManager {
data object NothingToAdd : State
}
@Serializable
data class AnalyticsParams(
val source: String,
)
interface Factory {
fun create(
scope: CoroutineScope,
token: TokenMarketParams,
analyticsParams: MarketsPortfolioComponent.AnalyticsParams?,
analyticsParams: AnalyticsParams?,
): AddToPortfolioManager
}
}

View file

@ -1,4 +1,4 @@
package com.tangem.features.feed.components.market.details.portfolio.add.api
package com.tangem.features.feed.components.market.details.portfolio.add
import com.tangem.domain.markets.TokenMarketInfo
import com.tangem.domain.models.account.AccountId
@ -9,7 +9,7 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import kotlinx.serialization.Serializable
internal data class AvailableToAddData(
data class AvailableToAddData(
val availableToAddWallets: Map<UserWalletId, AvailableToAddWallet>,
) {
val isAvailableToAdd: Boolean
@ -18,7 +18,7 @@ internal data class AvailableToAddData(
get() = availableToAddWallets.size == 1 && availableToAddWallets.values.first().accounts.size == 1
}
internal data class AvailableToAddWallet(
data class AvailableToAddWallet(
val userWallet: UserWallet,
val accounts: List<AccountStatus>,
val availableNetworks: Set<TokenMarketInfo.Network>,
@ -26,7 +26,7 @@ internal data class AvailableToAddWallet(
)
@Serializable
internal data class AvailableToAddAccount(
data class AvailableToAddAccount(
val account: AccountStatus,
val availableNetworks: Set<TokenMarketInfo.Network>,
val addedNetworks: Set<Network>,
@ -44,14 +44,14 @@ internal data class AvailableToAddAccount(
}
@Serializable
internal data class SelectedPortfolio(
data class SelectedPortfolio(
val userWallet: UserWallet,
val account: AvailableToAddAccount,
val isAccountMode: Boolean,
val isAvailableMorePortfolio: Boolean,
)
internal data class SelectedNetwork(
data class SelectedNetwork(
val selectedNetwork: TokenMarketInfo.Network,
val cryptoCurrency: CryptoCurrency,
val isAvailableMoreNetwork: Boolean,

View file

@ -9,8 +9,8 @@ import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.features.feed.components.market.details.portfolio.add.api.SelectedNetwork
import com.tangem.features.feed.components.market.details.portfolio.add.api.SelectedPortfolio
import com.tangem.features.feed.components.market.details.portfolio.add.SelectedNetwork
import com.tangem.features.feed.components.market.details.portfolio.add.SelectedPortfolio
import com.tangem.features.feed.components.market.details.portfolio.add.impl.model.AddTokenModel
import com.tangem.features.feed.components.market.details.portfolio.impl.analytics.PortfolioAnalyticsEvent
import dagger.assisted.Assisted

View file

@ -9,7 +9,7 @@ import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.markets.TokenMarketInfo
import com.tangem.features.feed.components.market.details.portfolio.add.api.SelectedPortfolio
import com.tangem.features.feed.components.market.details.portfolio.add.SelectedPortfolio
import com.tangem.features.feed.components.market.details.portfolio.add.impl.model.ChooseNetworkModel
import com.tangem.features.feed.components.market.details.portfolio.add.impl.ui.ChooseNetworkContent
import dagger.assisted.Assisted

View file

@ -32,7 +32,7 @@ import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.account.PortfolioSelectorComponent
import com.tangem.features.feed.components.market.details.portfolio.add.api.AddToPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.add.impl.model.AddToPortfolioModel
import com.tangem.features.feed.components.market.details.portfolio.add.impl.model.AddToPortfolioRoutes
import com.tangem.features.feed.impl.R

View file

@ -12,9 +12,9 @@ import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.features.account.PortfolioFetcher
import com.tangem.features.feed.components.market.details.portfolio.add.api.AvailableToAddAccount
import com.tangem.features.feed.components.market.details.portfolio.add.api.AvailableToAddData
import com.tangem.features.feed.components.market.details.portfolio.add.api.AvailableToAddWallet
import com.tangem.features.feed.components.market.details.portfolio.add.AvailableToAddAccount
import com.tangem.features.feed.components.market.details.portfolio.add.AvailableToAddData
import com.tangem.features.feed.components.market.details.portfolio.add.AvailableToAddWallet
import javax.inject.Inject
internal class AvailableToAddDataConverter @Inject constructor(

View file

@ -1,7 +1,7 @@
package com.tangem.features.feed.components.market.details.portfolio.add.impl.di
import com.tangem.features.feed.components.market.details.portfolio.add.api.AddToPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.add.api.AddToPortfolioManager
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioManager
import com.tangem.features.feed.components.market.details.portfolio.add.impl.DefaultAddToPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.add.impl.ui.DefaultAddToPortfolioManager
import dagger.Binds

View file

@ -19,7 +19,12 @@ import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.features.account.PortfolioSelectorController
import com.tangem.features.feed.components.market.details.portfolio.add.api.*
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioManager
import com.tangem.features.feed.components.market.details.portfolio.add.AvailableToAddAccount
import com.tangem.features.feed.components.market.details.portfolio.add.AvailableToAddData
import com.tangem.features.feed.components.market.details.portfolio.add.SelectedNetwork
import com.tangem.features.feed.components.market.details.portfolio.add.SelectedPortfolio
import com.tangem.features.feed.components.market.details.portfolio.add.impl.AddTokenComponent
import com.tangem.features.feed.components.market.details.portfolio.add.impl.ChooseNetworkComponent
import com.tangem.features.feed.components.market.details.portfolio.add.impl.TokenActionsComponent
@ -91,6 +96,11 @@ internal class AddToPortfolioModel @Inject constructor(
channel.close()
}
fun finishSuccessFlow(addedToken: CryptoCurrencyStatus) {
params.callback.onSuccess(addedToken.currency)
channel.close()
}
val featureDataFlow: StateFlow<AvailableToAddData> = featureData
.filterIsInstance<AddToPortfolioManager.State.AvailableToAdd>()
.map { it.availableToAddData }
@ -183,13 +193,17 @@ internal class AddToPortfolioModel @Inject constructor(
messageSender.send(ToastMessage(message = resourceReference(R.string.markets_token_added)))
setupTokenActionsFlow(selectedPortfolio, addedToken)
.onEach { cryptoCurrencyData ->
tokenActionsData.emit(cryptoCurrencyData)
navigation.replaceAll(AddToPortfolioRoutes.TokenActions)
}
.onEmpty { finishFlow() }
.launchIn(this)
if (params.shouldSkipTokenActionsScreen) {
finishSuccessFlow(addedToken)
} else {
setupTokenActionsFlow(selectedPortfolio, addedToken)
.onEach { cryptoCurrencyData ->
tokenActionsData.emit(cryptoCurrencyData)
navigation.replaceAll(AddToPortfolioRoutes.TokenActions)
}
.onEmpty { finishFlow() }
.launchIn(this)
}
callbackDelegate.onLaterClick.receiveAsFlow().first()
finishFlow()
@ -316,8 +330,8 @@ internal class AddToPortfolioModel @Inject constructor(
network: TokenMarketInfo.Network,
account: AvailableToAddAccount,
): CryptoCurrency? {
val accountIndex = when (account.account) {
is AccountStatus.CryptoPortfolio -> account.account.account.derivationIndex
val accountIndex = when (val accountStatus = account.account) {
is AccountStatus.CryptoPortfolio -> accountStatus.account.derivationIndex
}
return getTokenMarketCryptoCurrency(
userWalletId = userWallet.walletId,

View file

@ -2,7 +2,7 @@ package com.tangem.features.feed.components.market.details.portfolio.add.impl.mo
import androidx.compose.runtime.Immutable
import com.tangem.core.decompose.navigation.Route
import com.tangem.features.feed.components.market.details.portfolio.add.api.SelectedPortfolio
import com.tangem.features.feed.components.market.details.portfolio.add.SelectedPortfolio
import kotlinx.serialization.Serializable
@Serializable

View file

@ -13,8 +13,8 @@ import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
import com.tangem.domain.models.account.Account
import com.tangem.domain.wallets.usecase.ColdWalletAndHasMissedDerivationsUseCase
import com.tangem.features.feed.components.market.details.portfolio.add.api.SelectedNetwork
import com.tangem.features.feed.components.market.details.portfolio.add.api.SelectedPortfolio
import com.tangem.features.feed.components.market.details.portfolio.add.SelectedNetwork
import com.tangem.features.feed.components.market.details.portfolio.add.SelectedPortfolio
import com.tangem.features.feed.components.market.details.portfolio.add.impl.AddTokenComponent
import com.tangem.features.feed.components.market.details.portfolio.add.impl.model.AddTokenUiBuilder.Companion.toggleProgress
import com.tangem.features.feed.impl.R

View file

@ -13,8 +13,8 @@ import com.tangem.core.ui.extensions.iconResId
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.domain.models.account.AccountStatus
import com.tangem.features.feed.components.market.details.portfolio.add.api.SelectedNetwork
import com.tangem.features.feed.components.market.details.portfolio.add.api.SelectedPortfolio
import com.tangem.features.feed.components.market.details.portfolio.add.SelectedNetwork
import com.tangem.features.feed.components.market.details.portfolio.add.SelectedPortfolio
import com.tangem.features.feed.components.market.details.portfolio.add.impl.AddTokenComponent
import com.tangem.features.feed.impl.R
import javax.inject.Inject

View file

@ -3,9 +3,8 @@ package com.tangem.features.feed.components.market.details.portfolio.add.impl.ui
import com.tangem.domain.markets.TokenMarketInfo
import com.tangem.domain.markets.TokenMarketParams
import com.tangem.features.account.PortfolioFetcher
import com.tangem.features.feed.components.market.details.portfolio.add.api.AddToPortfolioManager
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioManager
import com.tangem.features.feed.components.market.details.portfolio.add.impl.converter.AvailableToAddDataConverter
import com.tangem.features.feed.components.market.details.portfolio.api.MarketsPortfolioComponent
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -17,7 +16,7 @@ import kotlinx.coroutines.flow.*
internal class DefaultAddToPortfolioManager @AssistedInject constructor(
private val availableToAddDataConverter: AvailableToAddDataConverter,
@Assisted override val token: TokenMarketParams,
@Assisted override val analyticsParams: MarketsPortfolioComponent.AnalyticsParams?,
@Assisted override val analyticsParams: AddToPortfolioManager.AnalyticsParams?,
@Assisted val scope: CoroutineScope,
dispatchers: CoroutineDispatcherProvider,
portfolioFetcherFactory: PortfolioFetcher.Factory,
@ -66,7 +65,7 @@ internal class DefaultAddToPortfolioManager @AssistedInject constructor(
override fun create(
scope: CoroutineScope,
token: TokenMarketParams,
analyticsParams: MarketsPortfolioComponent.AnalyticsParams?,
analyticsParams: AddToPortfolioManager.AnalyticsParams?,
): DefaultAddToPortfolioManager
}
}

View file

@ -14,7 +14,7 @@ import com.tangem.core.decompose.context.childByContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.domain.markets.TokenMarketInfo
import com.tangem.features.feed.components.market.details.portfolio.add.api.AddToPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.api.MarketsPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.impl.model.MarketsPortfolioModel
import com.tangem.features.feed.components.market.details.portfolio.impl.model.MarketsPortfolioRoute

View file

@ -31,7 +31,7 @@ import com.tangem.domain.models.wallet.isMultiCurrency
import com.tangem.domain.transaction.usecase.ReceiveAddressesFactory
import com.tangem.domain.wallets.usecase.ColdWalletAndHasMissedDerivationsUseCase
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
import com.tangem.features.feed.components.market.details.portfolio.add.api.AddToPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.api.MarketsPortfolioComponent
import com.tangem.features.feed.components.market.details.portfolio.impl.analytics.PortfolioAnalyticsEvent
import com.tangem.features.feed.components.market.details.portfolio.impl.loader.PortfolioData
@ -50,7 +50,7 @@ import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
import com.tangem.features.feed.components.market.details.portfolio.add.api.AddToPortfolioManager as NewAddToPortfolioManager
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioManager as NewAddToPortfolioManager
@Suppress("LongParameterList", "LargeClass")
@Stable
@ -96,6 +96,7 @@ internal class MarketsPortfolioModel @Inject constructor(
val bottomSheetNavigation: SlotNavigation<MarketsPortfolioRoute> = SlotNavigation()
val addToPortfolioCallback = object : AddToPortfolioComponent.Callback {
override fun onDismiss() = bottomSheetNavigation.dismiss()
override fun onSuccess(addedToken: CryptoCurrency) = bottomSheetNavigation.dismiss()
}
private val currentAppCurrency = getSelectedAppCurrencyUseCase()
@ -184,7 +185,7 @@ internal class MarketsPortfolioModel @Inject constructor(
.create(
modelScope,
params.token,
params.analyticsParams,
params.analyticsParams?.source?.let { NewAddToPortfolioManager.AnalyticsParams(it) },
)
newMarketsPortfolioDelegate = newMarketsPortfolioDelegateFactory.create(
scope = modelScope,