Updated on 2026-08-14
This commit is contained in:
parent
9cde8a7ba0
commit
183cb93c1a
13 changed files with 107 additions and 46 deletions
|
|
@ -27,13 +27,13 @@ import com.tangem.domain.notifications.SendPushTokenUseCase
|
||||||
import com.tangem.domain.notifications.models.ApplicationId
|
import com.tangem.domain.notifications.models.ApplicationId
|
||||||
import com.tangem.domain.notifications.models.NotificationsError
|
import com.tangem.domain.notifications.models.NotificationsError
|
||||||
import com.tangem.domain.onramp.FetchHotCryptoUseCase
|
import com.tangem.domain.onramp.FetchHotCryptoUseCase
|
||||||
import com.tangem.domain.stories.GetStoryContentUseCase
|
|
||||||
import com.tangem.domain.stories.models.StoryContentIds
|
|
||||||
import com.tangem.domain.quotes.multi.MultiQuoteUpdater
|
import com.tangem.domain.quotes.multi.MultiQuoteUpdater
|
||||||
import com.tangem.domain.settings.DeleteDeprecatedLogsUseCase
|
import com.tangem.domain.settings.DeleteDeprecatedLogsUseCase
|
||||||
import com.tangem.domain.settings.IncrementAppLaunchCounterUseCase
|
import com.tangem.domain.settings.IncrementAppLaunchCounterUseCase
|
||||||
import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase
|
import com.tangem.domain.settings.usercountry.FetchUserCountryUseCase
|
||||||
import com.tangem.domain.staking.FetchStakingOptionsUseCase
|
import com.tangem.domain.staking.FetchStakingOptionsUseCase
|
||||||
|
import com.tangem.domain.stories.GetStoryContentUseCase
|
||||||
|
import com.tangem.domain.stories.models.StoryContentIds
|
||||||
import com.tangem.domain.wallets.usecase.AssociateWalletsWithApplicationIdUseCase
|
import com.tangem.domain.wallets.usecase.AssociateWalletsWithApplicationIdUseCase
|
||||||
import com.tangem.domain.wallets.usecase.GetSavedWalletsCountUseCase
|
import com.tangem.domain.wallets.usecase.GetSavedWalletsCountUseCase
|
||||||
import com.tangem.domain.wallets.usecase.UpdateRemoteWalletsInfoUseCase
|
import com.tangem.domain.wallets.usecase.UpdateRemoteWalletsInfoUseCase
|
||||||
|
|
@ -268,8 +268,12 @@ internal class MainViewModel @Inject constructor(
|
||||||
onShownBalanceToastAction()
|
onShownBalanceToastAction()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
startIconId = if (settings.isBalanceHidden) {
|
||||||
|
R.drawable.ic_eye_off_outline_24
|
||||||
|
} else {
|
||||||
|
R.drawable.ic_eye_outline_24
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
messageSender.send(message)
|
messageSender.send(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ private fun BottomSheetIcon(icon: MessageBottomSheetUM.Icon, modifier: Modifier
|
||||||
}
|
}
|
||||||
|
|
||||||
val backgroundColor = when (icon.backgroundType) {
|
val backgroundColor = when (icon.backgroundType) {
|
||||||
MessageBottomSheetUM.Icon.BackgroundType.Unspecified -> Color.Unspecified
|
MessageBottomSheetUM.Icon.BackgroundType.Unspecified -> TangemTheme.colors3.bg.tertiary
|
||||||
MessageBottomSheetUM.Icon.BackgroundType.SameAsTint -> {
|
MessageBottomSheetUM.Icon.BackgroundType.SameAsTint -> {
|
||||||
if (tint == Color.Unspecified) Color.Unspecified else tint.copy(alpha = 0.1f)
|
if (tint == Color.Unspecified) Color.Unspecified else tint.copy(alpha = 0.1f)
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +217,7 @@ private fun BottomSheetVector(vector: MessageBottomSheetUM.Vector, modifier: Mod
|
||||||
}
|
}
|
||||||
|
|
||||||
val backgroundColor = when (vector.backgroundType) {
|
val backgroundColor = when (vector.backgroundType) {
|
||||||
MessageBottomSheetUM.Vector.BackgroundType.Unspecified -> Color.Unspecified
|
MessageBottomSheetUM.Vector.BackgroundType.Unspecified -> TangemTheme.colors3.bg.tertiary
|
||||||
MessageBottomSheetUM.Vector.BackgroundType.SameAsTint -> tint
|
MessageBottomSheetUM.Vector.BackgroundType.SameAsTint -> tint
|
||||||
MessageBottomSheetUM.Vector.BackgroundType.Accent -> TangemTheme.colors3.bg.status.infoSubtle
|
MessageBottomSheetUM.Vector.BackgroundType.Accent -> TangemTheme.colors3.bg.status.infoSubtle
|
||||||
MessageBottomSheetUM.Vector.BackgroundType.Informative -> TangemTheme.colors3.bg.status.infoSubtle
|
MessageBottomSheetUM.Vector.BackgroundType.Informative -> TangemTheme.colors3.bg.status.infoSubtle
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,11 @@ fun TangemTopSnackbar(snackbarMessage: SnackbarMessage, modifier: Modifier = Mod
|
||||||
val action = snackbarMessage.action
|
val action = snackbarMessage.action
|
||||||
val hasAction = actionLabel != null && action != null
|
val hasAction = actionLabel != null && action != null
|
||||||
|
|
||||||
var isTextOverflowing by remember { mutableStateOf(false) }
|
var isTextOverflowing by remember(
|
||||||
|
snackbarMessage.message,
|
||||||
|
snackbarMessage.startIconId,
|
||||||
|
hasAction,
|
||||||
|
) { mutableStateOf(false) }
|
||||||
val shape = if (isTextOverflowing) {
|
val shape = if (isTextOverflowing) {
|
||||||
RoundedCornerShape(TangemTheme.dimens2.x5)
|
RoundedCornerShape(TangemTheme.dimens2.x5)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -55,7 +59,7 @@ fun TangemTopSnackbar(snackbarMessage: SnackbarMessage, modifier: Modifier = Mod
|
||||||
.clip(shape)
|
.clip(shape)
|
||||||
.hazeEffectTangem()
|
.hazeEffectTangem()
|
||||||
.sizeIn(minHeight = TangemTheme.dimens2.x11)
|
.sizeIn(minHeight = TangemTheme.dimens2.x11)
|
||||||
.padding(start = TangemTheme.dimens2.x5, end = TangemTheme.dimens2.x1)
|
.padding(start = TangemTheme.dimens2.x5, end = TangemTheme.dimens2.x3)
|
||||||
.padding(vertical = TangemTheme.dimens2.x1),
|
.padding(vertical = TangemTheme.dimens2.x1),
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
) {
|
) {
|
||||||
|
|
@ -81,7 +85,10 @@ fun TangemTopSnackbar(snackbarMessage: SnackbarMessage, modifier: Modifier = Mod
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
style = TangemTheme.typography.body2,
|
style = TangemTheme.typography.body2,
|
||||||
onTextLayout = { if (hasAction) isTextOverflowing = it.hasVisualOverflow },
|
onTextLayout = { layoutResult ->
|
||||||
|
val isOverflowing = hasAction && layoutResult.hasVisualOverflow
|
||||||
|
if (isTextOverflowing != isOverflowing) isTextOverflowing = isOverflowing
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
SpacerW(TangemTheme.dimens2.x4)
|
SpacerW(TangemTheme.dimens2.x4)
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,17 @@ import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.drawWithContent
|
import androidx.compose.ui.draw.drawWithContent
|
||||||
|
import androidx.compose.ui.draw.innerShadow
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.geometry.Size
|
import androidx.compose.ui.geometry.Size
|
||||||
import androidx.compose.ui.graphics.BlendMode
|
import androidx.compose.ui.graphics.BlendMode
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.drawscope.rotate
|
import androidx.compose.ui.graphics.drawscope.rotate
|
||||||
|
import androidx.compose.ui.graphics.shadow.Shadow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.unit.DpOffset
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.tangem.core.ui.components.haze.hazeForegroundEffectTangem
|
import com.tangem.core.ui.components.haze.hazeForegroundEffectTangem
|
||||||
import com.tangem.core.ui.extensions.conditionalCompose
|
import com.tangem.core.ui.extensions.conditionalCompose
|
||||||
|
|
@ -232,15 +235,28 @@ enum class TangemMessageEffect(val isAnimatable: Boolean) {
|
||||||
None -> if (isInDarkTheme) Color(0x1AFFFFFF) else Color.Transparent
|
None -> if (isInDarkTheme) Color(0x1AFFFFFF) else Color.Transparent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color of the inner shadow that glows inward evenly from every edge over the card body,
|
||||||
|
* or `null` when the effect doesn't have one. [None] uses a subtle white 15% highlight
|
||||||
|
* (Figma: inner shadow X0 Y0 blur 74 spread 0, #FFFFFF · 15%).
|
||||||
|
*/
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
fun getInnerGlowColor(isInDarkTheme: Boolean): Color? = when (this) {
|
||||||
|
None -> if (isInDarkTheme) Color(0x26FFFFFF) else null
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Applies a message effect background to the [Modifier] based on the provided [messageEffect] and [radius] */
|
/** Applies a message effect background to the [Modifier] based on the provided [messageEffect] and [radius] */
|
||||||
|
@Suppress("LongMethod")
|
||||||
@Composable
|
@Composable
|
||||||
fun Modifier.messageEffectBackground(messageEffect: TangemMessageEffect, radius: Dp, contentColor: Color): Modifier {
|
fun Modifier.messageEffectBackground(messageEffect: TangemMessageEffect, radius: Dp, contentColor: Color): Modifier {
|
||||||
val isInDarkTheme = LocalIsInDarkTheme.current
|
val isInDarkTheme = LocalIsInDarkTheme.current
|
||||||
val borderGradientColors = remember(messageEffect, isInDarkTheme) { messageEffect.getBorderGradient(isInDarkTheme) }
|
val borderGradientColors = remember(messageEffect, isInDarkTheme) { messageEffect.getBorderGradient(isInDarkTheme) }
|
||||||
val gradientColors = remember(messageEffect, isInDarkTheme) { messageEffect.getColorGradient(isInDarkTheme) }
|
val gradientColors = remember(messageEffect, isInDarkTheme) { messageEffect.getColorGradient(isInDarkTheme) }
|
||||||
val gradientTint = remember(messageEffect, isInDarkTheme) { messageEffect.getGradientTint(isInDarkTheme) }
|
val gradientTint = remember(messageEffect, isInDarkTheme) { messageEffect.getGradientTint(isInDarkTheme) }
|
||||||
|
val innerGlowColor = remember(messageEffect, isInDarkTheme) { messageEffect.getInnerGlowColor(isInDarkTheme) }
|
||||||
|
|
||||||
val angle by if (messageEffect.isAnimatable) {
|
val angle by if (messageEffect.isAnimatable) {
|
||||||
LocalMessageEffectAnimation.current.offsetState
|
LocalMessageEffectAnimation.current.offsetState
|
||||||
|
|
@ -293,14 +309,28 @@ fun Modifier.messageEffectBackground(messageEffect: TangemMessageEffect, radius:
|
||||||
blendMode = BlendMode.SrcIn,
|
blendMode = BlendMode.SrcIn,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
drawRect(
|
// None ignores contentColor — its body is the white-10% frosted haze, not a solid fill
|
||||||
color = contentColor,
|
if (messageEffect != TangemMessageEffect.None) {
|
||||||
topLeft = Offset(padding, padding),
|
drawRect(
|
||||||
size = Size(size.width - 2 * padding, size.height - 2 * padding),
|
color = contentColor,
|
||||||
)
|
topLeft = Offset(padding, padding),
|
||||||
|
size = Size(size.width - 2 * padding, size.height - 2 * padding),
|
||||||
|
)
|
||||||
|
}
|
||||||
drawContent()
|
drawContent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.conditionalCompose(innerGlowColor != null) {
|
||||||
|
innerShadow(
|
||||||
|
shape = RoundedCornerShape(0.dp),
|
||||||
|
shadow = Shadow(
|
||||||
|
radius = 10.dp,
|
||||||
|
spread = 10.dp,
|
||||||
|
color = innerGlowColor ?: Color.Transparent,
|
||||||
|
offset = DpOffset(0.dp, 0.dp),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ fun BigDecimalFiatFormat.defaultAmount(): BigDecimalFormat = BigDecimalFormat {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
formatter.format(value)
|
formatter.format(value.zeroIfRoundsToZero(FIAT_MARKET_DEFAULT_DIGITS))
|
||||||
.replace(formatterCurrency.getSymbol(locale), fiatCurrencySymbol)
|
.replace(formatterCurrency.getSymbol(locale), fiatCurrencySymbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +94,7 @@ fun BigDecimalFiatFormatStyled.defaultAmount(spanStyleReference: SpanStyleRefere
|
||||||
val formattingAmount = if (value.isLessThanThreshold()) {
|
val formattingAmount = if (value.isLessThanThreshold()) {
|
||||||
FIAT_FORMAT_THRESHOLD
|
FIAT_FORMAT_THRESHOLD
|
||||||
} else {
|
} else {
|
||||||
value
|
value.zeroIfRoundsToZero(FIAT_MARKET_DEFAULT_DIGITS)
|
||||||
}
|
}
|
||||||
|
|
||||||
val decimalSeparator = (formatter as? DecimalFormat)?.decimalFormatSymbols?.decimalSeparator
|
val decimalSeparator = (formatter as? DecimalFormat)?.decimalFormatSymbols?.decimalSeparator
|
||||||
|
|
@ -273,6 +273,9 @@ fun BigDecimalFiatFormat.optionalDecimals(): BigDecimalFormat = BigDecimalFormat
|
||||||
|
|
||||||
private fun BigDecimal.isLessThanThreshold() = this > BigDecimal.ZERO && this < FIAT_FORMAT_THRESHOLD
|
private fun BigDecimal.isLessThanThreshold() = this > BigDecimal.ZERO && this < FIAT_FORMAT_THRESHOLD
|
||||||
|
|
||||||
|
private fun BigDecimal.zeroIfRoundsToZero(scale: Int): BigDecimal =
|
||||||
|
if (setScale(scale, RoundingMode.HALF_UP).signum() == 0) BigDecimal.ZERO else this
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns amount with correct scale
|
* Returns amount with correct scale
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,38 @@ internal class BigDecimalFiatFormatTest {
|
||||||
.isEqualTo("<" + "0,01".addSymbolWithSpaceRight(usdSymbol))
|
.isEqualTo("<" + "0,01".addSymbolWithSpaceRight(usdSymbol))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `defaultAmount tiny negative rounding to zero is formatted without sign`() {
|
||||||
|
val testValue = BigDecimal("-0.0001")
|
||||||
|
|
||||||
|
val formatted = testValue.format {
|
||||||
|
fiat(
|
||||||
|
fiatCurrencyCode = usdCurrencyCode,
|
||||||
|
fiatCurrencySymbol = usdSymbol,
|
||||||
|
locale = testLocale,
|
||||||
|
).defaultAmount()
|
||||||
|
}
|
||||||
|
|
||||||
|
Truth.assertThat(formatted)
|
||||||
|
.isEqualTo("0.00".addUsdSymbolLeft())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `defaultAmount negative rounding away from zero keeps sign`() {
|
||||||
|
val testValue = BigDecimal("-0.005")
|
||||||
|
|
||||||
|
val formatted = testValue.format {
|
||||||
|
fiat(
|
||||||
|
fiatCurrencyCode = usdCurrencyCode,
|
||||||
|
fiatCurrencySymbol = usdSymbol,
|
||||||
|
locale = testLocale,
|
||||||
|
).defaultAmount()
|
||||||
|
}
|
||||||
|
|
||||||
|
Truth.assertThat(formatted)
|
||||||
|
.isEqualTo("-" + "0.01".addUsdSymbolLeft())
|
||||||
|
}
|
||||||
|
|
||||||
// === approximateAmount() ===
|
// === approximateAmount() ===
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,6 @@ internal class DefaultFeedEntryComponent @AssistedInject constructor(
|
||||||
preselectedNetworkId: String? = null,
|
preselectedNetworkId: String? = null,
|
||||||
): DefaultEarnComponent.Params = DefaultEarnComponent.Params(
|
): DefaultEarnComponent.Params = DefaultEarnComponent.Params(
|
||||||
onBackClick = onBack,
|
onBackClick = onBack,
|
||||||
onSearchClicked = clickIntents::openSearch,
|
|
||||||
preselectedEarnType = preselectedEarnType,
|
preselectedEarnType = preselectedEarnType,
|
||||||
preselectedNetworkId = preselectedNetworkId,
|
preselectedNetworkId = preselectedNetworkId,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,10 @@ import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
||||||
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
import com.tangem.core.ui.components.haze.hazeEffectTangem
|
||||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||||
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
|
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
|
||||||
|
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
||||||
|
import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
||||||
import com.tangem.core.ui.extensions.clickableSingle
|
import com.tangem.core.ui.extensions.clickableSingle
|
||||||
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||||
import com.tangem.core.ui.res.LocalMainBottomSheetColor
|
import com.tangem.core.ui.res.LocalMainBottomSheetColor
|
||||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||||
|
|
@ -36,7 +39,7 @@ import com.tangem.domain.models.earn.PreselectedEarnType
|
||||||
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioComponent
|
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioComponent
|
||||||
import com.tangem.features.feed.components.feed.FeedBottomSheetRoute
|
import com.tangem.features.feed.components.feed.FeedBottomSheetRoute
|
||||||
import com.tangem.features.feed.model.earn.EarnModel
|
import com.tangem.features.feed.model.earn.EarnModel
|
||||||
import com.tangem.features.feed.ui.components.FeedSearchBar
|
import com.tangem.features.feed.ui.LocalIsOpenedInBottomSheet
|
||||||
import com.tangem.features.feed.ui.earn.EarnContent
|
import com.tangem.features.feed.ui.earn.EarnContent
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
@ -60,9 +63,13 @@ internal class DefaultEarnComponent(
|
||||||
val background = LocalMainBottomSheetColor.current.value
|
val background = LocalMainBottomSheetColor.current.value
|
||||||
val state by earnModel.state.collectAsStateWithLifecycle()
|
val state by earnModel.state.collectAsStateWithLifecycle()
|
||||||
if (LocalRedesignEnabled.current) {
|
if (LocalRedesignEnabled.current) {
|
||||||
FeedSearchBar(
|
TangemTopBar(
|
||||||
isSearchBarClickable = bottomSheetState.value == BottomSheetState.EXPANDED,
|
title = resourceReference(R.string.earn_title),
|
||||||
feedListSearchBar = state.feedListSearchBar,
|
type = if (LocalIsOpenedInBottomSheet.current) {
|
||||||
|
TangemTopBarType.BottomSheet
|
||||||
|
} else {
|
||||||
|
TangemTopBarType.Default
|
||||||
|
},
|
||||||
startContent = {
|
startContent = {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = ImageVector.vectorResource(id = R.drawable.ic_arrow_back_28),
|
imageVector = ImageVector.vectorResource(id = R.drawable.ic_arrow_back_28),
|
||||||
|
|
@ -136,7 +143,6 @@ internal class DefaultEarnComponent(
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Params(
|
data class Params(
|
||||||
val onBackClick: () -> Unit,
|
val onBackClick: () -> Unit,
|
||||||
val onSearchClicked: (source: String) -> Unit,
|
|
||||||
val preselectedEarnType: PreselectedEarnType? = null,
|
val preselectedEarnType: PreselectedEarnType? = null,
|
||||||
val preselectedNetworkId: String? = null,
|
val preselectedNetworkId: String? = null,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import com.arkivanov.decompose.router.slot.dismiss
|
||||||
import com.tangem.common.routing.AppRoute
|
import com.tangem.common.routing.AppRoute
|
||||||
import com.tangem.common.routing.AppRouter
|
import com.tangem.common.routing.AppRouter
|
||||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||||
import com.tangem.core.analytics.models.AnalyticsParam
|
|
||||||
import com.tangem.core.decompose.di.ModelScoped
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
|
|
@ -22,8 +21,8 @@ import com.tangem.domain.markets.TokenMarketInfo
|
||||||
import com.tangem.domain.models.currency.CryptoCurrency
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
import com.tangem.domain.models.earn.EarnNetworks
|
import com.tangem.domain.models.earn.EarnNetworks
|
||||||
import com.tangem.domain.models.earn.EarnTokenWithCurrency
|
import com.tangem.domain.models.earn.EarnTokenWithCurrency
|
||||||
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioManager
|
|
||||||
import com.tangem.domain.models.earn.PreselectedEarnType
|
import com.tangem.domain.models.earn.PreselectedEarnType
|
||||||
|
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioManager
|
||||||
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioManager.AnalyticsParams.Companion.CategoryEarn
|
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioManager.AnalyticsParams.Companion.CategoryEarn
|
||||||
import com.tangem.features.feed.components.earn.DefaultEarnComponent
|
import com.tangem.features.feed.components.earn.DefaultEarnComponent
|
||||||
import com.tangem.features.feed.components.earn.EarnNetworkFilterComponent
|
import com.tangem.features.feed.components.earn.EarnNetworkFilterComponent
|
||||||
|
|
@ -400,7 +399,6 @@ internal class EarnModel @Inject constructor(
|
||||||
onNetworkFilterClick = ::onNetworkFilterClick,
|
onNetworkFilterClick = ::onNetworkFilterClick,
|
||||||
onTypeFilterClick = ::onTypeFilterClick,
|
onTypeFilterClick = ::onTypeFilterClick,
|
||||||
onScroll = ::onMostlyUsedScrolled,
|
onScroll = ::onMostlyUsedScrolled,
|
||||||
onSearchBarClicked = { params.onSearchClicked(AnalyticsParam.ScreensSources.Earn.value) },
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
package com.tangem.features.feed.model.earn.state
|
package com.tangem.features.feed.model.earn.state
|
||||||
|
|
||||||
import com.tangem.core.decompose.di.ModelScoped
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
|
||||||
import com.tangem.features.feed.model.earn.state.transformers.EarnUMTransformer
|
import com.tangem.features.feed.model.earn.state.transformers.EarnUMTransformer
|
||||||
import com.tangem.features.feed.ui.earn.state.*
|
import com.tangem.features.feed.ui.earn.state.*
|
||||||
import com.tangem.features.feed.ui.feed.state.FeedListSearchBar
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
|
@ -36,10 +34,6 @@ internal class EarnStateController @Inject constructor() {
|
||||||
onNetworkFilterClick = {},
|
onNetworkFilterClick = {},
|
||||||
onTypeFilterClick = {},
|
onTypeFilterClick = {},
|
||||||
onSliderScroll = {},
|
onSliderScroll = {},
|
||||||
feedListSearchBar = FeedListSearchBar(
|
|
||||||
placeholderText = TextReference.EMPTY,
|
|
||||||
onBarClick = {},
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,16 +1,12 @@
|
||||||
package com.tangem.features.feed.model.earn.state.transformers
|
package com.tangem.features.feed.model.earn.state.transformers
|
||||||
|
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
|
||||||
import com.tangem.features.feed.impl.R
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnUM
|
import com.tangem.features.feed.ui.earn.state.EarnUM
|
||||||
import com.tangem.features.feed.ui.feed.state.FeedListSearchBar
|
|
||||||
|
|
||||||
internal class UpdateEarnUMInitialStateTransformer(
|
internal class UpdateEarnUMInitialStateTransformer(
|
||||||
private val onBackClick: () -> Unit,
|
private val onBackClick: () -> Unit,
|
||||||
private val onNetworkFilterClick: () -> Unit,
|
private val onNetworkFilterClick: () -> Unit,
|
||||||
private val onTypeFilterClick: () -> Unit,
|
private val onTypeFilterClick: () -> Unit,
|
||||||
private val onScroll: () -> Unit,
|
private val onScroll: () -> Unit,
|
||||||
private val onSearchBarClicked: () -> Unit,
|
|
||||||
) : EarnUMTransformer {
|
) : EarnUMTransformer {
|
||||||
|
|
||||||
override fun transform(prevState: EarnUM): EarnUM {
|
override fun transform(prevState: EarnUM): EarnUM {
|
||||||
|
|
@ -19,10 +15,6 @@ internal class UpdateEarnUMInitialStateTransformer(
|
||||||
onNetworkFilterClick = onNetworkFilterClick,
|
onNetworkFilterClick = onNetworkFilterClick,
|
||||||
onTypeFilterClick = onTypeFilterClick,
|
onTypeFilterClick = onTypeFilterClick,
|
||||||
onSliderScroll = onScroll,
|
onSliderScroll = onScroll,
|
||||||
feedListSearchBar = FeedListSearchBar(
|
|
||||||
onBarClick = onSearchBarClicked,
|
|
||||||
placeholderText = resourceReference(id = R.string.markets_search_title_placeholder),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -22,12 +22,14 @@ import com.tangem.core.ui.components.*
|
||||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||||
import com.tangem.core.ui.components.list.InfiniteListHandler
|
import com.tangem.core.ui.components.list.InfiniteListHandler
|
||||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||||
import com.tangem.core.ui.extensions.*
|
import com.tangem.core.ui.extensions.conditional
|
||||||
|
import com.tangem.core.ui.extensions.conditionalCompose
|
||||||
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||||
import com.tangem.core.ui.res.*
|
import com.tangem.core.ui.res.*
|
||||||
import com.tangem.domain.models.earn.EarnType
|
import com.tangem.domain.models.earn.EarnType
|
||||||
import com.tangem.features.feed.ui.earn.components.*
|
import com.tangem.features.feed.ui.earn.components.*
|
||||||
import com.tangem.features.feed.ui.earn.state.*
|
import com.tangem.features.feed.ui.earn.state.*
|
||||||
import com.tangem.features.feed.ui.feed.state.FeedListSearchBar
|
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
private const val EARN_LOAD_MORE_BUFFER = 3
|
private const val EARN_LOAD_MORE_BUFFER = 3
|
||||||
|
|
@ -663,10 +665,6 @@ private fun previewEarnUM(
|
||||||
onNetworkFilterClick = {},
|
onNetworkFilterClick = {},
|
||||||
onTypeFilterClick = {},
|
onTypeFilterClick = {},
|
||||||
onSliderScroll = {},
|
onSliderScroll = {},
|
||||||
feedListSearchBar = FeedListSearchBar(
|
|
||||||
placeholderText = TextReference.Str("Search tokens & news"),
|
|
||||||
onBarClick = {},
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
private const val PLACEHOLDER_ITEMS_COUNT = 8
|
private const val PLACEHOLDER_ITEMS_COUNT = 8
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package com.tangem.features.feed.ui.earn.state
|
package com.tangem.features.feed.ui.earn.state
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import com.tangem.features.feed.ui.feed.state.FeedListSearchBar
|
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
internal data class EarnUM(
|
internal data class EarnUM(
|
||||||
|
|
@ -12,5 +11,4 @@ internal data class EarnUM(
|
||||||
val onNetworkFilterClick: () -> Unit,
|
val onNetworkFilterClick: () -> Unit,
|
||||||
val onTypeFilterClick: () -> Unit,
|
val onTypeFilterClick: () -> Unit,
|
||||||
val onSliderScroll: () -> Unit,
|
val onSliderScroll: () -> Unit,
|
||||||
val feedListSearchBar: FeedListSearchBar,
|
|
||||||
)
|
)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue