Updated on 2026-08-14
This commit is contained in:
parent
4aa267c951
commit
0548571089
41 changed files with 573 additions and 347 deletions
|
|
@ -45,4 +45,14 @@ object EarnDomainModule {
|
||||||
fun provideGetEarnTokensBatchFlowUseCase(repository: EarnRepository): GetEarnTokensBatchFlowUseCase {
|
fun provideGetEarnTokensBatchFlowUseCase(repository: EarnRepository): GetEarnTokensBatchFlowUseCase {
|
||||||
return GetEarnTokensBatchFlowUseCase(repository)
|
return GetEarnTokensBatchFlowUseCase(repository)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideGetEarnFilterUseCase(repository: EarnRepository): GetEarnFilterUseCase {
|
||||||
|
return GetEarnFilterUseCase(repository)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideSetEarnFilterUseCase(repository: EarnRepository): SetEarnFilterUseCase {
|
||||||
|
return SetEarnFilterUseCase(repository)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.tangem.data.earn.datastore
|
||||||
|
|
||||||
|
import com.tangem.datasource.local.datastore.RuntimeStateStore
|
||||||
|
import com.tangem.domain.earn.model.EarnFilter
|
||||||
|
import com.tangem.domain.earn.model.EarnFilterNetwork
|
||||||
|
import com.tangem.domain.earn.model.EarnFilterType
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
internal class EarnFilterStore @Inject constructor() :
|
||||||
|
RuntimeStateStore<EarnFilter> by RuntimeStateStore(
|
||||||
|
defaultValue = EarnFilter(
|
||||||
|
earnFilterNetwork = EarnFilterNetwork.AllNetworks(isSelected = true),
|
||||||
|
earnFilterType = EarnFilterType.ALL,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
@ -6,7 +6,7 @@ import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class EarnNetworksStore @Inject constructor() :
|
internal class EarnNetworksStore @Inject constructor() :
|
||||||
RuntimeStateStore<EarnNetworks?> by RuntimeStateStore(
|
RuntimeStateStore<EarnNetworks?> by RuntimeStateStore(
|
||||||
defaultValue = null,
|
defaultValue = null,
|
||||||
)
|
)
|
||||||
|
|
@ -6,7 +6,7 @@ import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class EarnTopTokensStore @Inject constructor() :
|
internal class EarnTopTokensStore @Inject constructor() :
|
||||||
RuntimeStateStore<EarnTopToken?> by RuntimeStateStore(
|
RuntimeStateStore<EarnTopToken?> by RuntimeStateStore(
|
||||||
defaultValue = null,
|
defaultValue = null,
|
||||||
)
|
)
|
||||||
|
|
@ -2,6 +2,7 @@ package com.tangem.data.earn.di
|
||||||
|
|
||||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||||
import com.tangem.data.earn.DefaultEarnErrorResolver
|
import com.tangem.data.earn.DefaultEarnErrorResolver
|
||||||
|
import com.tangem.data.earn.datastore.EarnFilterStore
|
||||||
import com.tangem.data.earn.datastore.EarnNetworksStore
|
import com.tangem.data.earn.datastore.EarnNetworksStore
|
||||||
import com.tangem.data.earn.datastore.EarnTopTokensStore
|
import com.tangem.data.earn.datastore.EarnTopTokensStore
|
||||||
import com.tangem.data.earn.repository.DefaultEarnRepository
|
import com.tangem.data.earn.repository.DefaultEarnRepository
|
||||||
|
|
@ -31,6 +32,7 @@ internal object EarnDataModule {
|
||||||
userWalletsListRepository: UserWalletsListRepository,
|
userWalletsListRepository: UserWalletsListRepository,
|
||||||
earnNetworksStore: EarnNetworksStore,
|
earnNetworksStore: EarnNetworksStore,
|
||||||
earnTopTokensStore: EarnTopTokensStore,
|
earnTopTokensStore: EarnTopTokensStore,
|
||||||
|
earnFilterStore: EarnFilterStore,
|
||||||
earnErrorResolver: EarnErrorResolver,
|
earnErrorResolver: EarnErrorResolver,
|
||||||
excludedBlockchains: ExcludedBlockchains,
|
excludedBlockchains: ExcludedBlockchains,
|
||||||
): EarnRepository {
|
): EarnRepository {
|
||||||
|
|
@ -42,6 +44,7 @@ internal object EarnDataModule {
|
||||||
earnTopTokensStore = earnTopTokensStore,
|
earnTopTokensStore = earnTopTokensStore,
|
||||||
earnErrorResolver = earnErrorResolver,
|
earnErrorResolver = earnErrorResolver,
|
||||||
excludedBlockchains = excludedBlockchains,
|
excludedBlockchains = excludedBlockchains,
|
||||||
|
earnFilterStore = earnFilterStore,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||||
import com.tangem.data.common.currency.CryptoCurrencyFactory
|
import com.tangem.data.common.currency.CryptoCurrencyFactory
|
||||||
import com.tangem.data.earn.converter.EarnTokenConverter
|
import com.tangem.data.earn.converter.EarnTokenConverter
|
||||||
|
import com.tangem.data.earn.datastore.EarnFilterStore
|
||||||
import com.tangem.data.earn.datastore.EarnNetworksStore
|
import com.tangem.data.earn.datastore.EarnNetworksStore
|
||||||
import com.tangem.data.earn.datastore.EarnTopTokensStore
|
import com.tangem.data.earn.datastore.EarnTopTokensStore
|
||||||
import com.tangem.data.earn.repository.batch.EarnTokensBatchFetcher
|
import com.tangem.data.earn.repository.batch.EarnTokensBatchFetcher
|
||||||
|
|
@ -14,6 +15,7 @@ import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||||
import com.tangem.datasource.api.tangemTech.models.EarnResponse
|
import com.tangem.datasource.api.tangemTech.models.EarnResponse
|
||||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||||
import com.tangem.domain.earn.EarnErrorResolver
|
import com.tangem.domain.earn.EarnErrorResolver
|
||||||
|
import com.tangem.domain.earn.model.EarnFilter
|
||||||
import com.tangem.domain.earn.model.EarnTokensBatchFlow
|
import com.tangem.domain.earn.model.EarnTokensBatchFlow
|
||||||
import com.tangem.domain.earn.model.EarnTokensBatchingContext
|
import com.tangem.domain.earn.model.EarnTokensBatchingContext
|
||||||
import com.tangem.domain.earn.repository.EarnRepository
|
import com.tangem.domain.earn.repository.EarnRepository
|
||||||
|
|
@ -38,6 +40,7 @@ internal class DefaultEarnRepository(
|
||||||
private val userWalletsListRepository: UserWalletsListRepository,
|
private val userWalletsListRepository: UserWalletsListRepository,
|
||||||
private val earnNetworksStore: EarnNetworksStore,
|
private val earnNetworksStore: EarnNetworksStore,
|
||||||
private val earnTopTokensStore: EarnTopTokensStore,
|
private val earnTopTokensStore: EarnTopTokensStore,
|
||||||
|
private val earnFilterStore: EarnFilterStore,
|
||||||
private val earnErrorResolver: EarnErrorResolver,
|
private val earnErrorResolver: EarnErrorResolver,
|
||||||
private val excludedBlockchains: ExcludedBlockchains,
|
private val excludedBlockchains: ExcludedBlockchains,
|
||||||
) : EarnRepository {
|
) : EarnRepository {
|
||||||
|
|
@ -123,6 +126,14 @@ internal class DefaultEarnRepository(
|
||||||
return earnTopTokensStore.get()
|
return earnTopTokensStore.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun observeEarnFilter(): Flow<EarnFilter> {
|
||||||
|
return earnFilterStore.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun setEarnFilter(filter: EarnFilter) {
|
||||||
|
earnFilterStore.store(filter)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
internal const val FIRST_PAGE = 1
|
internal const val FIRST_PAGE = 1
|
||||||
private const val INITIAL_BATCH_KEY = 0
|
private const val INITIAL_BATCH_KEY = 0
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.tangem.domain.earn.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class EarnFilter(
|
||||||
|
val earnFilterNetwork: EarnFilterNetwork,
|
||||||
|
val earnFilterType: EarnFilterType,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.tangem.domain.earn.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
sealed interface EarnFilterNetwork {
|
||||||
|
|
||||||
|
val isSelected: Boolean
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AllNetworks(
|
||||||
|
override val isSelected: Boolean,
|
||||||
|
) : EarnFilterNetwork
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MyNetworks(
|
||||||
|
override val isSelected: Boolean,
|
||||||
|
) : EarnFilterNetwork
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Specific(
|
||||||
|
override val isSelected: Boolean,
|
||||||
|
val id: String,
|
||||||
|
val symbol: String,
|
||||||
|
val fullName: String,
|
||||||
|
) : EarnFilterNetwork
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.tangem.domain.earn.model
|
||||||
|
|
||||||
|
enum class EarnFilterType {
|
||||||
|
ALL,
|
||||||
|
STAKING,
|
||||||
|
YIELD,
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.domain.earn.repository
|
package com.tangem.domain.earn.repository
|
||||||
|
|
||||||
|
import com.tangem.domain.earn.model.EarnFilter
|
||||||
import com.tangem.domain.earn.model.EarnTokensBatchFlow
|
import com.tangem.domain.earn.model.EarnTokensBatchFlow
|
||||||
import com.tangem.domain.earn.model.EarnTokensBatchingContext
|
import com.tangem.domain.earn.model.EarnTokensBatchingContext
|
||||||
import com.tangem.domain.models.earn.EarnNetworks
|
import com.tangem.domain.models.earn.EarnNetworks
|
||||||
|
|
@ -23,4 +24,8 @@ interface EarnRepository {
|
||||||
suspend fun fetchTopEarnTokens(limit: Int)
|
suspend fun fetchTopEarnTokens(limit: Int)
|
||||||
|
|
||||||
fun observeTopEarnTokens(): Flow<EarnTopToken?>
|
fun observeTopEarnTokens(): Flow<EarnTopToken?>
|
||||||
|
|
||||||
|
fun observeEarnFilter(): Flow<EarnFilter>
|
||||||
|
|
||||||
|
suspend fun setEarnFilter(filter: EarnFilter)
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.tangem.domain.earn.usecase
|
||||||
|
|
||||||
|
import com.tangem.domain.earn.model.EarnFilter
|
||||||
|
import com.tangem.domain.earn.repository.EarnRepository
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class GetEarnFilterUseCase(private val repository: EarnRepository) {
|
||||||
|
|
||||||
|
operator fun invoke(): Flow<EarnFilter> {
|
||||||
|
return repository.observeEarnFilter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.tangem.domain.earn.usecase
|
||||||
|
|
||||||
|
import com.tangem.domain.earn.model.EarnFilter
|
||||||
|
import com.tangem.domain.earn.repository.EarnRepository
|
||||||
|
|
||||||
|
class SetEarnFilterUseCase(private val repository: EarnRepository) {
|
||||||
|
|
||||||
|
suspend operator fun invoke(filter: EarnFilter) {
|
||||||
|
repository.setEarnFilter(filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,7 @@ 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.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.features.feed.components.feed.FeedPortfolioRoute
|
import com.tangem.features.feed.components.feed.FeedBottomSheetRoute
|
||||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent
|
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent
|
||||||
import com.tangem.features.feed.model.earn.EarnModel
|
import com.tangem.features.feed.model.earn.EarnModel
|
||||||
import com.tangem.features.feed.ui.earn.EarnContent
|
import com.tangem.features.feed.ui.earn.EarnContent
|
||||||
|
|
@ -35,7 +35,7 @@ internal class DefaultEarnComponent(
|
||||||
|
|
||||||
private val bottomSheetSlot = childSlot(
|
private val bottomSheetSlot = childSlot(
|
||||||
source = earnModel.bottomSheetNavigation,
|
source = earnModel.bottomSheetNavigation,
|
||||||
serializer = FeedPortfolioRoute.serializer(),
|
serializer = null,
|
||||||
handleBackButton = false,
|
handleBackButton = false,
|
||||||
childFactory = ::bottomSheetChild,
|
childFactory = ::bottomSheetChild,
|
||||||
)
|
)
|
||||||
|
|
@ -68,10 +68,10 @@ internal class DefaultEarnComponent(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bottomSheetChild(
|
private fun bottomSheetChild(
|
||||||
config: FeedPortfolioRoute,
|
config: FeedBottomSheetRoute,
|
||||||
componentContext: ComponentContext,
|
componentContext: ComponentContext,
|
||||||
): ComposableBottomSheetComponent = when (config) {
|
): ComposableBottomSheetComponent = when (config) {
|
||||||
is FeedPortfolioRoute.AddToPortfolio -> {
|
is FeedBottomSheetRoute.AddToPortfolio -> {
|
||||||
addToPortfolioComponentFactory.create(
|
addToPortfolioComponentFactory.create(
|
||||||
context = childByContext(componentContext),
|
context = childByContext(componentContext),
|
||||||
params = AddToPortfolioPreselectedDataComponent.Params(
|
params = AddToPortfolioPreselectedDataComponent.Params(
|
||||||
|
|
@ -80,6 +80,14 @@ internal class DefaultEarnComponent(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
is FeedBottomSheetRoute.NetworkFilter -> EarnNetworkFilterComponent(
|
||||||
|
context = childByContext(componentContext),
|
||||||
|
params = config.params,
|
||||||
|
)
|
||||||
|
is FeedBottomSheetRoute.TypeFilter -> EarnTypeFilterComponent(
|
||||||
|
context = childByContext(componentContext),
|
||||||
|
params = config.params,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.tangem.features.feed.components.earn
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
|
import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
|
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||||
|
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||||
|
import com.tangem.domain.earn.model.EarnFilterNetwork
|
||||||
|
import com.tangem.features.feed.model.earn.filters.EarnNetworkFilterModel
|
||||||
|
import com.tangem.features.feed.ui.earn.components.EarnFilterByNetworkBottomSheet
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
|
|
||||||
|
internal class EarnNetworkFilterComponent @AssistedInject constructor(
|
||||||
|
@Assisted context: AppComponentContext,
|
||||||
|
@Assisted private val params: Params,
|
||||||
|
) : AppComponentContext by context, ComposableBottomSheetComponent {
|
||||||
|
|
||||||
|
private val model = getOrCreateModel<EarnNetworkFilterModel, Params>(params = params)
|
||||||
|
|
||||||
|
override fun dismiss() {
|
||||||
|
params.onDismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun BottomSheet() {
|
||||||
|
val state = model.state.collectAsStateWithLifecycle()
|
||||||
|
EarnFilterByNetworkBottomSheet(
|
||||||
|
config = TangemBottomSheetConfig(
|
||||||
|
isShown = true,
|
||||||
|
onDismissRequest = ::dismiss,
|
||||||
|
content = state.value,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Params(
|
||||||
|
val allFilters: List<EarnFilterNetwork>,
|
||||||
|
val onFilterSelected: (EarnFilterNetwork) -> Unit,
|
||||||
|
val onDismiss: () -> Unit,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.tangem.features.feed.components.earn
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
|
import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
|
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||||
|
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||||
|
import com.tangem.domain.earn.model.EarnFilterType
|
||||||
|
import com.tangem.features.feed.model.earn.filters.EarnTypeFilterModel
|
||||||
|
import com.tangem.features.feed.ui.earn.components.EarnFilterByTypeBottomSheet
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
|
|
||||||
|
internal class EarnTypeFilterComponent @AssistedInject constructor(
|
||||||
|
@Assisted context: AppComponentContext,
|
||||||
|
@Assisted private val params: Params,
|
||||||
|
) : AppComponentContext by context, ComposableBottomSheetComponent {
|
||||||
|
|
||||||
|
private val model = getOrCreateModel<EarnTypeFilterModel, Params>(params = params)
|
||||||
|
|
||||||
|
override fun dismiss() {
|
||||||
|
params.onDismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun BottomSheet() {
|
||||||
|
val state = model.state.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
|
EarnFilterByTypeBottomSheet(
|
||||||
|
config = TangemBottomSheetConfig(
|
||||||
|
isShown = true,
|
||||||
|
onDismissRequest = ::dismiss,
|
||||||
|
content = state.value,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Params(
|
||||||
|
val selectedFilter: EarnFilterType,
|
||||||
|
val onFilterSelected: (EarnFilterType) -> Unit,
|
||||||
|
val onDismiss: () -> Unit,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -15,7 +15,9 @@ import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
||||||
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.decompose.EmptyComposableBottomSheetComponent
|
||||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent
|
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent
|
||||||
|
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent.Params
|
||||||
import com.tangem.features.feed.model.feed.FeedComponentModel
|
import com.tangem.features.feed.model.feed.FeedComponentModel
|
||||||
import com.tangem.features.feed.model.feed.FeedModelClickIntents
|
import com.tangem.features.feed.model.feed.FeedModelClickIntents
|
||||||
import com.tangem.features.feed.ui.feed.FeedList
|
import com.tangem.features.feed.ui.feed.FeedList
|
||||||
|
|
@ -31,7 +33,7 @@ internal class DefaultFeedComponent(
|
||||||
|
|
||||||
private val bottomSheetSlot = childSlot(
|
private val bottomSheetSlot = childSlot(
|
||||||
source = feedComponentModel.bottomSheetNavigation,
|
source = feedComponentModel.bottomSheetNavigation,
|
||||||
serializer = FeedPortfolioRoute.serializer(),
|
serializer = null,
|
||||||
handleBackButton = false,
|
handleBackButton = false,
|
||||||
childFactory = ::bottomSheetChild,
|
childFactory = ::bottomSheetChild,
|
||||||
)
|
)
|
||||||
|
|
@ -64,18 +66,20 @@ internal class DefaultFeedComponent(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bottomSheetChild(
|
private fun bottomSheetChild(
|
||||||
config: FeedPortfolioRoute,
|
config: FeedBottomSheetRoute,
|
||||||
componentContext: ComponentContext,
|
componentContext: ComponentContext,
|
||||||
): ComposableBottomSheetComponent = when (config) {
|
): ComposableBottomSheetComponent = when (config) {
|
||||||
is FeedPortfolioRoute.AddToPortfolio -> {
|
is FeedBottomSheetRoute.AddToPortfolio -> {
|
||||||
addToPortfolioComponentFactory.create(
|
addToPortfolioComponentFactory.create(
|
||||||
context = childByContext(componentContext),
|
context = childByContext(componentContext),
|
||||||
params = AddToPortfolioPreselectedDataComponent.Params(
|
params = Params(
|
||||||
tokenToAdd = config.tokenToAdd,
|
tokenToAdd = config.tokenToAdd,
|
||||||
callback = feedComponentModel.addToPortfolioCallback,
|
callback = feedComponentModel.addToPortfolioCallback,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
is FeedBottomSheetRoute.NetworkFilter -> EmptyComposableBottomSheetComponent
|
||||||
|
is FeedBottomSheetRoute.TypeFilter -> EmptyComposableBottomSheetComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
data class FeedParams(val feedClickIntents: FeedModelClickIntents)
|
data class FeedParams(val feedClickIntents: FeedModelClickIntents)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.tangem.features.feed.components.feed
|
||||||
|
|
||||||
|
import com.tangem.features.feed.components.earn.EarnNetworkFilterComponent
|
||||||
|
import com.tangem.features.feed.components.earn.EarnTypeFilterComponent
|
||||||
|
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent
|
||||||
|
|
||||||
|
internal sealed interface FeedBottomSheetRoute {
|
||||||
|
|
||||||
|
data class AddToPortfolio(val tokenToAdd: AddToPortfolioPreselectedDataComponent.TokenToAdd) : FeedBottomSheetRoute
|
||||||
|
|
||||||
|
data class NetworkFilter(val params: EarnNetworkFilterComponent.Params) : FeedBottomSheetRoute
|
||||||
|
|
||||||
|
data class TypeFilter(val params: EarnTypeFilterComponent.Params) : FeedBottomSheetRoute
|
||||||
|
}
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
package com.tangem.features.feed.components.feed
|
|
||||||
|
|
||||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
sealed interface FeedPortfolioRoute {
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class AddToPortfolio(val tokenToAdd: AddToPortfolioPreselectedDataComponent.TokenToAdd) : FeedPortfolioRoute
|
|
||||||
}
|
|
||||||
|
|
@ -4,6 +4,8 @@ import com.tangem.core.decompose.di.ModelComponent
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.features.feed.model.FeedEntryModel
|
import com.tangem.features.feed.model.FeedEntryModel
|
||||||
import com.tangem.features.feed.model.earn.EarnModel
|
import com.tangem.features.feed.model.earn.EarnModel
|
||||||
|
import com.tangem.features.feed.model.earn.filters.EarnNetworkFilterModel
|
||||||
|
import com.tangem.features.feed.model.earn.filters.EarnTypeFilterModel
|
||||||
import com.tangem.features.feed.model.feed.FeedComponentModel
|
import com.tangem.features.feed.model.feed.FeedComponentModel
|
||||||
import com.tangem.features.feed.model.market.details.MarketsTokenDetailsModel
|
import com.tangem.features.feed.model.market.details.MarketsTokenDetailsModel
|
||||||
import com.tangem.features.feed.model.market.list.MarketsListModel
|
import com.tangem.features.feed.model.market.list.MarketsListModel
|
||||||
|
|
@ -53,4 +55,14 @@ internal interface ModelModule {
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@ClassKey(FeedEntryModel::class)
|
@ClassKey(FeedEntryModel::class)
|
||||||
fun provideFeedEntryModel(model: FeedEntryModel): Model
|
fun provideFeedEntryModel(model: FeedEntryModel): Model
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ClassKey(EarnNetworkFilterModel::class)
|
||||||
|
fun provideEarnNetworkFilterModel(model: EarnNetworkFilterModel): Model
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ClassKey(EarnTypeFilterModel::class)
|
||||||
|
fun provideEarnTypeFilterModel(model: EarnTypeFilterModel): Model
|
||||||
}
|
}
|
||||||
|
|
@ -5,14 +5,14 @@ import arrow.core.Either
|
||||||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||||
import com.arkivanov.decompose.router.slot.activate
|
import com.arkivanov.decompose.router.slot.activate
|
||||||
import com.arkivanov.decompose.router.slot.dismiss
|
import com.arkivanov.decompose.router.slot.dismiss
|
||||||
import com.tangem.common.R
|
|
||||||
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.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
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
import com.tangem.domain.earn.model.EarnFilter
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.domain.earn.model.EarnFilterNetwork
|
||||||
|
import com.tangem.domain.earn.model.EarnFilterType
|
||||||
import com.tangem.domain.earn.usecase.*
|
import com.tangem.domain.earn.usecase.*
|
||||||
import com.tangem.domain.markets.TokenMarketInfo
|
import com.tangem.domain.markets.TokenMarketInfo
|
||||||
import com.tangem.domain.models.currency.CryptoCurrency
|
import com.tangem.domain.models.currency.CryptoCurrency
|
||||||
|
|
@ -20,17 +20,26 @@ import com.tangem.domain.models.earn.EarnNetworks
|
||||||
import com.tangem.domain.models.earn.EarnTokenWithCurrency
|
import com.tangem.domain.models.earn.EarnTokenWithCurrency
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.features.feed.components.earn.DefaultEarnComponent
|
import com.tangem.features.feed.components.earn.DefaultEarnComponent
|
||||||
import com.tangem.features.feed.components.feed.FeedPortfolioRoute
|
import com.tangem.features.feed.components.earn.EarnNetworkFilterComponent
|
||||||
|
import com.tangem.features.feed.components.earn.EarnTypeFilterComponent
|
||||||
|
import com.tangem.features.feed.components.feed.FeedBottomSheetRoute
|
||||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent
|
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent
|
||||||
|
import com.tangem.features.feed.model.earn.filters.state.EarnFilterNetworkConverter
|
||||||
|
import com.tangem.features.feed.model.earn.filters.state.EarnFilterNetworkUMConverter
|
||||||
|
import com.tangem.features.feed.model.earn.filters.state.EarnFilterTypeConverter
|
||||||
|
import com.tangem.features.feed.model.earn.filters.state.EarnFilterTypeUMConverter
|
||||||
import com.tangem.features.feed.model.earn.state.EarnStateController
|
import com.tangem.features.feed.model.earn.state.EarnStateController
|
||||||
import com.tangem.features.feed.model.earn.state.converter.EarnNetworksConverter
|
import com.tangem.features.feed.model.earn.state.transformers.EarnFilterSelectedStateTransformer
|
||||||
import com.tangem.features.feed.model.earn.state.transformers.*
|
import com.tangem.features.feed.model.earn.state.transformers.UpdateBestOpportunitiesStateTransformer
|
||||||
|
import com.tangem.features.feed.model.earn.state.transformers.UpdateEarnUMInitialStateTransformer
|
||||||
|
import com.tangem.features.feed.model.earn.state.transformers.UpdateMostlyUsedStateTransformer
|
||||||
import com.tangem.features.feed.model.earn.statemanager.EarnListBatchFlowManager
|
import com.tangem.features.feed.model.earn.statemanager.EarnListBatchFlowManager
|
||||||
import com.tangem.features.feed.model.earn.statemanager.EarnListStateManager
|
import com.tangem.features.feed.model.earn.statemanager.EarnListStateManager
|
||||||
import com.tangem.features.feed.ui.earn.state.*
|
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnFilterTypeUM
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnUM
|
||||||
import com.tangem.utils.Provider
|
import com.tangem.utils.Provider
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
@ -46,13 +55,14 @@ internal class EarnModel @Inject constructor(
|
||||||
private val getEarnTokensBatchFlowUseCase: GetEarnTokensBatchFlowUseCase,
|
private val getEarnTokensBatchFlowUseCase: GetEarnTokensBatchFlowUseCase,
|
||||||
private val getTopEarnTokensUseCase: GetTopEarnTokensUseCase,
|
private val getTopEarnTokensUseCase: GetTopEarnTokensUseCase,
|
||||||
private val fetchTopEarnTokensUseCase: FetchTopEarnTokensUseCase,
|
private val fetchTopEarnTokensUseCase: FetchTopEarnTokensUseCase,
|
||||||
|
private val getEarnFilterUseCase: GetEarnFilterUseCase,
|
||||||
|
private val setEarnFilterUseCase: SetEarnFilterUseCase,
|
||||||
private val appRouter: AppRouter,
|
private val appRouter: AppRouter,
|
||||||
private val stateController: EarnStateController,
|
private val stateController: EarnStateController,
|
||||||
) : Model() {
|
) : Model() {
|
||||||
|
|
||||||
private val params = paramsContainer.require<DefaultEarnComponent.Params>()
|
private val params = paramsContainer.require<DefaultEarnComponent.Params>()
|
||||||
private val earnNetworks = MutableStateFlow<EarnNetworks>(Either.Right(emptyList()))
|
private val earnNetworks = MutableStateFlow<EarnNetworks>(Either.Right(emptyList()))
|
||||||
private val earnNetworksConverter: EarnNetworksConverter by lazy { EarnNetworksConverter() }
|
|
||||||
private val earnListConfigProvider = Provider {
|
private val earnListConfigProvider = Provider {
|
||||||
createEarnTokensListConfig(
|
createEarnTokensListConfig(
|
||||||
selectedTypeFilter = stateController.value.selectedTypeFilter,
|
selectedTypeFilter = stateController.value.selectedTypeFilter,
|
||||||
|
|
@ -61,17 +71,15 @@ internal class EarnModel @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val batchFlowManager by lazy {
|
private val batchFlowManager = EarnListBatchFlowManager(
|
||||||
EarnListBatchFlowManager(
|
getEarnTokensBatchFlowUseCase = getEarnTokensBatchFlowUseCase,
|
||||||
getEarnTokensBatchFlowUseCase = getEarnTokensBatchFlowUseCase,
|
configProvider = earnListConfigProvider,
|
||||||
configProvider = earnListConfigProvider,
|
onItemClick = ::onEarnTokenClick,
|
||||||
onItemClick = ::onEarnTokenClick,
|
modelScope = modelScope,
|
||||||
modelScope = modelScope,
|
dispatchers = dispatchers,
|
||||||
dispatchers = dispatchers,
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val bottomSheetNavigation: SlotNavigation<FeedPortfolioRoute> = SlotNavigation()
|
val bottomSheetNavigation: SlotNavigation<FeedBottomSheetRoute> = SlotNavigation()
|
||||||
|
|
||||||
val addToPortfolioCallback = object : AddToPortfolioPreselectedDataComponent.Callback {
|
val addToPortfolioCallback = object : AddToPortfolioPreselectedDataComponent.Callback {
|
||||||
override fun onDismiss() = bottomSheetNavigation.dismiss()
|
override fun onDismiss() = bottomSheetNavigation.dismiss()
|
||||||
|
|
@ -93,6 +101,7 @@ internal class EarnModel @Inject constructor(
|
||||||
updateInitialState()
|
updateInitialState()
|
||||||
fetchEarnNetworks()
|
fetchEarnNetworks()
|
||||||
fetchTopEarnTokens()
|
fetchTopEarnTokens()
|
||||||
|
subscribeOnStoredFilters()
|
||||||
subscribeOnNetworks()
|
subscribeOnNetworks()
|
||||||
subscribeOnBatchFlow()
|
subscribeOnBatchFlow()
|
||||||
subscribeToMostlyUsed()
|
subscribeToMostlyUsed()
|
||||||
|
|
@ -117,9 +126,7 @@ internal class EarnModel @Inject constructor(
|
||||||
)
|
)
|
||||||
}.onEach { bestOpportunitiesState ->
|
}.onEach { bestOpportunitiesState ->
|
||||||
stateController.update(UpdateBestOpportunitiesStateTransformer(bestOpportunitiesState))
|
stateController.update(UpdateBestOpportunitiesStateTransformer(bestOpportunitiesState))
|
||||||
}
|
}.launchIn(modelScope)
|
||||||
.onStart { batchFlowManager.reload() }
|
|
||||||
.launchIn(modelScope)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun subscribeToMostlyUsed() {
|
private fun subscribeToMostlyUsed() {
|
||||||
|
|
@ -142,6 +149,23 @@ internal class EarnModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun subscribeOnStoredFilters() {
|
||||||
|
modelScope.launch(dispatchers.default) {
|
||||||
|
getEarnFilterUseCase()
|
||||||
|
.collect { filter ->
|
||||||
|
val typeFilterUM = EarnFilterTypeConverter().convert(filter.earnFilterType)
|
||||||
|
val networkFilterUM = EarnFilterNetworkConverter().convert(filter.earnFilterNetwork)
|
||||||
|
stateController.update(
|
||||||
|
EarnFilterSelectedStateTransformer(
|
||||||
|
filterType = typeFilterUM,
|
||||||
|
filterNetwork = networkFilterUM,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
batchFlowManager.reload()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun fetchTopEarnTokens() {
|
private fun fetchTopEarnTokens() {
|
||||||
modelScope.launch(dispatchers.default) {
|
modelScope.launch(dispatchers.default) {
|
||||||
fetchTopEarnTokensUseCase()
|
fetchTopEarnTokensUseCase()
|
||||||
|
|
@ -154,142 +178,73 @@ internal class EarnModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTypeFilterBottomSheetConfig(
|
|
||||||
selectedOption: EarnFilterTypeUM,
|
|
||||||
isShown: Boolean = false,
|
|
||||||
): TangemBottomSheetConfig {
|
|
||||||
return TangemBottomSheetConfig(
|
|
||||||
isShown = isShown,
|
|
||||||
onDismissRequest = ::hideTypeFilterBottomSheet,
|
|
||||||
content = EarnFilterByTypeBottomSheetContentUM(
|
|
||||||
selectedOption = selectedOption,
|
|
||||||
onOptionClick = ::onTypeFilterOptionSelected,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createNetworkFilterBottomSheetConfig(
|
|
||||||
selectedNetwork: EarnFilterNetworkUM,
|
|
||||||
isShown: Boolean = false,
|
|
||||||
): TangemBottomSheetConfig {
|
|
||||||
val filters = buildList {
|
|
||||||
add(
|
|
||||||
EarnFilterNetworkUM.AllNetworks(
|
|
||||||
text = TextReference.Res(R.string.earn_filter_all_networks),
|
|
||||||
isSelected = false,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
add(
|
|
||||||
EarnFilterNetworkUM.MyNetworks(
|
|
||||||
text = TextReference.Res(R.string.earn_filter_my_networks),
|
|
||||||
isSelected = false,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
earnNetworks.value.onRight { networks ->
|
|
||||||
addAll(networks.map(earnNetworksConverter::convert))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val updatedNetworks = filters.map { filter ->
|
|
||||||
val shouldBeSelected = when (filter) {
|
|
||||||
is EarnFilterNetworkUM.AllNetworks -> selectedNetwork is EarnFilterNetworkUM.AllNetworks
|
|
||||||
is EarnFilterNetworkUM.MyNetworks -> selectedNetwork is EarnFilterNetworkUM.MyNetworks
|
|
||||||
is EarnFilterNetworkUM.Network ->
|
|
||||||
selectedNetwork is EarnFilterNetworkUM.Network && filter.id == selectedNetwork.id
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.isSelected != shouldBeSelected) {
|
|
||||||
when (filter) {
|
|
||||||
is EarnFilterNetworkUM.AllNetworks -> filter.copy(isSelected = shouldBeSelected)
|
|
||||||
is EarnFilterNetworkUM.MyNetworks -> filter.copy(isSelected = shouldBeSelected)
|
|
||||||
is EarnFilterNetworkUM.Network -> filter.copy(isSelected = shouldBeSelected)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
filter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TangemBottomSheetConfig(
|
|
||||||
isShown = isShown,
|
|
||||||
onDismissRequest = ::hideNetworkFilterBottomSheet,
|
|
||||||
content = EarnFilterByNetworkBottomSheetContentUM(
|
|
||||||
selectedNetwork = selectedNetwork,
|
|
||||||
networks = persistentListOf(*updatedNetworks.toTypedArray()),
|
|
||||||
onOptionClick = ::onNetworkFilterOptionSelected,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* start of clicks area */
|
/* start of clicks area */
|
||||||
private fun onTypeFilterClick() {
|
private fun onTypeFilterClick() {
|
||||||
stateController.update(
|
val currentState = state.value
|
||||||
EarnTypeFilterStateTransformer(
|
bottomSheetNavigation.activate(
|
||||||
shouldShow = true,
|
FeedBottomSheetRoute.TypeFilter(
|
||||||
filterByTypeBottomSheetConfig = ::createTypeFilterBottomSheetConfig,
|
params = EarnTypeFilterComponent.Params(
|
||||||
),
|
selectedFilter = EarnFilterTypeUMConverter().convert(currentState.selectedTypeFilter),
|
||||||
)
|
onFilterSelected = ::onTypeFilterOptionSelected,
|
||||||
}
|
onDismiss = { bottomSheetNavigation.dismiss() },
|
||||||
|
),
|
||||||
private fun hideTypeFilterBottomSheet() {
|
|
||||||
stateController.update(
|
|
||||||
EarnTypeFilterStateTransformer(
|
|
||||||
shouldShow = false,
|
|
||||||
filterByTypeBottomSheetConfig = ::createTypeFilterBottomSheetConfig,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onNetworkFilterClick() {
|
private fun onNetworkFilterClick() {
|
||||||
stateController.update(
|
bottomSheetNavigation.activate(
|
||||||
EarnNetworkFilterStateTransformer(
|
FeedBottomSheetRoute.NetworkFilter(
|
||||||
shouldShow = true,
|
params = EarnNetworkFilterComponent.Params(
|
||||||
filterByNetworkBottomSheetConfig = ::createNetworkFilterBottomSheetConfig,
|
allFilters = createNetworkFilters(),
|
||||||
|
onFilterSelected = ::onNetworkFilterOptionSelected,
|
||||||
|
onDismiss = { bottomSheetNavigation.dismiss() },
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideNetworkFilterBottomSheet() {
|
private fun createNetworkFilters(): List<EarnFilterNetwork> {
|
||||||
stateController.update(
|
val selectedFilter = state.value.selectedNetworkFilter
|
||||||
EarnNetworkFilterStateTransformer(
|
return buildList {
|
||||||
shouldShow = false,
|
add(
|
||||||
filterByNetworkBottomSheetConfig = ::createNetworkFilterBottomSheetConfig,
|
EarnFilterNetwork.AllNetworks(
|
||||||
),
|
isSelected = selectedFilter is EarnFilterNetworkUM.AllNetworks,
|
||||||
)
|
),
|
||||||
}
|
)
|
||||||
|
add(
|
||||||
private fun onTypeFilterOptionSelected(type: EarnFilterTypeUM) {
|
EarnFilterNetwork.MyNetworks(
|
||||||
stateController.update(
|
isSelected = selectedFilter is EarnFilterNetworkUM.MyNetworks,
|
||||||
EarnTypeFilterSelectedStateTransformer(
|
),
|
||||||
filter = type,
|
)
|
||||||
filterByTypeBottomSheetConfig = ::createTypeFilterBottomSheetConfig,
|
earnNetworks.value.onRight { networks ->
|
||||||
),
|
networks.mapTo(this) { network ->
|
||||||
)
|
EarnFilterNetwork.Specific(
|
||||||
batchFlowManager.reload()
|
id = network.networkId,
|
||||||
}
|
isSelected = selectedFilter is EarnFilterNetworkUM.Network &&
|
||||||
|
selectedFilter.id == network.networkId,
|
||||||
private fun onNetworkFilterOptionSelected(network: EarnFilterNetworkUM) {
|
symbol = network.symbol,
|
||||||
stateController.update(
|
fullName = network.fullName,
|
||||||
EarnNetworkFilterSelectedStateTransformer(
|
)
|
||||||
filter = network,
|
}
|
||||||
filterByNetworkBottomSheetConfig = ::createNetworkFilterBottomSheetConfig,
|
}
|
||||||
),
|
}
|
||||||
)
|
|
||||||
batchFlowManager.reload()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onClearFiltersClick() {
|
private fun onClearFiltersClick() {
|
||||||
stateController.update(
|
modelScope.launch(dispatchers.default) {
|
||||||
ClearEarnUMFilterStateTransformer(
|
setEarnFilterUseCase(
|
||||||
filterByTypeBottomSheetConfig = ::createTypeFilterBottomSheetConfig,
|
EarnFilter(
|
||||||
filterByNetworkBottomSheetConfig = ::createNetworkFilterBottomSheetConfig,
|
earnFilterNetwork = EarnFilterNetwork.AllNetworks(isSelected = true),
|
||||||
),
|
earnFilterType = EarnFilterType.ALL,
|
||||||
)
|
),
|
||||||
batchFlowManager.reload()
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onEarnTokenClick(earnTokenWithCurrency: EarnTokenWithCurrency) {
|
private fun onEarnTokenClick(earnTokenWithCurrency: EarnTokenWithCurrency) {
|
||||||
bottomSheetNavigation.activate(
|
bottomSheetNavigation.activate(
|
||||||
FeedPortfolioRoute.AddToPortfolio(
|
FeedBottomSheetRoute.AddToPortfolio(
|
||||||
tokenToAdd = AddToPortfolioPreselectedDataComponent.TokenToAdd(
|
tokenToAdd = AddToPortfolioPreselectedDataComponent.TokenToAdd(
|
||||||
network = TokenMarketInfo.Network(
|
network = TokenMarketInfo.Network(
|
||||||
networkId = earnTokenWithCurrency.earnToken.networkId,
|
networkId = earnTokenWithCurrency.earnToken.networkId,
|
||||||
|
|
@ -304,6 +259,30 @@ internal class EarnModel @Inject constructor(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onTypeFilterOptionSelected(type: EarnFilterType) {
|
||||||
|
modelScope.launch(dispatchers.default) {
|
||||||
|
setEarnFilterUseCase(
|
||||||
|
EarnFilter(
|
||||||
|
earnFilterNetwork = EarnFilterNetworkUMConverter().convert(state.value.selectedNetworkFilter),
|
||||||
|
earnFilterType = type,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
bottomSheetNavigation.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onNetworkFilterOptionSelected(filter: EarnFilterNetwork) {
|
||||||
|
modelScope.launch(dispatchers.default) {
|
||||||
|
setEarnFilterUseCase(
|
||||||
|
EarnFilter(
|
||||||
|
earnFilterNetwork = filter,
|
||||||
|
earnFilterType = EarnFilterTypeUMConverter().convert(state.value.selectedTypeFilter),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
bottomSheetNavigation.dismiss()
|
||||||
|
}
|
||||||
/* end of clicks area */
|
/* end of clicks area */
|
||||||
|
|
||||||
private fun updateInitialState() {
|
private fun updateInitialState() {
|
||||||
|
|
@ -311,10 +290,6 @@ internal class EarnModel @Inject constructor(
|
||||||
UpdateEarnUMInitialStateTransformer(
|
UpdateEarnUMInitialStateTransformer(
|
||||||
onBackClick = params.onBackClick,
|
onBackClick = params.onBackClick,
|
||||||
onNetworkFilterClick = ::onNetworkFilterClick,
|
onNetworkFilterClick = ::onNetworkFilterClick,
|
||||||
filterByTypeBottomSheetConfig = createTypeFilterBottomSheetConfig(state.value.selectedTypeFilter),
|
|
||||||
filterByNetworkBottomSheetConfig = createNetworkFilterBottomSheetConfig(
|
|
||||||
selectedNetwork = state.value.selectedNetworkFilter,
|
|
||||||
),
|
|
||||||
onTypeFilterClick = ::onTypeFilterClick,
|
onTypeFilterClick = ::onTypeFilterClick,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.tangem.features.feed.model.earn.filters
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
|
import com.tangem.core.decompose.model.Model
|
||||||
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
|
import com.tangem.features.feed.components.earn.EarnNetworkFilterComponent
|
||||||
|
import com.tangem.features.feed.model.earn.filters.state.EarnFilterNetworkUMConverter
|
||||||
|
import com.tangem.features.feed.model.earn.filters.state.EarnFilterNetworkConverter
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnFilterByNetworkBottomSheetContentUM
|
||||||
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@ModelScoped
|
||||||
|
internal class EarnNetworkFilterModel @Inject constructor(
|
||||||
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
|
paramsContainer: ParamsContainer,
|
||||||
|
) : Model() {
|
||||||
|
|
||||||
|
private val params = paramsContainer.require<EarnNetworkFilterComponent.Params>()
|
||||||
|
|
||||||
|
private val _state = MutableStateFlow(configureInitialState())
|
||||||
|
val state = _state.asStateFlow()
|
||||||
|
|
||||||
|
private fun configureInitialState(): EarnFilterByNetworkBottomSheetContentUM {
|
||||||
|
return EarnFilterByNetworkBottomSheetContentUM(
|
||||||
|
networks = params.allFilters
|
||||||
|
.map { EarnFilterNetworkConverter().convert(it) }
|
||||||
|
.toPersistentList(),
|
||||||
|
onOptionClick = { filterUM -> params.onFilterSelected(EarnFilterNetworkUMConverter().convert(filterUM)) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.tangem.features.feed.model.earn.filters
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
|
import com.tangem.core.decompose.model.Model
|
||||||
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
|
import com.tangem.features.feed.components.earn.EarnTypeFilterComponent
|
||||||
|
import com.tangem.features.feed.model.earn.filters.state.EarnFilterTypeConverter
|
||||||
|
import com.tangem.features.feed.model.earn.filters.state.EarnFilterTypeUMConverter
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnFilterByTypeBottomSheetContentUM
|
||||||
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@ModelScoped
|
||||||
|
internal class EarnTypeFilterModel @Inject constructor(
|
||||||
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
|
paramsContainer: ParamsContainer,
|
||||||
|
) : Model() {
|
||||||
|
|
||||||
|
private val params = paramsContainer.require<EarnTypeFilterComponent.Params>()
|
||||||
|
|
||||||
|
private val _state = MutableStateFlow(configureInitialState())
|
||||||
|
val state = _state.asStateFlow()
|
||||||
|
|
||||||
|
private fun configureInitialState(): EarnFilterByTypeBottomSheetContentUM {
|
||||||
|
return EarnFilterByTypeBottomSheetContentUM(
|
||||||
|
selectedOption = EarnFilterTypeConverter().convert(params.selectedFilter),
|
||||||
|
onOptionClick = { filterTypeUM ->
|
||||||
|
params.onFilterSelected(EarnFilterTypeUMConverter().convert(filterTypeUM))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.tangem.features.feed.model.earn.filters.state
|
||||||
|
|
||||||
|
import com.tangem.blockchain.common.Blockchain
|
||||||
|
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||||
|
import com.tangem.core.ui.extensions.getActiveIconRes
|
||||||
|
import com.tangem.domain.earn.model.EarnFilterNetwork
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
||||||
|
import com.tangem.utils.converter.Converter
|
||||||
|
|
||||||
|
internal class EarnFilterNetworkConverter : Converter<EarnFilterNetwork, EarnFilterNetworkUM> {
|
||||||
|
|
||||||
|
override fun convert(value: EarnFilterNetwork): EarnFilterNetworkUM {
|
||||||
|
return when (value) {
|
||||||
|
is EarnFilterNetwork.AllNetworks -> {
|
||||||
|
EarnFilterNetworkUM.AllNetworks(isSelected = value.isSelected)
|
||||||
|
}
|
||||||
|
is EarnFilterNetwork.MyNetworks -> {
|
||||||
|
EarnFilterNetworkUM.MyNetworks(isSelected = value.isSelected)
|
||||||
|
}
|
||||||
|
is EarnFilterNetwork.Specific -> {
|
||||||
|
EarnFilterNetworkUM.Network(
|
||||||
|
id = value.id,
|
||||||
|
text = value.fullName,
|
||||||
|
symbol = value.symbol,
|
||||||
|
iconRes = getActiveIconRes(Blockchain.fromNetworkId(value.id)?.id.orEmpty()),
|
||||||
|
isSelected = value.isSelected,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.tangem.features.feed.model.earn.filters.state
|
||||||
|
|
||||||
|
import com.tangem.domain.earn.model.EarnFilterNetwork
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
||||||
|
import com.tangem.utils.converter.Converter
|
||||||
|
|
||||||
|
internal class EarnFilterNetworkUMConverter : Converter<EarnFilterNetworkUM, EarnFilterNetwork> {
|
||||||
|
|
||||||
|
override fun convert(value: EarnFilterNetworkUM): EarnFilterNetwork {
|
||||||
|
return when (value) {
|
||||||
|
is EarnFilterNetworkUM.AllNetworks -> EarnFilterNetwork.AllNetworks(isSelected = value.isSelected)
|
||||||
|
is EarnFilterNetworkUM.MyNetworks -> EarnFilterNetwork.MyNetworks(isSelected = value.isSelected)
|
||||||
|
is EarnFilterNetworkUM.Network -> EarnFilterNetwork.Specific(
|
||||||
|
isSelected = value.isSelected,
|
||||||
|
id = value.id,
|
||||||
|
symbol = value.symbol,
|
||||||
|
fullName = value.text,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.tangem.features.feed.model.earn.filters.state
|
||||||
|
|
||||||
|
import com.tangem.domain.earn.model.EarnFilterType
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnFilterTypeUM
|
||||||
|
import com.tangem.utils.converter.Converter
|
||||||
|
|
||||||
|
internal class EarnFilterTypeConverter : Converter<EarnFilterType, EarnFilterTypeUM> {
|
||||||
|
override fun convert(value: EarnFilterType): EarnFilterTypeUM {
|
||||||
|
return when (value) {
|
||||||
|
EarnFilterType.ALL -> EarnFilterTypeUM.All
|
||||||
|
EarnFilterType.STAKING -> EarnFilterTypeUM.Staking
|
||||||
|
EarnFilterType.YIELD -> EarnFilterTypeUM.YieldMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.tangem.features.feed.model.earn.filters.state
|
||||||
|
|
||||||
|
import com.tangem.domain.earn.model.EarnFilterType
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnFilterTypeUM
|
||||||
|
import com.tangem.utils.converter.Converter
|
||||||
|
|
||||||
|
internal class EarnFilterTypeUMConverter : Converter<EarnFilterTypeUM, EarnFilterType> {
|
||||||
|
|
||||||
|
override fun convert(value: EarnFilterTypeUM): EarnFilterType {
|
||||||
|
return when (value) {
|
||||||
|
EarnFilterTypeUM.All -> EarnFilterType.ALL
|
||||||
|
EarnFilterTypeUM.Staking -> EarnFilterType.STAKING
|
||||||
|
EarnFilterTypeUM.YieldMode -> EarnFilterType.YIELD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
package com.tangem.features.feed.model.earn.state
|
package com.tangem.features.feed.model.earn.state
|
||||||
|
|
||||||
import com.tangem.common.R
|
|
||||||
import com.tangem.core.decompose.di.ModelScoped
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|
||||||
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 kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -34,12 +31,7 @@ internal class EarnStateController @Inject constructor() {
|
||||||
mostlyUsed = EarnListUM.Loading,
|
mostlyUsed = EarnListUM.Loading,
|
||||||
bestOpportunities = EarnBestOpportunitiesUM.Loading,
|
bestOpportunities = EarnBestOpportunitiesUM.Loading,
|
||||||
selectedTypeFilter = EarnFilterTypeUM.All,
|
selectedTypeFilter = EarnFilterTypeUM.All,
|
||||||
selectedNetworkFilter = EarnFilterNetworkUM.AllNetworks(
|
selectedNetworkFilter = EarnFilterNetworkUM.AllNetworks(isSelected = true),
|
||||||
text = TextReference.Res(R.string.earn_filter_all_networks),
|
|
||||||
isSelected = true,
|
|
||||||
),
|
|
||||||
filterByTypeBottomSheet = TangemBottomSheetConfig.Empty,
|
|
||||||
filterByNetworkBottomSheet = TangemBottomSheetConfig.Empty,
|
|
||||||
onBackClick = {},
|
onBackClick = {},
|
||||||
onNetworkFilterClick = {},
|
onNetworkFilterClick = {},
|
||||||
onTypeFilterClick = {},
|
onTypeFilterClick = {},
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package com.tangem.features.feed.model.earn.state.converter
|
|
||||||
|
|
||||||
import com.tangem.blockchain.common.Blockchain
|
|
||||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
|
||||||
import com.tangem.core.ui.extensions.getActiveIconRes
|
|
||||||
import com.tangem.domain.models.earn.EarnNetwork
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
|
||||||
import com.tangem.utils.converter.Converter
|
|
||||||
|
|
||||||
internal class EarnNetworksConverter : Converter<EarnNetwork, EarnFilterNetworkUM.Network> {
|
|
||||||
|
|
||||||
override fun convert(value: EarnNetwork): EarnFilterNetworkUM.Network {
|
|
||||||
return EarnFilterNetworkUM.Network(
|
|
||||||
id = value.networkId,
|
|
||||||
text = TextReference.Str(value.fullName),
|
|
||||||
symbol = TextReference.Str(value.symbol),
|
|
||||||
iconRes = getActiveIconRes(Blockchain.fromNetworkId(value.networkId)?.id.orEmpty()),
|
|
||||||
isSelected = false,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
package com.tangem.features.feed.model.earn.state.transformers
|
|
||||||
|
|
||||||
import com.tangem.common.R
|
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnFilterTypeUM
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnUM
|
|
||||||
|
|
||||||
internal class ClearEarnUMFilterStateTransformer(
|
|
||||||
private val filterByTypeBottomSheetConfig: (EarnFilterTypeUM, Boolean) -> TangemBottomSheetConfig,
|
|
||||||
private val filterByNetworkBottomSheetConfig: (EarnFilterNetworkUM, Boolean) -> TangemBottomSheetConfig,
|
|
||||||
) : EarnUMTransformer {
|
|
||||||
|
|
||||||
override fun transform(prevState: EarnUM): EarnUM {
|
|
||||||
val defaultNetworksFilter = EarnFilterNetworkUM.AllNetworks(
|
|
||||||
text = TextReference.Res(R.string.earn_filter_all_networks),
|
|
||||||
isSelected = true,
|
|
||||||
)
|
|
||||||
|
|
||||||
return prevState.copy(
|
|
||||||
selectedTypeFilter = EarnFilterTypeUM.All,
|
|
||||||
selectedNetworkFilter = defaultNetworksFilter,
|
|
||||||
filterByTypeBottomSheet = filterByTypeBottomSheetConfig(EarnFilterTypeUM.All, false),
|
|
||||||
filterByNetworkBottomSheet = filterByNetworkBottomSheetConfig(defaultNetworksFilter, false),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.tangem.features.feed.model.earn.state.transformers
|
||||||
|
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnFilterTypeUM
|
||||||
|
import com.tangem.features.feed.ui.earn.state.EarnUM
|
||||||
|
|
||||||
|
internal class EarnFilterSelectedStateTransformer(
|
||||||
|
private val filterType: EarnFilterTypeUM,
|
||||||
|
private val filterNetwork: EarnFilterNetworkUM,
|
||||||
|
) : EarnUMTransformer {
|
||||||
|
|
||||||
|
override fun transform(prevState: EarnUM): EarnUM {
|
||||||
|
return prevState.copy(
|
||||||
|
selectedTypeFilter = filterType,
|
||||||
|
selectedNetworkFilter = filterNetwork,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,13 @@
|
||||||
package com.tangem.features.feed.model.earn.state.transformers
|
package com.tangem.features.feed.model.earn.state.transformers
|
||||||
|
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnUM
|
import com.tangem.features.feed.ui.earn.state.EarnUM
|
||||||
|
|
||||||
internal class EarnNetworkFilterSelectedStateTransformer(
|
internal class EarnNetworkFilterSelectedStateTransformer(
|
||||||
private val filter: EarnFilterNetworkUM,
|
private val filter: EarnFilterNetworkUM,
|
||||||
private val filterByNetworkBottomSheetConfig: (EarnFilterNetworkUM, Boolean) -> TangemBottomSheetConfig,
|
|
||||||
) : EarnUMTransformer {
|
) : EarnUMTransformer {
|
||||||
|
|
||||||
override fun transform(prevState: EarnUM): EarnUM {
|
override fun transform(prevState: EarnUM): EarnUM {
|
||||||
return prevState.copy(
|
return prevState.copy(selectedNetworkFilter = filter)
|
||||||
selectedNetworkFilter = filter,
|
|
||||||
filterByNetworkBottomSheet = filterByNetworkBottomSheetConfig(filter, false),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
package com.tangem.features.feed.model.earn.state.transformers
|
|
||||||
|
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnFilterNetworkUM
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnUM
|
|
||||||
|
|
||||||
internal class EarnNetworkFilterStateTransformer(
|
|
||||||
private val shouldShow: Boolean,
|
|
||||||
private val filterByNetworkBottomSheetConfig: (EarnFilterNetworkUM, Boolean) -> TangemBottomSheetConfig,
|
|
||||||
) : EarnUMTransformer {
|
|
||||||
|
|
||||||
override fun transform(prevState: EarnUM): EarnUM {
|
|
||||||
return if (shouldShow) {
|
|
||||||
prevState.copy(
|
|
||||||
filterByNetworkBottomSheet = filterByNetworkBottomSheetConfig(prevState.selectedNetworkFilter, true),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
prevState.copy(filterByNetworkBottomSheet = prevState.filterByNetworkBottomSheet.copy(isShown = false))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
package com.tangem.features.feed.model.earn.state.transformers
|
|
||||||
|
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnFilterTypeUM
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnUM
|
|
||||||
|
|
||||||
internal class EarnTypeFilterSelectedStateTransformer(
|
|
||||||
private val filter: EarnFilterTypeUM,
|
|
||||||
private val filterByTypeBottomSheetConfig: (EarnFilterTypeUM, Boolean) -> TangemBottomSheetConfig,
|
|
||||||
) : EarnUMTransformer {
|
|
||||||
|
|
||||||
override fun transform(prevState: EarnUM): EarnUM {
|
|
||||||
return prevState.copy(
|
|
||||||
selectedTypeFilter = filter,
|
|
||||||
filterByTypeBottomSheet = filterByTypeBottomSheetConfig(filter, false),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
package com.tangem.features.feed.model.earn.state.transformers
|
|
||||||
|
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnFilterTypeUM
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnUM
|
|
||||||
|
|
||||||
internal class EarnTypeFilterStateTransformer(
|
|
||||||
private val shouldShow: Boolean,
|
|
||||||
private val filterByTypeBottomSheetConfig: (EarnFilterTypeUM, Boolean) -> TangemBottomSheetConfig,
|
|
||||||
) : EarnUMTransformer {
|
|
||||||
|
|
||||||
override fun transform(prevState: EarnUM): EarnUM {
|
|
||||||
return if (shouldShow) {
|
|
||||||
prevState.copy(
|
|
||||||
filterByTypeBottomSheet = filterByTypeBottomSheetConfig(prevState.selectedTypeFilter, true),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
prevState.copy(filterByTypeBottomSheet = prevState.filterByTypeBottomSheet.copy(isShown = false))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
package com.tangem.features.feed.model.earn.state.transformers
|
package com.tangem.features.feed.model.earn.state.transformers
|
||||||
|
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|
||||||
import com.tangem.features.feed.ui.earn.state.EarnUM
|
import com.tangem.features.feed.ui.earn.state.EarnUM
|
||||||
|
|
||||||
internal class UpdateEarnUMInitialStateTransformer(
|
internal class UpdateEarnUMInitialStateTransformer(
|
||||||
private val onBackClick: () -> Unit,
|
private val onBackClick: () -> Unit,
|
||||||
private val filterByTypeBottomSheetConfig: TangemBottomSheetConfig,
|
|
||||||
private val filterByNetworkBottomSheetConfig: TangemBottomSheetConfig,
|
|
||||||
private val onNetworkFilterClick: () -> Unit,
|
private val onNetworkFilterClick: () -> Unit,
|
||||||
private val onTypeFilterClick: () -> Unit,
|
private val onTypeFilterClick: () -> Unit,
|
||||||
) : EarnUMTransformer {
|
) : EarnUMTransformer {
|
||||||
|
|
@ -14,8 +11,6 @@ internal class UpdateEarnUMInitialStateTransformer(
|
||||||
override fun transform(prevState: EarnUM): EarnUM {
|
override fun transform(prevState: EarnUM): EarnUM {
|
||||||
return prevState.copy(
|
return prevState.copy(
|
||||||
onBackClick = onBackClick,
|
onBackClick = onBackClick,
|
||||||
filterByNetworkBottomSheet = filterByNetworkBottomSheetConfig,
|
|
||||||
filterByTypeBottomSheet = filterByTypeBottomSheetConfig,
|
|
||||||
onNetworkFilterClick = onNetworkFilterClick,
|
onNetworkFilterClick = onNetworkFilterClick,
|
||||||
onTypeFilterClick = onTypeFilterClick,
|
onTypeFilterClick = onTypeFilterClick,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.domain.news.usecase.FetchTrendingNewsUseCase
|
import com.tangem.domain.news.usecase.FetchTrendingNewsUseCase
|
||||||
import com.tangem.domain.news.usecase.ManageTrendingNewsUseCase
|
import com.tangem.domain.news.usecase.ManageTrendingNewsUseCase
|
||||||
import com.tangem.features.feed.components.feed.DefaultFeedComponent
|
import com.tangem.features.feed.components.feed.DefaultFeedComponent
|
||||||
import com.tangem.features.feed.components.feed.FeedPortfolioRoute
|
import com.tangem.features.feed.components.feed.FeedBottomSheetRoute
|
||||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent
|
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioPreselectedDataComponent
|
||||||
import com.tangem.features.feed.entry.featuretoggle.FeedFeatureToggle
|
import com.tangem.features.feed.entry.featuretoggle.FeedFeatureToggle
|
||||||
import com.tangem.features.feed.impl.R
|
import com.tangem.features.feed.impl.R
|
||||||
|
|
@ -89,7 +89,7 @@ internal class FeedComponentModel @Inject constructor(
|
||||||
dispatchers = dispatchers,
|
dispatchers = dispatchers,
|
||||||
)
|
)
|
||||||
|
|
||||||
val bottomSheetNavigation: SlotNavigation<FeedPortfolioRoute> = SlotNavigation()
|
val bottomSheetNavigation: SlotNavigation<FeedBottomSheetRoute> = SlotNavigation()
|
||||||
|
|
||||||
val addToPortfolioCallback = object : AddToPortfolioPreselectedDataComponent.Callback {
|
val addToPortfolioCallback = object : AddToPortfolioPreselectedDataComponent.Callback {
|
||||||
override fun onDismiss() = bottomSheetNavigation.dismiss()
|
override fun onDismiss() = bottomSheetNavigation.dismiss()
|
||||||
|
|
@ -398,7 +398,7 @@ internal class FeedComponentModel @Inject constructor(
|
||||||
|
|
||||||
private fun handleEarnTokenClick(earnTokenWithCurrency: EarnTokenWithCurrency) {
|
private fun handleEarnTokenClick(earnTokenWithCurrency: EarnTokenWithCurrency) {
|
||||||
bottomSheetNavigation.activate(
|
bottomSheetNavigation.activate(
|
||||||
FeedPortfolioRoute.AddToPortfolio(
|
FeedBottomSheetRoute.AddToPortfolio(
|
||||||
tokenToAdd = AddToPortfolioPreselectedDataComponent.TokenToAdd(
|
tokenToAdd = AddToPortfolioPreselectedDataComponent.TokenToAdd(
|
||||||
network = TokenMarketInfo.Network(
|
network = TokenMarketInfo.Network(
|
||||||
networkId = earnTokenWithCurrency.earnToken.networkId,
|
networkId = earnTokenWithCurrency.earnToken.networkId,
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.tangem.core.ui.R
|
import com.tangem.core.ui.R
|
||||||
import com.tangem.core.ui.components.*
|
import com.tangem.core.ui.components.*
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|
||||||
import com.tangem.core.ui.components.buttons.SecondarySmallButton
|
import com.tangem.core.ui.components.buttons.SecondarySmallButton
|
||||||
import com.tangem.core.ui.components.buttons.SmallButtonConfig
|
import com.tangem.core.ui.components.buttons.SmallButtonConfig
|
||||||
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||||
|
|
@ -37,7 +36,9 @@ import com.tangem.core.ui.res.LocalMainBottomSheetColor
|
||||||
import com.tangem.core.ui.res.TangemColorPalette
|
import com.tangem.core.ui.res.TangemColorPalette
|
||||||
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
|
||||||
import com.tangem.features.feed.ui.earn.components.*
|
import com.tangem.features.feed.ui.earn.components.EarnItemPlaceholder
|
||||||
|
import com.tangem.features.feed.ui.earn.components.EarnListItem
|
||||||
|
import com.tangem.features.feed.ui.earn.components.MostlyUsedPlaceholder
|
||||||
import com.tangem.features.feed.ui.earn.state.*
|
import com.tangem.features.feed.ui.earn.state.*
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
|
|
@ -50,9 +51,6 @@ internal fun EarnContent(state: EarnUM, modifier: Modifier = Modifier) {
|
||||||
val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(this).toDp() }
|
val bottomBarHeight = with(density) { WindowInsets.systemBars.getBottom(this).toDp() }
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
|
|
||||||
EarnFilterByTypeBottomSheet(config = state.filterByTypeBottomSheet)
|
|
||||||
EarnFilterByNetworkBottomSheet(config = state.filterByNetworkBottomSheet)
|
|
||||||
|
|
||||||
if (state.bestOpportunities is EarnBestOpportunitiesUM.Content) {
|
if (state.bestOpportunities is EarnBestOpportunitiesUM.Content) {
|
||||||
PaginationHandler(
|
PaginationHandler(
|
||||||
listState = listState,
|
listState = listState,
|
||||||
|
|
@ -89,7 +87,11 @@ internal fun EarnContent(state: EarnUM, modifier: Modifier = Modifier) {
|
||||||
SpacerH(12.dp)
|
SpacerH(12.dp)
|
||||||
BestOpportunitiesFilters(
|
BestOpportunitiesFilters(
|
||||||
state = state.bestOpportunities,
|
state = state.bestOpportunities,
|
||||||
selectedNetworkFilterText = state.selectedNetworkFilterText,
|
selectedNetworkFilterText = when (state.selectedNetworkFilter) {
|
||||||
|
is EarnFilterNetworkUM.AllNetworks -> TextReference.Res(R.string.earn_filter_all_networks)
|
||||||
|
is EarnFilterNetworkUM.MyNetworks -> TextReference.Res(R.string.earn_filter_my_networks)
|
||||||
|
is EarnFilterNetworkUM.Network -> TextReference.Str(state.selectedNetworkFilter.text)
|
||||||
|
},
|
||||||
selectedTypeFilterText = state.selectedTypeFilterText,
|
selectedTypeFilterText = state.selectedTypeFilterText,
|
||||||
onNetworkFilterClick = state.onNetworkFilterClick,
|
onNetworkFilterClick = state.onNetworkFilterClick,
|
||||||
onTypeFilterClick = state.onTypeFilterClick,
|
onTypeFilterClick = state.onTypeFilterClick,
|
||||||
|
|
@ -573,12 +575,7 @@ private fun previewEarnUM(
|
||||||
mostlyUsed = mostlyUsed,
|
mostlyUsed = mostlyUsed,
|
||||||
bestOpportunities = bestOpportunities,
|
bestOpportunities = bestOpportunities,
|
||||||
selectedTypeFilter = EarnFilterTypeUM.All,
|
selectedTypeFilter = EarnFilterTypeUM.All,
|
||||||
selectedNetworkFilter = EarnFilterNetworkUM.AllNetworks(
|
selectedNetworkFilter = EarnFilterNetworkUM.AllNetworks(isSelected = true),
|
||||||
text = resourceReference(R.string.earn_filter_all_networks),
|
|
||||||
isSelected = true,
|
|
||||||
),
|
|
||||||
filterByTypeBottomSheet = TangemBottomSheetConfig.Empty,
|
|
||||||
filterByNetworkBottomSheet = TangemBottomSheetConfig.Empty,
|
|
||||||
onBackClick = {},
|
onBackClick = {},
|
||||||
onNetworkFilterClick = {},
|
onNetworkFilterClick = {},
|
||||||
onTypeFilterClick = {},
|
onTypeFilterClick = {},
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,8 @@ import com.tangem.core.ui.components.inputrow.inner.DividerContainer
|
||||||
import com.tangem.core.ui.components.rows.RowContentContainer
|
import com.tangem.core.ui.components.rows.RowContentContainer
|
||||||
import com.tangem.core.ui.components.rows.RowText
|
import com.tangem.core.ui.components.rows.RowText
|
||||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||||
import com.tangem.core.ui.extensions.resolveReference
|
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.stringResourceSafe
|
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||||
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
|
||||||
|
|
@ -106,7 +105,11 @@ private fun LazyListScope.allMyNetworksList(
|
||||||
showDivider = index != allMyNetworks.lastIndex,
|
showDivider = index != allMyNetworks.lastIndex,
|
||||||
) {
|
) {
|
||||||
InputRowChecked(
|
InputRowChecked(
|
||||||
text = item.text,
|
text = when (item) {
|
||||||
|
is EarnFilterNetworkUM.AllNetworks -> TextReference.Res(R.string.earn_filter_all_networks)
|
||||||
|
is EarnFilterNetworkUM.MyNetworks -> TextReference.Res(R.string.earn_filter_my_networks)
|
||||||
|
is EarnFilterNetworkUM.Network -> TextReference.Str(item.text)
|
||||||
|
},
|
||||||
checked = item.isSelected,
|
checked = item.isSelected,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -170,13 +173,13 @@ private fun LazyListScope.specificNetworksList(
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.size(22.dp),
|
modifier = Modifier.size(22.dp),
|
||||||
imageVector = ImageVector.vectorResource(item.iconRes),
|
imageVector = ImageVector.vectorResource(item.iconRes),
|
||||||
contentDescription = item.symbol.resolveReference(),
|
contentDescription = item.symbol,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
RowText(
|
RowText(
|
||||||
mainText = item.text.resolveReference(),
|
mainText = item.text,
|
||||||
secondText = item.symbol.resolveReference(),
|
secondText = item.symbol,
|
||||||
accentMainText = true,
|
accentMainText = true,
|
||||||
accentSecondText = false,
|
accentSecondText = false,
|
||||||
)
|
)
|
||||||
|
|
@ -208,30 +211,20 @@ private fun Preview() {
|
||||||
isShown = true,
|
isShown = true,
|
||||||
onDismissRequest = {},
|
onDismissRequest = {},
|
||||||
content = EarnFilterByNetworkBottomSheetContentUM(
|
content = EarnFilterByNetworkBottomSheetContentUM(
|
||||||
selectedNetwork = EarnFilterNetworkUM.AllNetworks(
|
|
||||||
text = resourceReference(R.string.earn_filter_all_networks),
|
|
||||||
isSelected = true,
|
|
||||||
),
|
|
||||||
networks = persistentListOf(
|
networks = persistentListOf(
|
||||||
EarnFilterNetworkUM.AllNetworks(
|
EarnFilterNetworkUM.AllNetworks(isSelected = true),
|
||||||
text = resourceReference(R.string.earn_filter_all_networks),
|
EarnFilterNetworkUM.MyNetworks(isSelected = false),
|
||||||
isSelected = true,
|
|
||||||
),
|
|
||||||
EarnFilterNetworkUM.MyNetworks(
|
|
||||||
text = stringReference("My network"),
|
|
||||||
isSelected = false,
|
|
||||||
),
|
|
||||||
EarnFilterNetworkUM.Network(
|
EarnFilterNetworkUM.Network(
|
||||||
id = "ethereum",
|
id = "ethereum",
|
||||||
text = stringReference("Ethereum"),
|
text = "Ethereum",
|
||||||
symbol = stringReference("ETH"),
|
symbol = "ETH",
|
||||||
iconRes = R.drawable.img_btc_22,
|
iconRes = R.drawable.img_btc_22,
|
||||||
isSelected = false,
|
isSelected = false,
|
||||||
),
|
),
|
||||||
EarnFilterNetworkUM.Network(
|
EarnFilterNetworkUM.Network(
|
||||||
id = "polygon",
|
id = "polygon",
|
||||||
text = stringReference("Polygon"),
|
text = "Polygon",
|
||||||
symbol = stringReference("MATIC"),
|
symbol = "MATIC",
|
||||||
iconRes = R.drawable.img_btc_22,
|
iconRes = R.drawable.img_btc_22,
|
||||||
isSelected = false,
|
isSelected = false,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
internal data class EarnFilterByNetworkBottomSheetContentUM(
|
internal data class EarnFilterByNetworkBottomSheetContentUM(
|
||||||
val selectedNetwork: EarnFilterNetworkUM,
|
|
||||||
val networks: ImmutableList<EarnFilterNetworkUM>,
|
val networks: ImmutableList<EarnFilterNetworkUM>,
|
||||||
val onOptionClick: (EarnFilterNetworkUM) -> Unit,
|
val onOptionClick: (EarnFilterNetworkUM) -> Unit,
|
||||||
) : TangemBottomSheetConfigContent
|
) : TangemBottomSheetConfigContent
|
||||||
|
|
@ -1,29 +1,25 @@
|
||||||
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.core.ui.extensions.TextReference
|
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
internal sealed class EarnFilterNetworkUM {
|
internal sealed class EarnFilterNetworkUM {
|
||||||
|
|
||||||
abstract val text: TextReference
|
|
||||||
abstract val isSelected: Boolean
|
abstract val isSelected: Boolean
|
||||||
|
|
||||||
data class AllNetworks(
|
data class AllNetworks(
|
||||||
override val text: TextReference,
|
|
||||||
override val isSelected: Boolean,
|
override val isSelected: Boolean,
|
||||||
) : EarnFilterNetworkUM()
|
) : EarnFilterNetworkUM()
|
||||||
|
|
||||||
data class MyNetworks(
|
data class MyNetworks(
|
||||||
override val text: TextReference,
|
|
||||||
override val isSelected: Boolean,
|
override val isSelected: Boolean,
|
||||||
) : EarnFilterNetworkUM()
|
) : EarnFilterNetworkUM()
|
||||||
|
|
||||||
data class Network(
|
data class Network(
|
||||||
val id: String,
|
|
||||||
override val text: TextReference,
|
|
||||||
val symbol: TextReference,
|
|
||||||
val iconRes: Int,
|
|
||||||
override val isSelected: Boolean,
|
override val isSelected: Boolean,
|
||||||
|
val id: String,
|
||||||
|
val text: String,
|
||||||
|
val symbol: String,
|
||||||
|
val iconRes: Int,
|
||||||
) : EarnFilterNetworkUM()
|
) : EarnFilterNetworkUM()
|
||||||
}
|
}
|
||||||
|
|
@ -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.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
|
@ -10,16 +9,11 @@ internal data class EarnUM(
|
||||||
val bestOpportunities: EarnBestOpportunitiesUM,
|
val bestOpportunities: EarnBestOpportunitiesUM,
|
||||||
val selectedTypeFilter: EarnFilterTypeUM,
|
val selectedTypeFilter: EarnFilterTypeUM,
|
||||||
val selectedNetworkFilter: EarnFilterNetworkUM,
|
val selectedNetworkFilter: EarnFilterNetworkUM,
|
||||||
val filterByTypeBottomSheet: TangemBottomSheetConfig,
|
|
||||||
val filterByNetworkBottomSheet: TangemBottomSheetConfig,
|
|
||||||
val onBackClick: () -> Unit,
|
val onBackClick: () -> Unit,
|
||||||
val onNetworkFilterClick: () -> Unit,
|
val onNetworkFilterClick: () -> Unit,
|
||||||
val onTypeFilterClick: () -> Unit,
|
val onTypeFilterClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val selectedNetworkFilterText: TextReference
|
|
||||||
get() = selectedNetworkFilter.text
|
|
||||||
|
|
||||||
val selectedTypeFilterText: TextReference
|
val selectedTypeFilterText: TextReference
|
||||||
get() = selectedTypeFilter.text
|
get() = selectedTypeFilter.text
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue