Updated on 2026-08-14
This commit is contained in:
parent
27347a13e8
commit
6d3eb6de79
11 changed files with 332 additions and 67 deletions
|
|
@ -74,6 +74,7 @@ data class TangemDimens internal constructor(
|
|||
val size56: Dp = 56.dp,
|
||||
val size60: Dp = 60.dp,
|
||||
val size62: Dp = 62.dp,
|
||||
val size63: Dp = 63.dp,
|
||||
val size64: Dp = 64.dp,
|
||||
val size68: Dp = 68.dp,
|
||||
val size70: Dp = 70.dp,
|
||||
|
|
|
|||
|
|
@ -17,11 +17,16 @@ dependencies {
|
|||
implementation(projects.core.navigation)
|
||||
|
||||
/* Domain */
|
||||
implementation(projects.domain.markets)
|
||||
implementation(projects.domain.appCurrency)
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.balanceHiding)
|
||||
implementation(projects.domain.balanceHiding.models)
|
||||
implementation(projects.domain.markets)
|
||||
implementation(projects.domain.staking.models)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.wallets)
|
||||
implementation(projects.domain.wallets.models)
|
||||
|
||||
/* Compose */
|
||||
implementation(deps.compose.coil)
|
||||
|
|
@ -52,4 +57,7 @@ dependencies {
|
|||
implementation(projects.common.ui)
|
||||
implementation(projects.common.uiCharts)
|
||||
implementation(projects.common.routing)
|
||||
|
||||
/* Libs */
|
||||
implementation(projects.libs.crypto)
|
||||
}
|
||||
|
|
@ -2,7 +2,9 @@ package com.tangem.features.markets.details.impl.model
|
|||
|
||||
import androidx.compose.runtime.Stable
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.ui.charts.state.*
|
||||
import com.tangem.common.ui.charts.state.MarketChartData
|
||||
import com.tangem.common.ui.charts.state.MarketChartDataProducer
|
||||
import com.tangem.common.ui.charts.state.MarketChartLook
|
||||
import com.tangem.core.decompose.di.ComponentScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
|
|
@ -22,13 +24,11 @@ import com.tangem.features.markets.details.MarketsTokenDetailsComponent
|
|||
import com.tangem.features.markets.details.impl.model.converters.DescriptionConverter
|
||||
import com.tangem.features.markets.details.impl.model.converters.TokenMarketInfoConverter
|
||||
import com.tangem.features.markets.details.impl.model.formatter.*
|
||||
import com.tangem.features.markets.details.impl.model.formatter.formatAsPrice
|
||||
import com.tangem.features.markets.details.impl.model.formatter.getChangePercentBetween
|
||||
import com.tangem.features.markets.details.impl.model.formatter.getPercentByInterval
|
||||
import com.tangem.features.markets.details.impl.model.state.TokenNetworksState
|
||||
import com.tangem.features.markets.details.impl.ui.state.InfoBottomSheetContent
|
||||
import com.tangem.features.markets.details.impl.ui.state.MarketsTokenDetailsUM
|
||||
import com.tangem.features.markets.impl.R
|
||||
import com.tangem.lib.crypto.BlockchainUtils
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
|
|
@ -296,7 +296,9 @@ internal class MarketsTokenDetailsModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
val networks = result.networks
|
||||
val networks = result.networks?.filter {
|
||||
BlockchainUtils.isSupportedNetworkId(it.networkId)
|
||||
}
|
||||
|
||||
networksState.value = if (networks.isNullOrEmpty()) {
|
||||
TokenNetworksState.NoNetworksAvailable
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@ package com.tangem.features.markets.portfolio.impl
|
|||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.features.markets.portfolio.api.MarketsPortfolioComponent
|
||||
import com.tangem.features.markets.portfolio.impl.model.MarketsPortfolioModel
|
||||
import com.tangem.features.markets.portfolio.impl.ui.MyPortfolio
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -27,10 +28,9 @@ internal class DefaultMarketsPortfolioComponent @AssistedInject constructor(
|
|||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
MyPortfolio(
|
||||
modifier = modifier,
|
||||
state = MyPortfolioUM.Loading,
|
||||
)
|
||||
val state by model.state.collectAsStateWithLifecycle()
|
||||
|
||||
MyPortfolio(modifier = modifier, state = state)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
|
|
|
|||
|
|
@ -1,30 +1,92 @@
|
|||
package com.tangem.features.markets.portfolio.impl.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.core.decompose.di.ComponentScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.domain.tokens.GetAllWalletsCryptoCurrencyStatusesUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.markets.portfolio.api.MarketsPortfolioComponent
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.*
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@Stable
|
||||
@ComponentScoped
|
||||
internal class MarketsPortfolioModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
getAllWalletsCryptoCurrencyStatusesUseCase: GetAllWalletsCryptoCurrencyStatusesUseCase,
|
||||
getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
) : Model() {
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
val state: StateFlow<MyPortfolioUM> get() = _state
|
||||
private val _state: MutableStateFlow<MyPortfolioUM> = MutableStateFlow(value = MyPortfolioUM.Loading)
|
||||
|
||||
private val params = paramsContainer.require<MarketsPortfolioComponent.Params>()
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private val availableNetworks = MutableStateFlow<List<TokenMarketInfo.Network>?>(value = null)
|
||||
|
||||
private val factory = MyPortfolioUMMFactory(::onAddClick, ::onTokenItemClick)
|
||||
|
||||
init {
|
||||
combine(
|
||||
flow = getAllWalletsCryptoCurrencyStatusesUseCase(params.tokenId),
|
||||
flow2 = availableNetworks,
|
||||
flow3 = getSelectedAppCurrencyUseCase(),
|
||||
flow4 = getBalanceHidingSettingsUseCase(),
|
||||
) { walletsWithCurrencyStatuses, networks, maybeAppCurrency, isBalanceHidden ->
|
||||
val appCurrency = maybeAppCurrency.getOrElse { e ->
|
||||
Timber.e("Failed to load app currency: $e")
|
||||
AppCurrency.Default
|
||||
}
|
||||
|
||||
factory.create(
|
||||
walletsWithCurrencyStatuses = walletsWithCurrencyStatuses,
|
||||
availableNetworks = networks,
|
||||
appCurrency = appCurrency,
|
||||
isBalanceHidden = isBalanceHidden.isBalanceHidden,
|
||||
)
|
||||
}
|
||||
.onEach { _state.value = it }
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
fun setTokenNetworks(networks: List<TokenMarketInfo.Network>) {
|
||||
// TODO [REDACTED_TASK_KEY]
|
||||
availableNetworks.value = networks
|
||||
}
|
||||
|
||||
fun setNoNetworksAvailable() {
|
||||
// TODO [REDACTED_TASK_KEY]
|
||||
availableNetworks.value = emptyList()
|
||||
}
|
||||
|
||||
private fun onAddClick() {
|
||||
// TODO [REDACTED_JIRA]
|
||||
}
|
||||
|
||||
private fun onTokenItemClick(token: CryptoCurrencyStatus) {
|
||||
_state.update {
|
||||
(_state.value as? MyPortfolioUM.Tokens)?.let { state ->
|
||||
state.copy(
|
||||
tokens = state.tokens.map { tokenUM ->
|
||||
if (tokenUM.tokenItemState.id == token.currency.id.value) {
|
||||
tokenUM.copy(isQuickActionsShown = !tokenUM.isQuickActionsShown)
|
||||
} else {
|
||||
tokenUM
|
||||
}
|
||||
}
|
||||
.toImmutableList(),
|
||||
)
|
||||
} ?: it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package com.tangem.features.markets.portfolio.impl.model
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM
|
||||
|
||||
/**
|
||||
* Factory for creating [MyPortfolioUM]
|
||||
*
|
||||
* @property onAddClick callback when user wants to add new token
|
||||
* @property onTokenItemClick callback when user wants to see actions with token
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class MyPortfolioUMMFactory(
|
||||
private val onAddClick: () -> Unit,
|
||||
private val onTokenItemClick: (CryptoCurrencyStatus) -> Unit,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Create [MyPortfolioUM] from data set
|
||||
*
|
||||
* @param walletsWithCurrencyStatuses wallets with currency statuses
|
||||
* @param availableNetworks available networks
|
||||
* @param appCurrency app currency
|
||||
* @param isBalanceHidden flag that indicates if balance should be hidden
|
||||
*/
|
||||
fun create(
|
||||
walletsWithCurrencyStatuses: Map<UserWallet, List<Either<CurrencyStatusError, CryptoCurrencyStatus>>>,
|
||||
availableNetworks: List<TokenMarketInfo.Network>?,
|
||||
appCurrency: AppCurrency,
|
||||
isBalanceHidden: Boolean,
|
||||
): MyPortfolioUM {
|
||||
if (availableNetworks == null) return MyPortfolioUM.Loading
|
||||
|
||||
if (availableNetworks.isEmpty()) return MyPortfolioUM.Unavailable
|
||||
|
||||
val availableWalletsWithStatuses = walletsWithCurrencyStatuses
|
||||
.filterAvailable(networks = availableNetworks)
|
||||
.flatMapStatuses()
|
||||
|
||||
if (availableWalletsWithStatuses.isEmpty()) {
|
||||
return MyPortfolioUM.AddFirstToken(onAddClick = onAddClick)
|
||||
}
|
||||
|
||||
return TokensPortfolioUMConverter(
|
||||
appCurrency = appCurrency,
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
availableNetworks = availableNetworks,
|
||||
onAddClick = onAddClick,
|
||||
onTokenItemClick = onTokenItemClick,
|
||||
)
|
||||
.convert(availableWalletsWithStatuses)
|
||||
}
|
||||
|
||||
private fun Map<UserWallet, List<Either<CurrencyStatusError, CryptoCurrencyStatus>>>.filterAvailable(
|
||||
networks: List<TokenMarketInfo.Network>,
|
||||
): Map<UserWallet, List<CryptoCurrencyStatus>> {
|
||||
val networkIds = networks.map { it.networkId }
|
||||
|
||||
return mapValues { entry ->
|
||||
entry.value.mapNotNull { maybeStatus ->
|
||||
maybeStatus.getOrNull()
|
||||
?.takeIf { networkIds.contains(it.currency.network.backendId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Map<UserWallet, List<CryptoCurrencyStatus>>.flatMapStatuses(): Map<UserWallet, CryptoCurrencyStatus> {
|
||||
return this
|
||||
.flatMap { entry ->
|
||||
entry.value.map { entry.key to it }
|
||||
}
|
||||
.toMap()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.tangem.features.markets.portfolio.impl.model
|
||||
|
||||
import com.tangem.common.ui.tokens.TokenItemStateConverter
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.PortfolioTokenUM
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
/**
|
||||
* Converter from [UserWallet] and [CryptoCurrencyStatus] to [PortfolioTokenUM]
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class PortfolioTokenUMConverter(
|
||||
private val appCurrency: AppCurrency,
|
||||
private val isBalanceHidden: Boolean,
|
||||
private val onTokenItemClick: (CryptoCurrencyStatus) -> Unit,
|
||||
) : Converter<Map.Entry<UserWallet, CryptoCurrencyStatus>, PortfolioTokenUM> {
|
||||
|
||||
override fun convert(value: Map.Entry<UserWallet, CryptoCurrencyStatus>): PortfolioTokenUM {
|
||||
val (userWallet, cryptoCurrencyStatus) = value
|
||||
|
||||
val tokenItemStateConverter = TokenItemStateConverter(
|
||||
appCurrency = appCurrency,
|
||||
titleStateProvider = { TokenItemState.TitleState.Content(text = userWallet.name) },
|
||||
subtitleStateProvider = {
|
||||
TokenItemState.SubtitleState.TextContent(value = cryptoCurrencyStatus.currency.name)
|
||||
},
|
||||
onItemClick = onTokenItemClick,
|
||||
onItemLongClick = null,
|
||||
)
|
||||
|
||||
return PortfolioTokenUM(
|
||||
tokenItemState = tokenItemStateConverter.convert(value = cryptoCurrencyStatus),
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
isQuickActionsShown = false,
|
||||
onQuickActionClick = {
|
||||
// TODO: [REDACTED_JIRA]
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package com.tangem.features.markets.portfolio.impl.model
|
||||
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.markets.TokenMarketInfo
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM.Tokens.AddButtonState
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
/**
|
||||
* Converter from [Map] of [UserWallet] and [CryptoCurrencyStatus] to [MyPortfolioUM.Tokens]
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class TokensPortfolioUMConverter(
|
||||
private val appCurrency: AppCurrency,
|
||||
private val isBalanceHidden: Boolean,
|
||||
private val availableNetworks: List<TokenMarketInfo.Network>,
|
||||
private val onAddClick: () -> Unit,
|
||||
private val onTokenItemClick: (CryptoCurrencyStatus) -> Unit,
|
||||
) : Converter<Map<UserWallet, CryptoCurrencyStatus>, MyPortfolioUM.Tokens> {
|
||||
|
||||
override fun convert(value: Map<UserWallet, CryptoCurrencyStatus>): MyPortfolioUM.Tokens {
|
||||
return MyPortfolioUM.Tokens(
|
||||
tokens = PortfolioTokenUMConverter(appCurrency, isBalanceHidden, onTokenItemClick)
|
||||
.convertList(value.entries)
|
||||
.toImmutableList(),
|
||||
buttonState = getAddButtonState(
|
||||
availableWalletsWithStatuses = value,
|
||||
availableNetworks = availableNetworks,
|
||||
),
|
||||
onAddClick = onAddClick,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getAddButtonState(
|
||||
availableWalletsWithStatuses: Map<UserWallet, CryptoCurrencyStatus>,
|
||||
availableNetworks: List<TokenMarketInfo.Network>,
|
||||
): AddButtonState {
|
||||
val networkIds = availableNetworks.map { it.networkId }
|
||||
|
||||
val allNetworksAdded = availableWalletsWithStatuses
|
||||
// User can add currencies only in multi-currency wallets
|
||||
.filterKeys(UserWallet::isMultiCurrency)
|
||||
.entries
|
||||
.groupBy(
|
||||
keySelector = { it.key },
|
||||
valueTransform = { it.value.currency.network.backendId },
|
||||
)
|
||||
.mapValues { it.value.toSet() }
|
||||
// Each wallets contains all available networks?
|
||||
.all { it.value.containsAll(networkIds) }
|
||||
|
||||
return if (allNetworksAdded) AddButtonState.Unavailable else AddButtonState.Available
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,6 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.components.SmallButtonShimmer
|
||||
|
|
@ -26,51 +25,68 @@ import com.tangem.core.ui.res.TangemThemePreview
|
|||
import com.tangem.features.markets.impl.R
|
||||
import com.tangem.features.markets.portfolio.impl.ui.preview.PreviewMyPortfolioUMProvider
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM
|
||||
import com.tangem.features.markets.portfolio.impl.ui.state.MyPortfolioUM.Tokens.AddButtonState
|
||||
|
||||
@Composable
|
||||
internal fun MyPortfolio(state: MyPortfolioUM, modifier: Modifier = Modifier) {
|
||||
InformationBlock(
|
||||
modifier = modifier,
|
||||
contentHorizontalPadding = 0.dp,
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(R.string.markets_common_my_portfolio),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
},
|
||||
contentHorizontalPadding = TangemTheme.dimens.spacing0,
|
||||
title = { Title() },
|
||||
action = {
|
||||
if (state !is MyPortfolioUM.Tokens) return@InformationBlock
|
||||
|
||||
when (state.buttonState) {
|
||||
MyPortfolioUM.Tokens.AddButtonState.Loading -> {
|
||||
SmallButtonShimmer(
|
||||
modifier = Modifier.size(width = 63.dp, height = TangemTheme.dimens.size18),
|
||||
shape = RoundedCornerShape(TangemTheme.dimens.radius3),
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
SecondarySmallButton(
|
||||
config = SmallButtonConfig(
|
||||
text = resourceReference(R.string.markets_add_token),
|
||||
icon = TangemButtonIconPosition.Start(R.drawable.ic_plus_24),
|
||||
onClick = state.onAddClick,
|
||||
enabled = state.buttonState == MyPortfolioUM.Tokens.AddButtonState.Available,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
AddButton(state = state.buttonState, onClick = state.onAddClick)
|
||||
},
|
||||
) {
|
||||
val contentModifier = Modifier.padding(
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
bottom = TangemTheme.dimens.spacing12,
|
||||
)
|
||||
|
||||
when (state) {
|
||||
is MyPortfolioUM.Tokens -> TokenList(state = state)
|
||||
is MyPortfolioUM.AddFirstToken -> AddFirstTokenContent(state = state)
|
||||
MyPortfolioUM.Loading -> LoadingPlaceholder()
|
||||
MyPortfolioUM.Unavailable -> UnavailableContent()
|
||||
is MyPortfolioUM.AddFirstToken -> AddFirstTokenContent(state = state, modifier = contentModifier)
|
||||
MyPortfolioUM.Loading -> LoadingPlaceholder(modifier = contentModifier)
|
||||
MyPortfolioUM.Unavailable -> UnavailableContent(modifier = contentModifier)
|
||||
}
|
||||
}
|
||||
|
||||
AddToPortfolioBottomSheet(state.addToPortfolioBS)
|
||||
AddToPortfolioBottomSheet(config = state.addToPortfolioBS)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Title() {
|
||||
Text(
|
||||
text = stringResource(R.string.markets_common_my_portfolio),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AddButton(state: AddButtonState, onClick: () -> Unit) {
|
||||
when (state) {
|
||||
AddButtonState.Loading -> {
|
||||
SmallButtonShimmer(
|
||||
modifier = Modifier.size(width = TangemTheme.dimens.size63, height = TangemTheme.dimens.size18),
|
||||
shape = RoundedCornerShape(TangemTheme.dimens.radius3),
|
||||
)
|
||||
}
|
||||
AddButtonState.Available,
|
||||
AddButtonState.Unavailable,
|
||||
-> {
|
||||
SecondarySmallButton(
|
||||
config = SmallButtonConfig(
|
||||
text = resourceReference(R.string.markets_add_token),
|
||||
icon = TangemButtonIconPosition.Start(R.drawable.ic_plus_24),
|
||||
onClick = onClick,
|
||||
enabled = state == AddButtonState.Available,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -90,12 +106,7 @@ private fun TokenList(state: MyPortfolioUM.Tokens, modifier: Modifier = Modifier
|
|||
@Composable
|
||||
private fun UnavailableContent(modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
modifier = modifier
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
bottom = TangemTheme.dimens.spacing12,
|
||||
),
|
||||
modifier = modifier,
|
||||
text = stringResource(R.string.markets_add_to_my_portfolio_unavailable_description),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
|
|
@ -105,12 +116,7 @@ private fun UnavailableContent(modifier: Modifier = Modifier) {
|
|||
@Composable
|
||||
private fun AddFirstTokenContent(state: MyPortfolioUM.AddFirstToken, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
bottom = TangemTheme.dimens.spacing12,
|
||||
),
|
||||
modifier = modifier,
|
||||
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
Text(
|
||||
|
|
@ -118,6 +124,7 @@ private fun AddFirstTokenContent(state: MyPortfolioUM.AddFirstToken, modifier: M
|
|||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
|
||||
PrimaryButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = stringResource(R.string.markets_add_to_portfolio_button),
|
||||
|
|
@ -128,19 +135,13 @@ private fun AddFirstTokenContent(state: MyPortfolioUM.AddFirstToken, modifier: M
|
|||
|
||||
@Composable
|
||||
private fun LoadingPlaceholder(modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.padding(
|
||||
start = TangemTheme.dimens.spacing12,
|
||||
end = TangemTheme.dimens.spacing12,
|
||||
bottom = TangemTheme.dimens.spacing12,
|
||||
),
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
TextShimmer(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
style = TangemTheme.typography.body2,
|
||||
textSizeHeight = true,
|
||||
)
|
||||
|
||||
TextShimmer(
|
||||
modifier = Modifier.fillMaxWidth(fraction = 0.7f),
|
||||
style = TangemTheme.typography.body2,
|
||||
|
|
|
|||
|
|
@ -20,4 +20,7 @@ dependencies {
|
|||
|
||||
/** Core */
|
||||
implementation(projects.core.utils)
|
||||
|
||||
/** Libs */
|
||||
implementation(projects.libs.blockchainSdk)
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package com.tangem.lib.crypto
|
|||
|
||||
import com.tangem.blockchain.blockchains.xrp.XrpAddressService
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.blockchainsdk.utils.isSupportedInApp
|
||||
import com.tangem.lib.crypto.converter.XrpTaggedAddressConverter
|
||||
import com.tangem.lib.crypto.models.XrpTaggedAddress
|
||||
|
||||
|
|
@ -55,4 +57,8 @@ object BlockchainUtils {
|
|||
val blockchain = Blockchain.fromId(networkId)
|
||||
return blockchain == Blockchain.Binance || blockchain == Blockchain.BinanceTestnet
|
||||
}
|
||||
|
||||
fun isSupportedNetworkId(networkId: String): Boolean {
|
||||
return Blockchain.fromNetworkId(networkId)?.isSupportedInApp() ?: false
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue