Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-23 18:02:14 +05:00
parent 4032360f13
commit 4dc6dffd67
16 changed files with 381 additions and 50 deletions

View file

@ -24,6 +24,7 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.CurrencyChecksRepository
import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
import com.tangem.domain.tokens.repository.TokenReceiveWarningsViewedRepository
import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository
import com.tangem.domain.tokens.wallet.WalletBalanceFetcher
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.tap.domain.tokens.DefaultTokensFeatureToggles
@ -455,4 +456,21 @@ internal object TokensDomainModule {
): SaveViewedTokenReceiveWarningUseCase {
return SaveViewedTokenReceiveWarningUseCase(tokenReceiveWarningsViewedRepository)
}
@Provides
@Singleton
fun provideNeedShowYieldSupplyDepositedWarningUseCase(
yieldSupplyWarningsViewedRepository: YieldSupplyWarningsViewedRepository,
dispatchers: CoroutineDispatcherProvider,
): NeedShowYieldSupplyDepositedWarningUseCase {
return NeedShowYieldSupplyDepositedWarningUseCase(yieldSupplyWarningsViewedRepository, dispatchers)
}
@Provides
@Singleton
fun provideSaveViewedYieldSupplyWarningUseCase(
yieldSupplyWarningsViewedRepository: YieldSupplyWarningsViewedRepository,
): SaveViewedYieldSupplyWarningUseCase {
return SaveViewedYieldSupplyWarningUseCase(yieldSupplyWarningsViewedRepository)
}
}

View file

@ -129,6 +129,8 @@ object PreferencesKeys {
val WALLETS_NFT_ENABLED_STATES_KEY by lazy { stringPreferencesKey(name = "walletsNftEnabledStates") }
val YIELD_SUPPLY_WARNINGS_STATES_KEY by lazy { stringPreferencesKey(name = "yieldSupplyWarningsStates") }
// region Notifications
val NOTIFICATIONS_APPLICATION_ID_KEY by lazy { stringPreferencesKey(name = "notificationsApplicationId") }

View file

@ -9,6 +9,7 @@ import com.tangem.data.tokens.repository.DefaultCurrenciesRepository
import com.tangem.data.tokens.repository.DefaultCurrencyChecksRepository
import com.tangem.data.tokens.repository.DefaultPolkadotAccountHealthCheckRepository
import com.tangem.data.tokens.repository.DefaultTokenReceiveWarningsViewedRepository
import com.tangem.data.tokens.repository.DefaultYieldSupplyWarningsViewedRepository
import com.tangem.datasource.api.tangemTech.TangemTechApi
import com.tangem.datasource.exchangeservice.swap.ExpressServiceLoader
import com.tangem.datasource.local.preferences.AppPreferencesStore
@ -19,6 +20,7 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.tokens.repository.CurrencyChecksRepository
import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
import com.tangem.domain.tokens.repository.TokenReceiveWarningsViewedRepository
import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
@ -96,4 +98,16 @@ internal object TokensDataModule {
tokenReceiveWarningActionStore = tokenReceiveWarningActionStore,
)
}
@Provides
@Singleton
fun provideDefaultYieldSupplyWarningsViewedRepository(
appPreferencesStore: AppPreferencesStore,
dispatchers: CoroutineDispatcherProvider,
): YieldSupplyWarningsViewedRepository {
return DefaultYieldSupplyWarningsViewedRepository(
appPreferencesStore = appPreferencesStore,
dispatchers = dispatchers,
)
}
}

View file

@ -0,0 +1,36 @@
package com.tangem.data.tokens.repository
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.preferences.PreferencesKeys
import com.tangem.datasource.local.preferences.utils.getObjectSet
import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.withContext
internal class DefaultYieldSupplyWarningsViewedRepository(
private val appPreferencesStore: AppPreferencesStore,
private val dispatchers: CoroutineDispatcherProvider,
) : YieldSupplyWarningsViewedRepository {
override suspend fun getViewedWarnings(): Set<String> = withContext(dispatchers.io) {
appPreferencesStore.getObjectSet<String>(PreferencesKeys.YIELD_SUPPLY_WARNINGS_STATES_KEY).firstOrNull()
?: emptySet()
}
override suspend fun view(symbol: String) = withContext(dispatchers.io) {
appPreferencesStore.editData { mutablePreferences ->
val stored = mutablePreferences.getObjectSet<String>(
PreferencesKeys.YIELD_SUPPLY_WARNINGS_STATES_KEY,
) ?: mutableSetOf()
val updated = stored + symbol
mutablePreferences.setObjectSet<String>(
key = PreferencesKeys.YIELD_SUPPLY_WARNINGS_STATES_KEY,
value = updated,
)
}
return@withContext
}
}

View file

@ -0,0 +1,7 @@
package com.tangem.domain.tokens.model.details
enum class TokenAction {
Receive,
Send,
Swap,
}

View file

@ -0,0 +1,19 @@
package com.tangem.domain.tokens
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
class NeedShowYieldSupplyDepositedWarningUseCase(
private val yieldSupplyWarningsViewedRepository: YieldSupplyWarningsViewedRepository,
private val dispatchers: CoroutineDispatcherProvider,
) {
suspend operator fun invoke(cryptoCurrencyStatus: CryptoCurrencyStatus?): Boolean = withContext(dispatchers.io) {
val hasActiveLending = cryptoCurrencyStatus?.value?.yieldSupplyStatus?.isActive == true
if (!hasActiveLending) return@withContext false
val showedWarnings = yieldSupplyWarningsViewedRepository.getViewedWarnings()
return@withContext !showedWarnings.contains(cryptoCurrencyStatus?.currency?.name)
}
}

View file

@ -0,0 +1,11 @@
package com.tangem.domain.tokens
import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository
class SaveViewedYieldSupplyWarningUseCase(
private val yieldSupplyWarningsViewedRepository: YieldSupplyWarningsViewedRepository,
) {
suspend operator fun invoke(symbol: String) {
yieldSupplyWarningsViewedRepository.view(symbol)
}
}

View file

@ -0,0 +1,8 @@
package com.tangem.domain.tokens.repository
interface YieldSupplyWarningsViewedRepository {
suspend fun getViewedWarnings(): Set<String>
suspend fun view(symbol: String)
}

View file

@ -0,0 +1,107 @@
package com.tangem.domain.tokens
import com.google.common.truth.Truth.assertThat
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.NetworkAddress
import com.tangem.domain.models.serialization.SerializedBigDecimal
import com.tangem.domain.models.yield.supply.YieldSupplyStatus
import com.tangem.domain.tokens.repository.YieldSupplyWarningsViewedRepository
import com.tangem.domain.tokens.mock.MockTokens
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.impl.annotations.RelaxedMockK
import io.mockk.junit5.MockKExtension
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@OptIn(ExperimentalCoroutinesApi::class)
@ExtendWith(MockKExtension::class)
class NeedShowYieldSupplyDepositedWarningUseCaseTest {
@RelaxedMockK
private lateinit var repository: YieldSupplyWarningsViewedRepository
private lateinit var dispatchers: TestingCoroutineDispatcherProvider
@BeforeEach
fun setup() {
dispatchers = TestingCoroutineDispatcherProvider()
}
@Test
fun `GIVEN null status WHEN invoke THEN returns false`() = runTest {
val useCase = NeedShowYieldSupplyDepositedWarningUseCase(repository, dispatchers)
val result = useCase.invoke(null)
assertThat(result).isFalse()
coVerify(exactly = 0) { repository.getViewedWarnings() }
}
@Test
fun `GIVEN inactive lending WHEN invoke THEN returns false`() = runTest {
val useCase = NeedShowYieldSupplyDepositedWarningUseCase(repository, dispatchers)
val status = createStatus(isActive = false)
val result = useCase.invoke(status)
assertThat(result).isFalse()
coVerify(exactly = 0) { repository.getViewedWarnings() }
}
@Test
fun `GIVEN active lending and not viewed WHEN invoke THEN returns true`() = runTest {
val useCase = NeedShowYieldSupplyDepositedWarningUseCase(repository, dispatchers)
val status = createStatus(isActive = true)
coEvery { repository.getViewedWarnings() } returns emptySet()
val result = useCase.invoke(status)
assertThat(result).isTrue()
coVerify(exactly = 1) { repository.getViewedWarnings() }
}
@Test
fun `GIVEN active lending and already viewed WHEN invoke THEN returns false`() = runTest {
val useCase = NeedShowYieldSupplyDepositedWarningUseCase(repository, dispatchers)
val status = createStatus(isActive = true)
coEvery { repository.getViewedWarnings() } returns setOf(status.currency.name)
val result = useCase.invoke(status)
assertThat(result).isFalse()
coVerify(exactly = 1) { repository.getViewedWarnings() }
}
private fun createStatus(isActive: Boolean): CryptoCurrencyStatus {
val currency = MockTokens.token1
val yieldSupplyStatus = YieldSupplyStatus(
isActive = isActive,
isInitialized = true,
isAllowedToSpend = true,
)
val value = CryptoCurrencyStatus.NoQuote(
amount = SerializedBigDecimal.ZERO,
yieldBalance = null,
yieldSupplyStatus = yieldSupplyStatus,
hasCurrentNetworkTransactions = false,
pendingTransactions = emptySet(),
networkAddress = NetworkAddress.Single(
defaultAddress = NetworkAddress.Address(
value = "address",
type = NetworkAddress.Address.Type.Primary,
),
),
sources = CryptoCurrencyStatus.Sources(),
)
return CryptoCurrencyStatus(
currency = currency,
value = value,
)
}
}

View file

@ -1,5 +1,6 @@
plugins {
alias(deps.plugins.android.library)
alias(deps.plugins.kotlin.serialization)
alias(deps.plugins.kotlin.android)
alias(deps.plugins.kotlin.kapt)
alias(deps.plugins.hilt.android)

View file

@ -15,15 +15,16 @@ import com.tangem.core.decompose.context.childByContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.components.NavigationBar3ButtonsScrim
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsModel
import com.tangem.feature.tokendetails.presentation.tokendetails.route.TokenDetailsBottomSheetConfig
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.TokenDetailsScreen
import com.tangem.features.markets.token.block.TokenMarketBlockComponent
import com.tangem.features.tokendetails.TokenDetailsComponent
import com.tangem.features.tokenreceive.TokenReceiveComponent
import com.tangem.features.txhistory.component.TxHistoryComponent
import com.tangem.features.yield.supply.api.YieldSupplyComponent
import com.tangem.features.yield.supply.api.YieldSupplyDepositedWarningComponent
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@ -35,6 +36,7 @@ internal class DefaultTokenDetailsComponent @AssistedInject constructor(
tokenMarketBlockComponentFactory: TokenMarketBlockComponent.Factory,
txHistoryComponentFactory: TxHistoryComponent.Factory,
private val tokenReceiveComponentFactory: TokenReceiveComponent.Factory,
private val yieldSupplyWarningComponentFactory: YieldSupplyDepositedWarningComponent.Factory,
yieldSupplyComponentFactory: YieldSupplyComponent.Factory,
) : TokenDetailsComponent, AppComponentContext by appComponentContext {
@ -50,7 +52,7 @@ internal class DefaultTokenDetailsComponent @AssistedInject constructor(
private val bottomSheetSlot = childSlot(
source = model.bottomSheetNavigation,
serializer = TokenReceiveConfig.serializer(),
serializer = TokenDetailsBottomSheetConfig.serializer(),
handleBackButton = false,
childFactory = ::bottomSheetChild,
)
@ -98,15 +100,26 @@ internal class DefaultTokenDetailsComponent @AssistedInject constructor(
}
private fun bottomSheetChild(
config: TokenReceiveConfig,
route: TokenDetailsBottomSheetConfig,
componentContext: ComponentContext,
): ComposableBottomSheetComponent = tokenReceiveComponentFactory.create(
context = childByContext(componentContext),
params = TokenReceiveComponent.Params(
config = config,
onDismiss = model.bottomSheetNavigation::dismiss,
),
)
): ComposableBottomSheetComponent = when (route) {
is TokenDetailsBottomSheetConfig.Receive -> tokenReceiveComponentFactory.create(
context = childByContext(componentContext),
params = TokenReceiveComponent.Params(
config = route.tokenReceiveConfig,
onDismiss = model.bottomSheetNavigation::dismiss,
),
)
is TokenDetailsBottomSheetConfig.YieldSupplyWarning -> yieldSupplyWarningComponentFactory.create(
context = childByContext(componentContext),
params = YieldSupplyDepositedWarningComponent.Params(
cryptoCurrency = route.cryptoCurrency,
onDismiss = model.bottomSheetNavigation::dismiss,
modelCallback = model,
tokenAction = route.tokenAction,
),
)
}
@AssistedFactory
interface Factory : TokenDetailsComponent.Factory {

View file

@ -5,6 +5,7 @@ import arrow.core.getOrElse
import arrow.core.merge
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
import com.arkivanov.decompose.router.slot.dismiss
import com.tangem.blockchain.common.address.AddressType
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
@ -58,6 +59,7 @@ import com.tangem.domain.tokens.model.TokenActionsState
import com.tangem.domain.tokens.model.analytics.*
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.toReasonAnalyticsText
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.DetailsScreenOpened.TokenBalance
import com.tangem.domain.tokens.model.details.TokenAction
import com.tangem.domain.transaction.error.AssociateAssetError
import com.tangem.domain.transaction.error.IncompleteTransactionError
import com.tangem.domain.transaction.error.OpenTrustlineError
@ -72,6 +74,7 @@ import com.tangem.feature.tokendetails.deeplink.TokenDetailsDeepLinkActionListen
import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter
import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.TokenDetailsCurrencyStatusAnalyticsSender
import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.TokenDetailsNotificationsAnalyticsSender
import com.tangem.feature.tokendetails.presentation.tokendetails.route.TokenDetailsBottomSheetConfig
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenBalanceSegmentedButtonConfig
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsStateFactory
@ -81,6 +84,7 @@ import com.tangem.features.tokendetails.TokenDetailsComponent
import com.tangem.features.tokendetails.impl.R
import com.tangem.features.tokenreceive.TokenReceiveFeatureToggle
import com.tangem.features.txhistory.entity.TxHistoryContentUpdateEmitter
import com.tangem.features.yield.supply.api.YieldSupplyDepositedWarningComponent
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import com.tangem.utils.Provider
import com.tangem.utils.coroutines.*
@ -139,7 +143,10 @@ internal class TokenDetailsModel @Inject constructor(
private val getViewedTokenReceiveWarningUseCase: GetViewedTokenReceiveWarningUseCase,
private val getEnsNameUseCase: GetEnsNameUseCase,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
) : Model(), TokenDetailsClickIntents {
private val saveViewedYieldSupplyWarningUseCase: SaveViewedYieldSupplyWarningUseCase,
private val saveViewedTokenReceiveWarningUseCase: SaveViewedTokenReceiveWarningUseCase,
private val needShowYieldSupplyDepositedWarningUseCase: NeedShowYieldSupplyDepositedWarningUseCase,
) : Model(), TokenDetailsClickIntents, YieldSupplyDepositedWarningComponent.ModelCallback {
private val params = paramsContainer.require<TokenDetailsComponent.Params>()
private val userWalletId: UserWalletId = params.userWalletId
@ -162,7 +169,7 @@ internal class TokenDetailsModel @Inject constructor(
/** Transaction id to check for status */
private val waitForFirstExpressStatusEmmit = MutableStateFlow(false)
val bottomSheetNavigation: SlotNavigation<TokenReceiveConfig> = SlotNavigation()
val bottomSheetNavigation: SlotNavigation<TokenDetailsBottomSheetConfig> = SlotNavigation()
private val stateFactory = TokenDetailsStateFactory(
currentStateProvider = Provider { uiState.value },
@ -527,8 +534,18 @@ internal class TokenDetailsModel @Inject constructor(
if (handleUnavailabilityReason(unavailabilityReason = unavailabilityReason)) {
return
}
sendCurrency()
modelScope.launch {
if (needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus)) {
bottomSheetNavigation.activate(
configuration = TokenDetailsBottomSheetConfig.YieldSupplyWarning(
cryptoCurrency = cryptoCurrency,
tokenAction = TokenAction.Send,
),
)
} else {
sendCurrency()
}
}
}
private fun sendCurrency() {
@ -563,26 +580,15 @@ internal class TokenDetailsModel @Inject constructor(
}
modelScope.launch {
if (tokenReceiveFeatureToggle.isNewTokenReceiveEnabled) {
if (needShowYieldSupplyWarning()) {
bottomSheetNavigation.activate(
configuration = configureReceiveAddresses(addresses = networkAddress),
configuration = TokenDetailsBottomSheetConfig.YieldSupplyWarning(
cryptoCurrency = cryptoCurrency,
tokenAction = TokenAction.Receive,
),
)
} else {
analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ReceiveScreenOpened(cryptoCurrency.symbol))
internalUiState.value = stateFactory.getStateWithReceiveBottomSheet(
currency = cryptoCurrency,
networkAddress = networkAddress,
onCopyClick = {
analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ButtonCopyAddress(cryptoCurrency.symbol))
clipboardManager.setText(text = it, isSensitive = true)
},
onShareClick = {
analyticsEventsHandler.send(
TokenReceiveAnalyticsEvent.ButtonShareAddress(cryptoCurrency.symbol),
)
shareManager.shareText(text = it)
},
)
navigateToReceive()
}
}
}
@ -656,13 +662,24 @@ internal class TokenDetailsModel @Inject constructor(
return
}
appRouter.push(
AppRoute.Swap(
currencyFrom = cryptoCurrency,
userWalletId = userWalletId,
screenSource = AnalyticsParam.ScreensSources.Token.value,
),
)
modelScope.launch {
if (needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus)) {
bottomSheetNavigation.activate(
configuration = TokenDetailsBottomSheetConfig.YieldSupplyWarning(
cryptoCurrency = cryptoCurrency,
tokenAction = TokenAction.Swap,
),
)
} else {
appRouter.push(
AppRoute.Swap(
currencyFrom = cryptoCurrency,
userWalletId = userWalletId,
screenSource = AnalyticsParam.ScreensSources.Token.value,
),
)
}
}
}
override fun onDismissDialog() {
@ -1040,7 +1057,7 @@ internal class TokenDetailsModel @Inject constructor(
.launchIn(modelScope)
}
private suspend fun configureReceiveAddresses(addresses: NetworkAddress): TokenReceiveConfig {
private suspend fun configureReceiveAddresses(addresses: NetworkAddress): TokenDetailsBottomSheetConfig {
val ensName = getEnsNameUseCase.invoke(
userWalletId = userWalletId,
network = cryptoCurrency.network,
@ -1069,12 +1086,14 @@ internal class TokenDetailsModel @Inject constructor(
}
}
return TokenReceiveConfig(
shouldShowWarning = cryptoCurrency.name !in getViewedTokenReceiveWarningUseCase(),
cryptoCurrency = cryptoCurrency,
userWalletId = userWalletId,
showMemoDisclaimer = cryptoCurrency.network.transactionExtrasType != Network.TransactionExtrasType.NONE,
receiveAddress = receiveAddresses,
return TokenDetailsBottomSheetConfig.Receive(
TokenReceiveConfig(
shouldShowWarning = cryptoCurrency.name !in getViewedTokenReceiveWarningUseCase(),
cryptoCurrency = cryptoCurrency,
userWalletId = userWalletId,
showMemoDisclaimer = cryptoCurrency.network.transactionExtrasType != Network.TransactionExtrasType.NONE,
receiveAddress = receiveAddresses,
),
)
}
@ -1115,6 +1134,59 @@ internal class TokenDetailsModel @Inject constructor(
isBalanceLoadedEventSent = true
}
private suspend fun needShowYieldSupplyWarning(): Boolean {
return yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled &&
needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus)
}
override fun onYieldSupplyWarningAcknowledged(tokenAction: TokenAction) {
bottomSheetNavigation.dismiss()
modelScope.launch {
saveViewedYieldSupplyWarningUseCase(cryptoCurrency.name)
if (tokenAction == TokenAction.Receive) {
saveViewedTokenReceiveWarningUseCase(cryptoCurrency.name)
}
when (tokenAction) {
TokenAction.Receive -> navigateToReceive()
TokenAction.Send -> sendCurrency()
TokenAction.Swap -> appRouter.push(
AppRoute.Swap(
currencyFrom = cryptoCurrency,
userWalletId = userWalletId,
screenSource = AnalyticsParam.ScreensSources.Token.value,
),
)
}
}
}
private fun navigateToReceive() {
val networkAddress = cryptoCurrencyStatus?.value?.networkAddress ?: return
if (tokenReceiveFeatureToggle.isNewTokenReceiveEnabled) {
modelScope.launch {
bottomSheetNavigation.activate(
configuration = configureReceiveAddresses(addresses = networkAddress),
)
}
} else {
analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ReceiveScreenOpened(cryptoCurrency.symbol))
internalUiState.value = stateFactory.getStateWithReceiveBottomSheet(
currency = cryptoCurrency,
networkAddress = networkAddress,
onCopyClick = {
analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ButtonCopyAddress(cryptoCurrency.symbol))
clipboardManager.setText(text = it, isSensitive = true)
},
onShareClick = {
analyticsEventsHandler.send(
TokenReceiveAnalyticsEvent.ButtonShareAddress(cryptoCurrency.symbol),
)
shareManager.shareText(text = it)
},
)
}
}
private companion object {
const val EXPRESS_STATUS_UPDATE_DELAY = 10_000L
}

View file

@ -0,0 +1,20 @@
package com.tangem.feature.tokendetails.presentation.tokendetails.route
import com.tangem.core.decompose.navigation.Route
import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.tokens.model.details.TokenAction
import kotlinx.serialization.Serializable
@Serializable
sealed class TokenDetailsBottomSheetConfig : Route {
@Serializable
data class Receive(val tokenReceiveConfig: TokenReceiveConfig) : TokenDetailsBottomSheetConfig()
@Serializable
data class YieldSupplyWarning(
val cryptoCurrency: CryptoCurrency,
val tokenAction: TokenAction,
) : TokenDetailsBottomSheetConfig()
}

View file

@ -4,17 +4,19 @@ import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.tokens.model.details.TokenAction
interface YieldSupplyDepositedWarningComponent : ComposableBottomSheetComponent {
data class Params(
val cryptoCurrency: CryptoCurrency,
val tokenAction: TokenAction,
val modelCallback: ModelCallback,
val onDismiss: () -> Unit,
)
interface ModelCallback {
fun onYieldSupplyWarningAcknowledged()
fun onYieldSupplyWarningAcknowledged(tokenAction: TokenAction)
}
interface Factory : ComponentFactory<Params, YieldSupplyDepositedWarningComponent> {

View file

@ -28,7 +28,9 @@ internal class YieldSupplyDepositedWarningModel @Inject constructor(
field = MutableStateFlow(
YieldSupplyDepositedWarningUM(
iconState = iconStateConverter.convert(params.cryptoCurrency),
onWarningAcknowledged = params.modelCallback::onYieldSupplyWarningAcknowledged,
onWarningAcknowledged = {
params.modelCallback.onYieldSupplyWarningAcknowledged(params.tokenAction)
},
network = params.cryptoCurrency.name,
),
)

View file

@ -40,7 +40,7 @@ internal fun YieldSupplyDepositedWarningContent(warningUM: YieldSupplyDepositedW
onDismissRequest = onDismiss,
content = TangemBottomSheetConfigContent.Empty,
),
containerColor = TangemTheme.colors.background.primary,
containerColor = TangemTheme.colors.background.tertiary,
onBack = null,
title = {
TangemModalBottomSheetTitle(
@ -57,7 +57,7 @@ internal fun YieldSupplyDepositedWarningContent(warningUM: YieldSupplyDepositedW
.padding(horizontal = 16.dp)
.fillMaxWidth(),
text = stringResourceSafe(CoreUiR.string.balance_hidden_got_it_button),
onClick = onDismiss,
onClick = warningUM.onWarningAcknowledged,
)
},
)
@ -68,7 +68,6 @@ private fun Content(warningUM: YieldSupplyDepositedWarningUM) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(color = TangemTheme.colors.background.primary)
.padding(
start = 16.dp,
end = 16.dp,