Updated on 2026-08-14
This commit is contained in:
parent
a3f7c6dcc4
commit
99dfa2a392
12 changed files with 189 additions and 36 deletions
|
|
@ -4,11 +4,11 @@ import android.content.Context
|
||||||
import androidx.datastore.core.DataStoreFactory
|
import androidx.datastore.core.DataStoreFactory
|
||||||
import androidx.datastore.dataStoreFile
|
import androidx.datastore.dataStoreFile
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
|
import com.tangem.datasource.api.tangemTech.models.YieldMarketsResponse
|
||||||
import com.tangem.datasource.local.yieldsupply.DefaultYieldMarketsStore
|
import com.tangem.datasource.local.yieldsupply.DefaultYieldMarketsStore
|
||||||
import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
|
import com.tangem.datasource.local.yieldsupply.YieldMarketsStore
|
||||||
import com.tangem.datasource.utils.MoshiDataStoreSerializer
|
import com.tangem.datasource.utils.MoshiDataStoreSerializer
|
||||||
import com.tangem.datasource.utils.listTypes
|
import com.tangem.datasource.utils.listTypes
|
||||||
import com.tangem.domain.yield.supply.models.YieldMarketToken
|
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
|
|
@ -34,7 +34,7 @@ object YieldSupplyModule {
|
||||||
persistenceStore = DataStoreFactory.create(
|
persistenceStore = DataStoreFactory.create(
|
||||||
serializer = MoshiDataStoreSerializer(
|
serializer = MoshiDataStoreSerializer(
|
||||||
moshi = moshi,
|
moshi = moshi,
|
||||||
types = listTypes<YieldMarketToken>(),
|
types = listTypes<YieldMarketsResponse.MarketDto>(),
|
||||||
defaultValue = emptyList(),
|
defaultValue = emptyList(),
|
||||||
),
|
),
|
||||||
produceFile = { context.dataStoreFile(fileName = "yield_markets_cache") },
|
produceFile = { context.dataStoreFile(fileName = "yield_markets_cache") },
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
package com.tangem.datasource.local.yieldsupply
|
package com.tangem.datasource.local.yieldsupply
|
||||||
|
|
||||||
import androidx.datastore.core.DataStore
|
import androidx.datastore.core.DataStore
|
||||||
import com.tangem.domain.yield.supply.models.YieldMarketToken
|
import com.tangem.datasource.api.tangemTech.models.YieldMarketsResponse
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.firstOrNull
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
|
|
||||||
internal class DefaultYieldMarketsStore(
|
internal class DefaultYieldMarketsStore(
|
||||||
private val persistenceStore: DataStore<List<YieldMarketToken>>,
|
private val persistenceStore: DataStore<List<YieldMarketsResponse.MarketDto>>,
|
||||||
) : YieldMarketsStore {
|
) : YieldMarketsStore {
|
||||||
|
|
||||||
override fun get(): Flow<List<YieldMarketToken>> = persistenceStore.data
|
override fun get(): Flow<List<YieldMarketsResponse.MarketDto>> = persistenceStore.data
|
||||||
|
|
||||||
override suspend fun getSyncOrNull(): List<YieldMarketToken>? {
|
override suspend fun getSyncOrNull(): List<YieldMarketsResponse.MarketDto>? {
|
||||||
return persistenceStore.data.firstOrNull()
|
return persistenceStore.data.firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun store(items: List<YieldMarketToken>) {
|
override suspend fun store(items: List<YieldMarketsResponse.MarketDto>) {
|
||||||
persistenceStore.updateData { _ -> items }
|
persistenceStore.updateData { _ -> items }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
package com.tangem.datasource.local.yieldsupply
|
package com.tangem.datasource.local.yieldsupply
|
||||||
|
|
||||||
import com.tangem.domain.yield.supply.models.YieldMarketToken
|
import com.tangem.datasource.api.tangemTech.models.YieldMarketsResponse
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface YieldMarketsStore {
|
interface YieldMarketsStore {
|
||||||
|
|
||||||
fun get(): Flow<List<YieldMarketToken>>
|
fun get(): Flow<List<YieldMarketsResponse.MarketDto>>
|
||||||
|
|
||||||
suspend fun getSyncOrNull(): List<YieldMarketToken>?
|
suspend fun getSyncOrNull(): List<YieldMarketsResponse.MarketDto>?
|
||||||
|
|
||||||
suspend fun store(items: List<YieldMarketToken>)
|
suspend fun store(items: List<YieldMarketsResponse.MarketDto>)
|
||||||
}
|
}
|
||||||
|
|
@ -27,18 +27,20 @@ internal class DefaultYieldSupplyMarketRepository(
|
||||||
) : YieldSupplyMarketRepository {
|
) : YieldSupplyMarketRepository {
|
||||||
|
|
||||||
override suspend fun getCachedMarkets(): List<YieldMarketToken>? = withContext(dispatchers.io) {
|
override suspend fun getCachedMarkets(): List<YieldMarketToken>? = withContext(dispatchers.io) {
|
||||||
store.getSyncOrNull()?.enrichNetworkIds()
|
val cache = store.getSyncOrNull().orEmpty()
|
||||||
|
val domain = cache.map(YieldMarketTokenConverter::convert)
|
||||||
|
domain.enrichNetworkIds()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateMarkets(): List<YieldMarketToken> = withContext(dispatchers.io) {
|
override suspend fun updateMarkets(): List<YieldMarketToken> = withContext(dispatchers.io) {
|
||||||
val response = yieldSupplyApi.getYieldMarkets().getOrThrow()
|
val response = yieldSupplyApi.getYieldMarkets().getOrThrow()
|
||||||
val domain = response.marketDtos.map(YieldMarketTokenConverter::convert)
|
val domain = response.marketDtos.map(YieldMarketTokenConverter::convert)
|
||||||
store.store(domain)
|
store.store(response.marketDtos)
|
||||||
domain
|
domain
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMarketsFlow(): Flow<List<YieldMarketToken>> = store.get().map {
|
override fun getMarketsFlow(): Flow<List<YieldMarketToken>> = store.get().map {
|
||||||
it.enrichNetworkIds()
|
it.map(YieldMarketTokenConverter::convert).enrichNetworkIds()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getTokenStatus(cryptoCurrencyToken: CryptoCurrency.Token): YieldMarketTokenStatus {
|
override suspend fun getTokenStatus(cryptoCurrencyToken: CryptoCurrency.Token): YieldMarketTokenStatus {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.tangem.features.yield.supply.impl.main.entity
|
||||||
|
|
||||||
|
internal enum class LoadingStatusMode {
|
||||||
|
Initial,
|
||||||
|
LoadApy,
|
||||||
|
}
|
||||||
|
|
@ -8,8 +8,6 @@ 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
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
|
||||||
import com.tangem.core.ui.extensions.wrappedList
|
|
||||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||||
import com.tangem.domain.models.currency.CryptoCurrency
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
|
|
@ -20,8 +18,10 @@ import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
|
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
|
||||||
import com.tangem.features.yield.supply.api.YieldSupplyComponent
|
import com.tangem.features.yield.supply.api.YieldSupplyComponent
|
||||||
import com.tangem.features.yield.supply.impl.R
|
|
||||||
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
|
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
|
||||||
|
import com.tangem.features.yield.supply.impl.main.entity.LoadingStatusMode
|
||||||
|
import com.tangem.features.yield.supply.impl.main.model.transformers.YieldSupplyTokenStatusFailureTransformer
|
||||||
|
import com.tangem.features.yield.supply.impl.main.model.transformers.YieldSupplyTokenStatusSuccessTransformer
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
import com.tangem.utils.coroutines.DelayedWork
|
import com.tangem.utils.coroutines.DelayedWork
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
@ -29,6 +29,7 @@ import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import com.tangem.utils.transformer.update
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
|
|
@ -102,24 +103,20 @@ internal class YieldSupplyModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadTokenStatus(cryptoCurrency: CryptoCurrency.Token) {
|
private fun loadTokenStatus(mode: LoadingStatusMode) {
|
||||||
|
val cryptoCurrencyToken = cryptoCurrency as? CryptoCurrency.Token ?: return
|
||||||
modelScope.launch(dispatchers.default) {
|
modelScope.launch(dispatchers.default) {
|
||||||
yieldSupplyGetTokenStatusUseCase(cryptoCurrency)
|
yieldSupplyGetTokenStatusUseCase(cryptoCurrencyToken)
|
||||||
.onRight { tokenStatus ->
|
.onRight { tokenStatus ->
|
||||||
val newState = if (tokenStatus.isActive) {
|
uiState.update(
|
||||||
YieldSupplyUM.Initial(
|
YieldSupplyTokenStatusSuccessTransformer(
|
||||||
title = resourceReference(
|
tokenStatus = tokenStatus,
|
||||||
id = R.string.yield_module_token_details_earn_notification_title,
|
onStartEarningClick = ::onStartEarningClick,
|
||||||
formatArgs = wrappedList(tokenStatus.apy),
|
mode = mode,
|
||||||
),
|
),
|
||||||
onClick = ::onStartEarningClick,
|
)
|
||||||
)
|
|
||||||
} else {
|
|
||||||
YieldSupplyUM.Unavailable
|
|
||||||
}
|
|
||||||
uiState.update { newState }
|
|
||||||
}.onLeft {
|
}.onLeft {
|
||||||
uiState.update { YieldSupplyUM.Unavailable }
|
uiState.update(YieldSupplyTokenStatusFailureTransformer(mode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -178,8 +175,10 @@ internal class YieldSupplyModel @Inject constructor(
|
||||||
|
|
||||||
uiState.update { yieldSupplyUM }
|
uiState.update { yieldSupplyUM }
|
||||||
|
|
||||||
if (yieldSupplyUM is YieldSupplyUM.Loading) {
|
when (yieldSupplyUM) {
|
||||||
(cryptoCurrency as? CryptoCurrency.Token)?.let(::loadTokenStatus)
|
is YieldSupplyUM.Loading -> loadTokenStatus(LoadingStatusMode.Initial)
|
||||||
|
is YieldSupplyUM.Content -> loadTokenStatus(LoadingStatusMode.LoadApy)
|
||||||
|
else -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.tangem.features.yield.supply.impl.main.model.transformers
|
||||||
|
|
||||||
|
import com.tangem.features.yield.supply.impl.main.entity.LoadingStatusMode
|
||||||
|
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
|
||||||
|
import com.tangem.utils.transformer.Transformer
|
||||||
|
|
||||||
|
internal class YieldSupplyTokenStatusFailureTransformer(
|
||||||
|
private val mode: LoadingStatusMode,
|
||||||
|
) : Transformer<YieldSupplyUM> {
|
||||||
|
|
||||||
|
override fun transform(prevState: YieldSupplyUM): YieldSupplyUM {
|
||||||
|
return when (mode) {
|
||||||
|
LoadingStatusMode.Initial -> YieldSupplyUM.Unavailable
|
||||||
|
LoadingStatusMode.LoadApy -> prevState // TODO apply correct UI
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.tangem.features.yield.supply.impl.main.model.transformers
|
||||||
|
|
||||||
|
import com.tangem.domain.yield.supply.models.YieldMarketTokenStatus
|
||||||
|
import com.tangem.features.yield.supply.impl.R
|
||||||
|
import com.tangem.features.yield.supply.impl.main.entity.LoadingStatusMode
|
||||||
|
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
|
||||||
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
import com.tangem.core.ui.extensions.wrappedList
|
||||||
|
import com.tangem.utils.transformer.Transformer
|
||||||
|
|
||||||
|
internal class YieldSupplyTokenStatusSuccessTransformer(
|
||||||
|
private val tokenStatus: YieldMarketTokenStatus,
|
||||||
|
private val onStartEarningClick: () -> Unit,
|
||||||
|
private val mode: LoadingStatusMode,
|
||||||
|
) : Transformer<YieldSupplyUM> {
|
||||||
|
|
||||||
|
override fun transform(prevState: YieldSupplyUM): YieldSupplyUM {
|
||||||
|
if (!tokenStatus.isActive) return YieldSupplyUM.Unavailable
|
||||||
|
|
||||||
|
return when (mode) {
|
||||||
|
LoadingStatusMode.Initial -> {
|
||||||
|
YieldSupplyUM.Initial(
|
||||||
|
title = resourceReference(
|
||||||
|
id = R.string.yield_module_token_details_earn_notification_title,
|
||||||
|
formatArgs = wrappedList(tokenStatus.apy),
|
||||||
|
),
|
||||||
|
onClick = onStartEarningClick,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
LoadingStatusMode.LoadApy -> {
|
||||||
|
if (prevState is YieldSupplyUM.Content) {
|
||||||
|
prevState.copy(
|
||||||
|
rewardsApy = stringReference("${tokenStatus.apy}%"),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
prevState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,16 +8,19 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.tangem.core.decompose.context.AppComponentContext
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
|
import com.tangem.core.decompose.context.child
|
||||||
import com.tangem.core.decompose.model.getOrCreateModel
|
import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
import com.tangem.core.ui.components.SecondaryButton
|
import com.tangem.core.ui.components.SecondaryButton
|
||||||
import com.tangem.core.ui.decompose.ComposableModularContentComponent
|
import com.tangem.core.ui.decompose.ComposableModularContentComponent
|
||||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||||
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||||
import com.tangem.domain.models.wallet.UserWallet
|
import com.tangem.domain.models.wallet.UserWallet
|
||||||
import com.tangem.features.yield.supply.impl.subcomponents.active.model.YieldSupplyActiveModel
|
import com.tangem.features.yield.supply.impl.subcomponents.active.model.YieldSupplyActiveModel
|
||||||
import com.tangem.features.yield.supply.impl.subcomponents.active.ui.YieldSupplyActiveContent
|
import com.tangem.features.yield.supply.impl.subcomponents.active.ui.YieldSupplyActiveContent
|
||||||
import com.tangem.features.yield.supply.impl.subcomponents.active.ui.YieldSupplyActiveTitle
|
import com.tangem.features.yield.supply.impl.subcomponents.active.ui.YieldSupplyActiveTitle
|
||||||
import com.tangem.features.yield.supply.impl.R
|
import com.tangem.features.yield.supply.impl.R
|
||||||
|
import com.tangem.features.yield.supply.impl.chart.DefaultYieldSupplyChartComponent
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
internal class YieldSupplyActiveComponent(
|
internal class YieldSupplyActiveComponent(
|
||||||
|
|
@ -26,6 +29,12 @@ internal class YieldSupplyActiveComponent(
|
||||||
) : ComposableModularContentComponent, AppComponentContext by appComponentContext {
|
) : ComposableModularContentComponent, AppComponentContext by appComponentContext {
|
||||||
|
|
||||||
private val model: YieldSupplyActiveModel = getOrCreateModel(params = params)
|
private val model: YieldSupplyActiveModel = getOrCreateModel(params = params)
|
||||||
|
private val chartComponent = DefaultYieldSupplyChartComponent(
|
||||||
|
appComponentContext = child("chartComponent"),
|
||||||
|
params = DefaultYieldSupplyChartComponent.Params(
|
||||||
|
cryptoCurrency = params.cryptoCurrencyStatusFlow.value.currency as CryptoCurrency.Token,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Title() {
|
override fun Title() {
|
||||||
|
|
@ -37,7 +46,12 @@ internal class YieldSupplyActiveComponent(
|
||||||
val state by model.uiState.collectAsStateWithLifecycle()
|
val state by model.uiState.collectAsStateWithLifecycle()
|
||||||
val isBalanceHidden by params.isBalanceHiddenFlow.collectAsStateWithLifecycle()
|
val isBalanceHidden by params.isBalanceHiddenFlow.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
YieldSupplyActiveContent(state = state, isBalanceHidden = isBalanceHidden, modifier = Modifier)
|
YieldSupplyActiveContent(
|
||||||
|
state = state,
|
||||||
|
isBalanceHidden = isBalanceHidden,
|
||||||
|
chartComponent = chartComponent,
|
||||||
|
modifier = Modifier,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,5 @@ internal data class YieldSupplyActiveContentUM(
|
||||||
val subtitle: TextReference,
|
val subtitle: TextReference,
|
||||||
val subtitleLink: TextReference,
|
val subtitleLink: TextReference,
|
||||||
val notificationUM: NotificationUM?,
|
val notificationUM: NotificationUM?,
|
||||||
|
val apy: TextReference? = null,
|
||||||
)
|
)
|
||||||
|
|
@ -5,18 +5,22 @@ 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
|
||||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||||
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringReference
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
import com.tangem.core.ui.extensions.wrappedList
|
import com.tangem.core.ui.extensions.wrappedList
|
||||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||||
import com.tangem.core.ui.format.bigdecimal.format
|
import com.tangem.core.ui.format.bigdecimal.format
|
||||||
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetProtocolBalanceUseCase
|
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetProtocolBalanceUseCase
|
||||||
|
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
|
||||||
import com.tangem.features.yield.supply.impl.R
|
import com.tangem.features.yield.supply.impl.R
|
||||||
import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveComponent
|
import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveComponent
|
||||||
import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM
|
import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ModelScoped
|
@ModelScoped
|
||||||
|
|
@ -24,6 +28,7 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
||||||
paramsContainer: ParamsContainer,
|
paramsContainer: ParamsContainer,
|
||||||
override val dispatchers: CoroutineDispatcherProvider,
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
private val yieldSupplyGetProtocolBalanceUseCase: YieldSupplyGetProtocolBalanceUseCase,
|
private val yieldSupplyGetProtocolBalanceUseCase: YieldSupplyGetProtocolBalanceUseCase,
|
||||||
|
private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase,
|
||||||
) : Model() {
|
) : Model() {
|
||||||
|
|
||||||
private val params: YieldSupplyActiveComponent.Params = paramsContainer.require()
|
private val params: YieldSupplyActiveComponent.Params = paramsContainer.require()
|
||||||
|
|
@ -87,6 +92,8 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadApy()
|
||||||
|
|
||||||
uiState.update {
|
uiState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
notificationUM = approvalNotification,
|
notificationUM = approvalNotification,
|
||||||
|
|
@ -104,6 +111,21 @@ internal class YieldSupplyActiveModel @Inject constructor(
|
||||||
.launchIn(modelScope)
|
.launchIn(modelScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun loadApy() {
|
||||||
|
val cryptoCurrencyToken = cryptoCurrency as? CryptoCurrency.Token ?: return
|
||||||
|
modelScope.launch(dispatchers.default) {
|
||||||
|
yieldSupplyGetTokenStatusUseCase(cryptoCurrencyToken).onRight { tokenStatus ->
|
||||||
|
uiState.update {
|
||||||
|
it.copy(
|
||||||
|
apy = TextReference.Str("${tokenStatus.apy}%"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.onLeft {
|
||||||
|
Timber.e("Error loading token status")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val AAVEV3_PREFIX = "a"
|
const val AAVEV3_PREFIX = "a"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
|
@ -15,6 +16,7 @@ import androidx.compose.ui.Alignment
|
||||||
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.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
import androidx.compose.ui.text.LinkAnnotation
|
import androidx.compose.ui.text.LinkAnnotation
|
||||||
import androidx.compose.ui.text.withLink
|
import androidx.compose.ui.text.withLink
|
||||||
|
|
@ -25,6 +27,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import com.tangem.common.ui.notifications.NotificationUM
|
import com.tangem.common.ui.notifications.NotificationUM
|
||||||
import com.tangem.core.ui.components.*
|
import com.tangem.core.ui.components.*
|
||||||
import com.tangem.core.ui.components.notifications.Notification
|
import com.tangem.core.ui.components.notifications.Notification
|
||||||
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
import com.tangem.core.ui.extensions.*
|
import com.tangem.core.ui.extensions.*
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreview
|
import com.tangem.core.ui.res.TangemThemePreview
|
||||||
|
|
@ -35,6 +38,7 @@ import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSu
|
||||||
internal fun YieldSupplyActiveContent(
|
internal fun YieldSupplyActiveContent(
|
||||||
state: YieldSupplyActiveContentUM,
|
state: YieldSupplyActiveContentUM,
|
||||||
isBalanceHidden: Boolean,
|
isBalanceHidden: Boolean,
|
||||||
|
chartComponent: ComposableContentComponent,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
|
|
@ -62,6 +66,9 @@ internal fun YieldSupplyActiveContent(
|
||||||
style = TangemTheme.typography.h2,
|
style = TangemTheme.typography.h2,
|
||||||
color = TangemTheme.colors.text.primary1,
|
color = TangemTheme.colors.text.primary1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
CurrentApy(state.apy)
|
||||||
|
chartComponent.Content(Modifier.padding(bottom = 12.dp))
|
||||||
}
|
}
|
||||||
YieldSupplyActiveMyFunds(state = state, isBalanceHidden = isBalanceHidden)
|
YieldSupplyActiveMyFunds(state = state, isBalanceHidden = isBalanceHidden)
|
||||||
|
|
||||||
|
|
@ -76,6 +83,45 @@ internal fun YieldSupplyActiveContent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun CurrentApy(apy: TextReference?, modifier: Modifier = Modifier) {
|
||||||
|
Row(modifier = modifier.padding(vertical = 12.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text(
|
||||||
|
modifier = modifier.weight(1.0f),
|
||||||
|
text = stringResourceSafe(R.string.yield_module_earn_sheet_current_apy_title),
|
||||||
|
style = TangemTheme.typography.body1,
|
||||||
|
color = TangemTheme.colors.text.tertiary,
|
||||||
|
)
|
||||||
|
AnimatedContent(
|
||||||
|
targetState = apy?.resolveReference(),
|
||||||
|
label = "CurrentApy",
|
||||||
|
) { apyText ->
|
||||||
|
if (apyText == null) {
|
||||||
|
TextShimmer(
|
||||||
|
modifier = modifier.width(56.dp),
|
||||||
|
text = "",
|
||||||
|
style = TangemTheme.typography.body1,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Icon(
|
||||||
|
painterResource(R.drawable.ic_arrow_up_8),
|
||||||
|
tint = TangemTheme.colors.text.accent,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.padding(end = 8.dp),
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
modifier = modifier,
|
||||||
|
text = apyText,
|
||||||
|
style = TangemTheme.typography.body1,
|
||||||
|
color = TangemTheme.colors.text.accent,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun YieldSupplyActiveMyFunds(state: YieldSupplyActiveContentUM, isBalanceHidden: Boolean) {
|
private fun YieldSupplyActiveMyFunds(state: YieldSupplyActiveContentUM, isBalanceHidden: Boolean) {
|
||||||
Column(
|
Column(
|
||||||
|
|
@ -193,7 +239,11 @@ private fun YieldSupplyActiveBottomSheet_Preview(
|
||||||
@PreviewParameter(YieldSupplyActiveBottomSheetPreviewProvider::class) params: YieldSupplyActiveContentUM,
|
@PreviewParameter(YieldSupplyActiveBottomSheetPreviewProvider::class) params: YieldSupplyActiveContentUM,
|
||||||
) {
|
) {
|
||||||
TangemThemePreview {
|
TangemThemePreview {
|
||||||
YieldSupplyActiveContent(params, true)
|
YieldSupplyActiveContent(
|
||||||
|
state = params,
|
||||||
|
isBalanceHidden = true,
|
||||||
|
chartComponent = ComposableContentComponent.EMPTY,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue