diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt
index 8ec7199796..47d32be700 100644
--- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt
+++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt
@@ -7,6 +7,7 @@ import com.tangem.domain.tokens.*
import com.tangem.domain.tokens.repository.*
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.feature.swap.domain.api.SwapRepository
+import com.tangem.features.markets.MarketsFeatureToggles
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
@@ -230,6 +231,7 @@ internal object TokensDomainModule {
networksRepository: NetworksRepository,
stakingRepository: StakingRepository,
stakingFeatureToggles: StakingFeatureToggles,
+ marketsFeatureToggles: MarketsFeatureToggles,
dispatchers: CoroutineDispatcherProvider,
): GetCryptoCurrencyActionsUseCase {
return GetCryptoCurrencyActionsUseCase(
@@ -241,6 +243,7 @@ internal object TokensDomainModule {
networksRepository = networksRepository,
stakingRepository = stakingRepository,
stakingFeatureToggles = stakingFeatureToggles,
+ marketsFeatureToggles = marketsFeatureToggles,
dispatchers = dispatchers,
)
}
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 c2b8cf249c..f33cf4b1af 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
@@ -193,6 +193,7 @@ internal class ChildFactory @Inject constructor(
params = MarketsTokenDetailsComponent.Params(
token = route.token,
appCurrency = route.appCurrency,
+ showPortfolio = route.showPortfolio,
),
componentFactory = marketsTokenDetailsComponentFactory,
)
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 d8e383a18e..2362e15686 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
@@ -271,5 +271,6 @@ sealed class AppRoute(val path: String) : Route {
data class MarketsTokenDetails(
val token: TokenMarketParams,
val appCurrency: AppCurrency,
- ) : AppRoute(path = "/markets_token_details/${token.id}")
+ val showPortfolio: Boolean,
+ ) : AppRoute(path = "/markets_token_details/${token.id}/$showPortfolio")
}
\ No newline at end of file
diff --git a/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt
index cd14d8f8c8..992380b05e 100644
--- a/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt
+++ b/common/ui-charts/src/main/kotlin/com/tangem/common/ui/charts/MarketChart.kt
@@ -125,6 +125,8 @@ fun MarketChart(
// Sometimes the chart is not drawn correctly (ex. in LazyLayout), so we need to force the redraw
.drawBehind {
state.markerFraction
+ state.chartColor
+ state.markerHighlightRightSide
},
chart = chart,
modelProducer = state.modelProducer,
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Shimmers.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Shimmers.kt
index c0f97514dc..e613aa253a 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/Shimmers.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/Shimmers.kt
@@ -22,10 +22,13 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
import com.tangem.core.ui.R
import com.tangem.core.ui.components.buttons.PrimarySmallButton
import com.tangem.core.ui.components.buttons.SmallButtonConfig
+import com.tangem.core.ui.components.buttons.chip.Chip
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
+import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.res.*
import com.valentinilk.shimmer.*
@@ -123,6 +126,22 @@ fun SmallButtonShimmer(
)
}
+/**
+ * Shimmer for Chip
+ * Height and min width will be set automatically
+ */
+@Composable
+fun ChipShimmer(modifier: Modifier = Modifier) {
+ Chip(
+ modifier = modifier
+ .clip(RoundedCornerShape(size = 100.dp))
+ .shimmer(LocalTangemShimmer.current),
+ text = TextReference.EMPTY,
+ iconResId = R.drawable.ic_plus_24,
+ onClick = {},
+ )
+}
+
internal val TangemShimmer: Shimmer
@Composable
get() = rememberShimmer(
@@ -195,6 +214,7 @@ private fun ShimmersPreview() {
)
SmallButtonShimmer(withIcon = true)
SmallButtonShimmer(withIcon = false)
+ ChipShimmer()
}
}
}
diff --git a/core/ui/src/main/res/drawable/ic_analytics_24.xml b/core/ui/src/main/res/drawable/ic_analytics_24.xml
new file mode 100644
index 0000000000..743431578d
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_analytics_24.xml
@@ -0,0 +1,18 @@
+
+
+
+
diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultQuotesRepository.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultQuotesRepository.kt
index cc25c467e0..13e1c3e368 100644
--- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultQuotesRepository.kt
+++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/repository/DefaultQuotesRepository.kt
@@ -143,7 +143,6 @@ internal class DefaultQuotesRepository(
block = { acc.add(rawCurrencyId) },
)
}
-
acc
}
}
diff --git a/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenMarketParams.kt b/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenMarketParams.kt
index 643846c466..e14b1f417b 100644
--- a/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenMarketParams.kt
+++ b/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenMarketParams.kt
@@ -15,7 +15,7 @@ data class TokenMarketParams(
@Serializable
data class Quotes(
val currentPrice: SerializedBigDecimal,
- val h24Percent: SerializedBigDecimal,
+ val h24Percent: SerializedBigDecimal?,
val weekPercent: SerializedBigDecimal?,
val monthPercent: SerializedBigDecimal?,
)
diff --git a/domain/tokens/build.gradle.kts b/domain/tokens/build.gradle.kts
index bbe01868f9..a1c639300b 100644
--- a/domain/tokens/build.gradle.kts
+++ b/domain/tokens/build.gradle.kts
@@ -28,6 +28,7 @@ dependencies {
/** Project - Api */
implementation(projects.features.send.api)
implementation(projects.features.staking.api)
+ implementation(projects.features.markets.api)
/** Project - Other */
implementation(projects.core.utils)
diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt
index a1e112bb15..c1ac067bff 100644
--- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt
+++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyActionsUseCase.kt
@@ -12,6 +12,7 @@ import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWallet
+import com.tangem.features.markets.MarketsFeatureToggles
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.isNullOrZero
@@ -33,6 +34,7 @@ class GetCryptoCurrencyActionsUseCase(
private val networksRepository: NetworksRepository,
private val stakingRepository: StakingRepository,
private val stakingFeatureToggles: StakingFeatureToggles,
+ private val marketsFeatureToggles: MarketsFeatureToggles,
private val dispatchers: CoroutineDispatcherProvider,
) {
@@ -112,6 +114,12 @@ class GetCryptoCurrencyActionsUseCase(
val activeList = mutableListOf()
val disabledList = mutableListOf()
+ // markets
+ // not a custom token
+ if (marketsFeatureToggles.isFeatureEnabled && cryptoCurrencyStatus.currency.id.rawCurrencyId != null) {
+ activeList.add(TokenActionsState.ActionState.Analytics(ScenarioUnavailabilityReason.None))
+ }
+
// copy address
if (isAddressAvailable(cryptoCurrencyStatus.value.networkAddress)) {
activeList.add(TokenActionsState.ActionState.CopyAddress(ScenarioUnavailabilityReason.None))
diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/model/TokenActionsState.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/model/TokenActionsState.kt
index c6db8e28e2..2531bc3ee2 100644
--- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/model/TokenActionsState.kt
+++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/model/TokenActionsState.kt
@@ -30,6 +30,8 @@ data class TokenActionsState(
data class Send(override val unavailabilityReason: ScenarioUnavailabilityReason) : ActionState()
+ data class Analytics(override val unavailabilityReason: ScenarioUnavailabilityReason) : ActionState()
+
data class HideToken(override val unavailabilityReason: ScenarioUnavailabilityReason) : ActionState()
}
}
\ No newline at end of file
diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt
index d84cc432eb..3b4b3bb478 100644
--- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt
+++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/ui/ManageTokensScreen.kt
@@ -53,6 +53,8 @@ import com.tangem.core.ui.components.snackbar.TangemSnackbarHost
import com.tangem.core.ui.event.EventEffect
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.haptic.TangemHapticEffect
+import com.tangem.core.ui.res.LocalHapticManager
import com.tangem.core.ui.res.LocalSnackbarHostState
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@@ -369,6 +371,8 @@ private fun NetworksList(
isEditable: Boolean,
modifier: Modifier = Modifier,
) {
+ val hapticManager = LocalHapticManager.current
+
AnimatedVisibility(
modifier = modifier,
visible = networks is NetworksUM.Expanded,
@@ -403,7 +407,14 @@ private fun NetworksList(
if (isEditable) {
TangemSwitch(
checked = network.isSelected,
- onCheckedChange = network.onSelectedStateChange,
+ onCheckedChange = { checked ->
+ if (checked) {
+ hapticManager.perform(TangemHapticEffect.View.ToggleOn)
+ } else {
+ hapticManager.perform(TangemHapticEffect.View.ToggleOff)
+ }
+ network.onSelectedStateChange(checked)
+ },
)
}
},
diff --git a/features/markets/api/src/main/kotlin/com/tangem/features/markets/details/MarketsTokenDetailsComponent.kt b/features/markets/api/src/main/kotlin/com/tangem/features/markets/details/MarketsTokenDetailsComponent.kt
index b7c38d44bb..3a4b5e4b57 100644
--- a/features/markets/api/src/main/kotlin/com/tangem/features/markets/details/MarketsTokenDetailsComponent.kt
+++ b/features/markets/api/src/main/kotlin/com/tangem/features/markets/details/MarketsTokenDetailsComponent.kt
@@ -19,6 +19,7 @@ interface MarketsTokenDetailsComponent : ComposableContentComponent {
data class Params(
val token: TokenMarketParams,
val appCurrency: AppCurrency,
+ val showPortfolio: Boolean,
)
@Composable
diff --git a/features/markets/impl/build.gradle.kts b/features/markets/impl/build.gradle.kts
index 8cccec2563..d356234b52 100644
--- a/features/markets/impl/build.gradle.kts
+++ b/features/markets/impl/build.gradle.kts
@@ -46,6 +46,7 @@ dependencies {
implementation(deps.compose.ui.utils)
implementation(deps.lifecycle.compose)
implementation(deps.androidx.activity.compose)
+ implementation(deps.markdown.composeview)
/* DI */
implementation(deps.hilt.android)
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/DefaultMarketsTokenDetailsComponent.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/DefaultMarketsTokenDetailsComponent.kt
index 0d758ce282..22c2c2b970 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/DefaultMarketsTokenDetailsComponent.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/DefaultMarketsTokenDetailsComponent.kt
@@ -33,17 +33,21 @@ internal class DefaultMarketsTokenDetailsComponent @AssistedInject constructor(
private val model: MarketsTokenDetailsModel = getOrCreateModel(params)
- private val portfolioComponent = portfolioComponentFactory.create(
- context = child("my_portfolio"),
- params = MarketsPortfolioComponent.Params(params.token),
- )
+ private val portfolioComponent: MarketsPortfolioComponent? = if (params.showPortfolio) {
+ portfolioComponentFactory.create(
+ context = child("my_portfolio"),
+ params = MarketsPortfolioComponent.Params(params.token),
+ )
+ } else {
+ null
+ }
init {
componentScope.launch {
model.networksState.collectLatest {
when (it) {
- is TokenNetworksState.NetworksAvailable -> portfolioComponent.setTokenNetworks(it.networks)
- TokenNetworksState.NoNetworksAvailable -> portfolioComponent.setNoNetworksAvailable()
+ is TokenNetworksState.NetworksAvailable -> portfolioComponent?.setTokenNetworks(it.networks)
+ TokenNetworksState.NoNetworksAvailable -> portfolioComponent?.setNoNetworksAvailable()
else -> {}
}
}
@@ -79,10 +83,16 @@ internal class DefaultMarketsTokenDetailsComponent @AssistedInject constructor(
backgroundColor = LocalMainBottomSheetColor.current.value,
addTopBarStatusBarPadding = false,
state = state,
- onBackClick = ::navigateBack,
+ onBackClick = {
+ if (bsState == BottomSheetState.EXPANDED) {
+ navigateBack()
+ }
+ },
onHeaderSizeChange = onHeaderSizeChange,
- portfolioBlock = { blockModifier ->
- portfolioComponent.Content(blockModifier)
+ portfolioBlock = portfolioComponent?.let { component ->
+ { blockModifier ->
+ component.Content(blockModifier)
+ }
},
)
}
@@ -109,8 +119,10 @@ internal class DefaultMarketsTokenDetailsComponent @AssistedInject constructor(
state = state,
onBackClick = ::navigateBack,
onHeaderSizeChange = {},
- portfolioBlock = { blockModifier ->
- portfolioComponent.Content(blockModifier)
+ portfolioBlock = portfolioComponent?.let { component ->
+ { blockModifier ->
+ component.Content(blockModifier)
+ }
},
)
}
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt
index 83b17519eb..c1f7cd2393 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt
@@ -4,7 +4,6 @@ import androidx.compose.runtime.Stable
import arrow.core.getOrElse
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.common.ui.charts.state.sorted
import com.tangem.core.decompose.di.ComponentScoped
import com.tangem.core.decompose.model.Model
@@ -135,15 +134,16 @@ internal class MarketsTokenDetailsModel @Inject constructor(
fiatCurrencySymbol = currentAppCurrency.value.symbol,
),
dateTimeText = resourceReference(R.string.common_today),
- priceChangePercentText = BigDecimalFormatter.formatPercent(
- percent = params.token.tokenQuotes.h24Percent,
- useAbsoluteValue = true,
- ),
+ priceChangePercentText = params.token.tokenQuotes.h24Percent?.let {
+ BigDecimalFormatter.formatPercent(
+ percent = it,
+ useAbsoluteValue = true,
+ )
+ },
priceChangeType = params.token.tokenQuotes.h24Percent.percentChangeType(),
iconUrl = params.token.imageUrl,
chartState = MarketsTokenDetailsUM.ChartState(
dataProducer = chartDataProducer,
- chartLook = MarketChartLook(),
onLoadRetryClick = ::onLoadRetryClicked,
status = MarketsTokenDetailsUM.ChartState.Status.LOADING,
onMarkerPointSelected = ::onMarkerPointSelected,
@@ -320,6 +320,7 @@ internal class MarketsTokenDetailsModel @Inject constructor(
currentQuotes.value = newInfo.quotes
val percent = newInfo.quotes.getPercentByInterval(interval = state.value.selectedInterval)
+
state.update {
it.copy(
priceText = newInfo.quotes.currentPrice.formatAsPrice(currentAppCurrency.value),
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/MarketsTokenDetailsContent.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/MarketsTokenDetailsContent.kt
index 9bbdfb559c..295497c053 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/MarketsTokenDetailsContent.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/MarketsTokenDetailsContent.kt
@@ -18,7 +18,6 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import com.tangem.common.ui.charts.state.MarketChartDataProducer
-import com.tangem.common.ui.charts.state.MarketChartLook
import com.tangem.core.ui.components.*
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
@@ -54,7 +53,7 @@ internal fun MarketsTokenDetailsContent(
addTopBarStatusBarPadding: Boolean,
onBackClick: () -> Unit,
onHeaderSizeChange: (Dp) -> Unit,
- portfolioBlock: @Composable (Modifier) -> Unit,
+ portfolioBlock: @Composable ((Modifier) -> Unit)?,
modifier: Modifier = Modifier,
) {
Content(
@@ -78,7 +77,7 @@ private fun Content(
addTopBarStatusBarInsets: Boolean,
onBackClick: () -> Unit,
onHeaderSizeChange: (Dp) -> Unit,
- portfolioBlock: @Composable (Modifier) -> Unit,
+ portfolioBlock: @Composable ((Modifier) -> Unit)?,
modifier: Modifier = Modifier,
) {
val density = LocalDensity.current
@@ -129,9 +128,7 @@ private fun Content(
)
}
item { SpacerH32() }
- item(
- contentType = "chart",
- ) {
+ item("chart") {
MarketTokenDetailsChart(
modifier = Modifier.fillMaxWidth(),
backgroundColor = backgroundColor,
@@ -167,11 +164,13 @@ private fun Header(state: MarketsTokenDetailsUM, modifier: Modifier = Modifier)
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.tertiary,
)
- PriceChangeInPercent(
- valueInPercent = state.priceChangePercentText,
- type = state.priceChangeType,
- textStyle = TangemTheme.typography.caption2,
- )
+ if (state.priceChangePercentText != null) {
+ PriceChangeInPercent(
+ valueInPercent = state.priceChangePercentText,
+ type = state.priceChangeType,
+ textStyle = TangemTheme.typography.caption2,
+ )
+ }
}
}
SpacerW4()
@@ -290,7 +289,6 @@ private fun Preview() {
priceChangeType = PriceChangeType.UP,
chartState = MarketsTokenDetailsUM.ChartState(
dataProducer = MarketChartDataProducer.build { },
- chartLook = MarketChartLook(),
onLoadRetryClick = {},
status = MarketsTokenDetailsUM.ChartState.Status.LOADING,
onMarkerPointSelected = { _, _ -> },
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/InfoBottomSheet.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/InfoBottomSheet.kt
index 0d44a41f91..d78f6b2d99 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/InfoBottomSheet.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/InfoBottomSheet.kt
@@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
@@ -17,6 +16,7 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetTitle
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.markets.details.impl.ui.state.InfoBottomSheetContent
+import dev.jeziellago.compose.markdowntext.MarkdownText
@Composable
internal fun InfoBottomSheet(config: TangemBottomSheetConfig) {
@@ -35,10 +35,14 @@ internal fun InfoBottomSheet(config: TangemBottomSheetConfig) {
.verticalScroll(rememberScrollState())
.padding(horizontal = TangemTheme.dimens.spacing28),
) {
- Text(
- text = it.body.resolveReference(),
- style = TangemTheme.typography.body2,
- color = TangemTheme.colors.text.secondary,
+ MarkdownText(
+ markdown = it.body.resolveReference(),
+ disableLinkMovementMethod = true,
+ linkifyMask = 0,
+ syntaxHighlightColor = TangemTheme.colors.text.secondary,
+ style = TangemTheme.typography.body2.copy(
+ color = TangemTheme.colors.text.secondary,
+ ),
)
SpacerH(bottomBarHeight)
}
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/LinksBlock.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/LinksBlock.kt
index cfbb51ec74..e08e4a3052 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/LinksBlock.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/LinksBlock.kt
@@ -10,7 +10,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
-import com.tangem.core.ui.components.SmallButtonShimmer
+import com.tangem.core.ui.components.ChipShimmer
import com.tangem.core.ui.components.TextShimmer
import com.tangem.core.ui.components.block.information.InformationBlock
import com.tangem.core.ui.components.buttons.chip.Chip
@@ -145,9 +145,8 @@ private fun SubBlockPlaceholder(modifier: Modifier = Modifier, lastBlock: Boolea
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
) {
repeat(times = 3) {
- SmallButtonShimmer(
+ ChipShimmer(
modifier = Modifier.weight(1f),
- withIcon = true,
)
}
}
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/PricePerformanceBlock.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/PricePerformanceBlock.kt
index 057d1bbed6..4e947ff908 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/PricePerformanceBlock.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/PricePerformanceBlock.kt
@@ -161,7 +161,7 @@ internal fun PricePerformanceBlockPlaceholder(modifier: Modifier = Modifier) {
},
content = {
Column(
- modifier = modifier.padding(vertical = TangemTheme.dimens.spacing8),
+ modifier = Modifier.padding(vertical = TangemTheme.dimens.spacing8),
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
) {
Row(
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/TokenMarketDetailsBody.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/TokenMarketDetailsBody.kt
index 5d9e93fd4e..d7ae7737c6 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/TokenMarketDetailsBody.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/components/TokenMarketDetailsBody.kt
@@ -13,7 +13,7 @@ import com.tangem.features.markets.tokenlist.impl.ui.components.UnableToLoadData
internal fun LazyListScope.tokenMarketDetailsBody(
state: MarketsTokenDetailsUM.Body,
- portfolioBlock: @Composable (Modifier) -> Unit,
+ portfolioBlock: @Composable ((Modifier) -> Unit)?,
) {
when (state) {
MarketsTokenDetailsUM.Body.Loading -> {
@@ -21,8 +21,10 @@ internal fun LazyListScope.tokenMarketDetailsBody(
DescriptionPlaceholder(modifier = Modifier.blockPaddings())
}
- item(key = "portfolio") {
- portfolioBlock(Modifier.blockPaddings())
+ if (portfolioBlock != null) {
+ item(key = "portfolio") {
+ portfolioBlock(Modifier.blockPaddings())
+ }
}
loadingInfoBlocks()
@@ -32,8 +34,10 @@ internal fun LazyListScope.tokenMarketDetailsBody(
description(state.description)
}
- item(key = "portfolio") {
- portfolioBlock(Modifier.blockPaddings())
+ if (portfolioBlock != null) {
+ item(key = "portfolio") {
+ portfolioBlock(Modifier.blockPaddings())
+ }
}
infoBlocksList(state.infoBlocks)
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/state/MarketsTokenDetailsUM.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/state/MarketsTokenDetailsUM.kt
index 6023a1c8a2..cec823bccb 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/state/MarketsTokenDetailsUM.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/ui/state/MarketsTokenDetailsUM.kt
@@ -2,7 +2,6 @@ package com.tangem.features.markets.details.impl.ui.state
import androidx.compose.runtime.Immutable
import com.tangem.common.ui.charts.state.MarketChartDataProducer
-import com.tangem.common.ui.charts.state.MarketChartLook
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.marketprice.PriceChangeType
import com.tangem.core.ui.event.StateEvent
@@ -15,7 +14,7 @@ internal data class MarketsTokenDetailsUM(
val priceText: String,
val iconUrl: String?,
val dateTimeText: TextReference,
- val priceChangePercentText: String,
+ val priceChangePercentText: String?,
val priceChangeType: PriceChangeType,
val selectedInterval: PriceChangeInterval,
val markerSet: Boolean,
@@ -29,7 +28,6 @@ internal data class MarketsTokenDetailsUM(
data class ChartState(
val status: Status,
val dataProducer: MarketChartDataProducer,
- val chartLook: MarketChartLook,
val onLoadRetryClick: () -> Unit,
val onMarkerPointSelected: (time: BigDecimal?, price: BigDecimal?) -> Unit,
) {
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt
index 1419aa7349..7f96268b4c 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/entry/impl/DefaultMarketsEntryComponent.kt
@@ -70,6 +70,7 @@ internal class DefaultMarketsEntryComponent @AssistedInject constructor(
params = MarketsTokenDetailsComponent.Params(
token = token.toSerializableParam(),
appCurrency = appCurrency,
+ showPortfolio = true,
),
),
)
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt
index b77101acb9..c134371f8e 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/TokenActionsHandler.kt
@@ -182,13 +182,12 @@ internal class TokenActionsHandler @AssistedInject constructor(
is TokenActionsState.ActionState.HideToken -> null
is TokenActionsState.ActionState.Receive -> TokenActionsBSContentUM.Action.Receive
is TokenActionsState.ActionState.Sell -> TokenActionsBSContentUM.Action.Sell
- is TokenActionsState.ActionState.Send -> {
- TokenActionsBSContentUM.Action.Send.takeIf {
- cryptoCurrencyData.status.value.amount.isNullOrZero().not()
- }
+ is TokenActionsState.ActionState.Send -> TokenActionsBSContentUM.Action.Send.takeIf {
+ cryptoCurrencyData.status.value.amount.isNullOrZero().not()
}
is TokenActionsState.ActionState.Stake -> TokenActionsBSContentUM.Action.Stake
is TokenActionsState.ActionState.Swap -> TokenActionsBSContentUM.Action.Exchange
+ is TokenActionsState.ActionState.Analytics -> null
}
.takeIf { this.unavailabilityReason == ScenarioUnavailabilityReason.None }
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt
index 524c8bfd4f..b73ba99609 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt
@@ -36,6 +36,8 @@ import com.tangem.core.ui.components.currency.icon.CoinIcon
import com.tangem.core.ui.components.rows.ArrowRow
import com.tangem.core.ui.components.rows.BlockchainRow
import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.haptic.TangemHapticEffect
+import com.tangem.core.ui.res.LocalHapticManager
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.markets.impl.R
@@ -168,6 +170,8 @@ private fun ContinueButton(
@Suppress("LongMethod")
@Composable
private fun NetworkSelection(state: SelectNetworkUM, modifier: Modifier = Modifier) {
+ val hapticManager = LocalHapticManager.current
+
InformationBlock(
modifier = modifier,
title = {
@@ -229,7 +233,15 @@ private fun NetworkSelection(state: SelectNetworkUM, modifier: Modifier = Modifi
} else {
TangemTheme.colors.icon.inactive
},
- onCheckedChange = { state.onNetworkSwitchClick(network, it) },
+ onCheckedChange = { checked ->
+ if (checked) {
+ hapticManager.perform(TangemHapticEffect.View.ToggleOn)
+ } else {
+ hapticManager.perform(TangemHapticEffect.View.ToggleOff)
+ }
+
+ state.onNetworkSwitchClick(network, checked)
+ },
enabled = network.isEnabled,
)
},
diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/model/TokenMarketBlockModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/model/TokenMarketBlockModel.kt
index bb584f1731..71c71a4d5e 100644
--- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/model/TokenMarketBlockModel.kt
+++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/token/block/impl/model/TokenMarketBlockModel.kt
@@ -143,6 +143,7 @@ internal class TokenMarketBlockModel @Inject constructor(
AppRoute.MarketsTokenDetails(
token = tokenParam,
appCurrency = currentAppCurrency.value,
+ showPortfolio = false,
),
)
}
diff --git a/features/wallet/impl/build.gradle.kts b/features/wallet/impl/build.gradle.kts
index 5aa98a53a1..db8ba49b05 100644
--- a/features/wallet/impl/build.gradle.kts
+++ b/features/wallet/impl/build.gradle.kts
@@ -79,6 +79,7 @@ dependencies {
implementation(projects.domain.analytics)
implementation(projects.domain.visa)
implementation(projects.domain.staking.models)
+ implementation(projects.domain.markets.models)
//TODO: Create api/impl modules for onboarding [REDACTED_JIRA]
implementation(projects.features.onboarding)
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 f4009e9c73..0ff004ae48 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
@@ -95,6 +95,11 @@ internal class MultiWalletCurrencyActionsConverter(
icon = R.drawable.ic_hide_24
action = { clickIntents.onHideTokensClick(cryptoCurrencyStatus) }
}
+ is TokenActionsState.ActionState.Analytics -> {
+ title = resourceReference(R.string.common_analytics)
+ icon = R.drawable.ic_analytics_24
+ action = { clickIntents.onAnalyticsClick(cryptoCurrencyStatus) }
+ }
}
return TokenActionButtonConfig(
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletCurrencyActionsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletCurrencyActionsClickIntents.kt
index e66128d2c8..1a067b02f7 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletCurrencyActionsClickIntents.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletCurrencyActionsClickIntents.kt
@@ -20,6 +20,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.extenstions.unwrap
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.demo.IsDemoCardUseCase
+import com.tangem.domain.markets.TokenMarketParams
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.staking.model.stakekit.Yield
import com.tangem.domain.tokens.*
@@ -48,6 +49,7 @@ import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch
+import java.math.BigDecimal
import javax.inject.Inject
interface WalletCurrencyActionsClickIntents {
@@ -77,6 +79,8 @@ interface WalletCurrencyActionsClickIntents {
fun onPerformHideToken(cryptoCurrencyStatus: CryptoCurrencyStatus)
fun onExploreClick()
+
+ fun onAnalyticsClick(cryptoCurrencyStatus: CryptoCurrencyStatus)
}
@Suppress("LongParameterList", "LargeClass")
@@ -378,6 +382,31 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
showErrorIfDemoModeOrElse(action = ::openExplorer)
}
+ override fun onAnalyticsClick(cryptoCurrencyStatus: CryptoCurrencyStatus) {
+ viewModelScope.launch {
+ val rawId = cryptoCurrencyStatus.currency.id.rawCurrencyId ?: return@launch
+
+ appRouter.push(
+ AppRoute.MarketsTokenDetails(
+ TokenMarketParams(
+ id = rawId,
+ name = cryptoCurrencyStatus.currency.name,
+ symbol = cryptoCurrencyStatus.currency.symbol,
+ tokenQuotes = TokenMarketParams.Quotes(
+ currentPrice = cryptoCurrencyStatus.value.fiatRate ?: BigDecimal.ZERO,
+ h24Percent = cryptoCurrencyStatus.value.priceChange,
+ weekPercent = null,
+ monthPercent = null,
+ ),
+ imageUrl = cryptoCurrencyStatus.currency.iconUrl,
+ ),
+ appCurrency = getSelectedAppCurrencyUseCase.unwrap(),
+ showPortfolio = true,
+ ),
+ )
+ }
+ }
+
override fun onStakeClick(cryptoCurrencyStatus: CryptoCurrencyStatus, yield: Yield?) {
val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
stateHolder.update(CloseBottomSheetTransformer(userWalletId = userWallet.walletId))
diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml
index 4b1fb256b2..9fc95abab5 100644
--- a/gradle/dependencies.toml
+++ b/gradle/dependencies.toml
@@ -85,6 +85,7 @@ leakcanary = "2.13"
decompose = "2.2.2"
room = "2.6.1"
markdown = "0.7.2"
+markdownComposeView = "0.5.4"
# endregion Other libraries
# region Tangem
@@ -270,4 +271,5 @@ room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
markdown = { module = "org.jetbrains:markdown", version.ref = "markdown" }
+markdown-composeview = { module = "com.github.jeziellago:compose-markdown", version.ref = "markdownComposeView" }
# endregion Other