Updated on 2026-08-14
This commit is contained in:
parent
4032360f13
commit
4dc6dffd67
16 changed files with 381 additions and 50 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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") }
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.domain.tokens.model.details
|
||||
|
||||
enum class TokenAction {
|
||||
Receive,
|
||||
Send,
|
||||
Swap,
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.domain.tokens.repository
|
||||
|
||||
interface YieldSupplyWarningsViewedRepository {
|
||||
|
||||
suspend fun getViewedWarnings(): Set<String>
|
||||
|
||||
suspend fun view(symbol: String)
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue