Updated on 2026-08-14
This commit is contained in:
commit
bfd903b43c
595 changed files with 12755 additions and 19837 deletions
|
|
@ -9,7 +9,7 @@ import com.tangem.core.decompose.model.getOrCreateModel
|
|||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.OrganizeTokensModel
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensScreen
|
||||
import com.tangem.feature.wallet.child.organizetokens.ui.OrganizeTokensScreen
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal class OrganizeTokensComponent(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.analytics
|
||||
package com.tangem.feature.wallet.child.organizetokens.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.model
|
||||
package com.tangem.feature.wallet.child.organizetokens.entity
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
|
|
@ -1,27 +1,9 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.model
|
||||
package com.tangem.feature.wallet.child.organizetokens.entity
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Deprecated("Use OrganizeTokensListUM instead, will be removed in future releases")
|
||||
@Immutable
|
||||
internal sealed class OrganizeTokensListState {
|
||||
abstract val items: PersistentList<DraggableItem>
|
||||
|
||||
data class GroupedByNetwork(
|
||||
override val items: PersistentList<DraggableItem>,
|
||||
) : OrganizeTokensListState()
|
||||
|
||||
data class Ungrouped(
|
||||
override val items: PersistentList<DraggableItem>,
|
||||
) : OrganizeTokensListState()
|
||||
|
||||
data object Empty : OrganizeTokensListState() {
|
||||
override val items: PersistentList<DraggableItem> = persistentListOf()
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
internal sealed interface OrganizeTokensListUM {
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.model
|
||||
package com.tangem.feature.wallet.child.organizetokens.entity
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
|
|
@ -7,7 +7,6 @@ import org.burnoutcrew.reorderable.ItemPosition
|
|||
@Immutable
|
||||
internal data class OrganizeTokensState(
|
||||
val onBackClick: () -> Unit,
|
||||
val itemsState: OrganizeTokensListState,
|
||||
val tokenListUM: OrganizeTokensListUM,
|
||||
val header: HeaderConfig,
|
||||
val actions: ActionsConfig,
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.tangem.feature.wallet.child.organizetokens.model
|
||||
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrencies
|
||||
import com.tangem.domain.models.account.filterCryptoPortfolio
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensListUM
|
||||
|
||||
internal class CryptoCurrenciesIdsResolver {
|
||||
|
||||
fun resolve(tokensListUM: OrganizeTokensListUM, accountStatusList: AccountStatusList?): AccountCryptoCurrencies {
|
||||
if (accountStatusList == null) return emptyMap()
|
||||
|
||||
val draggableTokens = when (tokensListUM) {
|
||||
OrganizeTokensListUM.EmptyList -> return emptyMap()
|
||||
is OrganizeTokensListUM.AccountList,
|
||||
is OrganizeTokensListUM.TokensList,
|
||||
-> tokensListUM.items.filterIsInstance<DraggableItem.Token>()
|
||||
}
|
||||
|
||||
return accountStatusList.accountStatuses
|
||||
.filterCryptoPortfolio()
|
||||
.filter { it.tokenList != TokenList.Empty }
|
||||
.associate { accountStatus ->
|
||||
val currenciesById = accountStatus.flattenCurrencies().associateBy { it.currency.id.value }
|
||||
|
||||
accountStatus.account to draggableTokens
|
||||
.asSequence()
|
||||
.filter { it.accountId == accountStatus.account.accountId.value }
|
||||
.mapNotNull { token -> currenciesById[token.id]?.currency }
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens
|
||||
package com.tangem.feature.wallet.child.organizetokens.model
|
||||
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import org.burnoutcrew.reorderable.ItemPosition
|
||||
|
||||
internal interface OrganizeTokensIntents {
|
||||
|
|
@ -7,35 +7,21 @@ import com.tangem.core.analytics.models.AnalyticsParam
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.account.status.usecase.ApplyTokenListSortingUseCaseV2
|
||||
import com.tangem.domain.account.status.usecase.ToggleTokenListGroupingUseCaseV2
|
||||
import com.tangem.domain.account.status.usecase.ToggleTokenListSortingUseCaseV2
|
||||
import com.tangem.domain.account.status.usecase.ApplyTokenListSortingUseCase
|
||||
import com.tangem.domain.account.status.usecase.ToggleTokenListGroupingUseCase
|
||||
import com.tangem.domain.account.status.usecase.ToggleTokenListSortingUseCase
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.models.TokensSortType
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
|
||||
import com.tangem.domain.tokens.GetTokenListUseCase
|
||||
import com.tangem.domain.tokens.ToggleTokenListGroupingUseCase
|
||||
import com.tangem.domain.tokens.ToggleTokenListSortingUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.feature.wallet.child.organizetokens.OrganizeTokensComponent
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensIntents
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensStateHolder
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.analytics.PortfolioOrganizeTokensAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.CryptoCurrenciesIdsResolver
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.disableSortingByBalance
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.dnd.DragAndDropAdapter
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.dnd.DragAndDropAdapterV2
|
||||
import com.tangem.feature.wallet.child.organizetokens.analytics.PortfolioOrganizeTokensAnalyticsEvent
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.dnd.DragAndDropAdapter
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
|
@ -49,18 +35,13 @@ internal class OrganizeTokensModel @Inject constructor(
|
|||
paramsContainer: ParamsContainer,
|
||||
getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val getTokenListUseCase: GetTokenListUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
private val toggleTokenListGroupingUseCase: ToggleTokenListGroupingUseCase,
|
||||
private val toggleTokenListSortingUseCase: ToggleTokenListSortingUseCase,
|
||||
private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
private val toggleTokenListGroupingUseCaseV2: ToggleTokenListGroupingUseCaseV2,
|
||||
private val toggleTokenListSortingUseCaseV2: ToggleTokenListSortingUseCaseV2,
|
||||
private val applyTokenListSortingUseCaseV2: ApplyTokenListSortingUseCaseV2,
|
||||
) : Model(), OrganizeTokensIntents {
|
||||
|
||||
private val selectedAppCurrencyFlow = createSelectedAppCurrencyFlow()
|
||||
|
|
@ -68,24 +49,17 @@ internal class OrganizeTokensModel @Inject constructor(
|
|||
private var isBalanceHidden = true
|
||||
|
||||
private val dragAndDropAdapter = DragAndDropAdapter(
|
||||
listStateProvider = Provider { uiState.value.itemsState },
|
||||
)
|
||||
|
||||
private val dragAndDropAdapterV2 = DragAndDropAdapterV2(
|
||||
tokenListUMProvider = Provider { uiState.value.tokenListUM },
|
||||
)
|
||||
|
||||
private val stateHolder = OrganizeTokensStateHolder(
|
||||
intents = this,
|
||||
dragAndDropIntents = dragAndDropAdapter,
|
||||
dragAndDropAdapterV2 = dragAndDropAdapterV2,
|
||||
dragAndDropAdapter = dragAndDropAdapter,
|
||||
appCurrencyProvider = Provider(selectedAppCurrencyFlow::value),
|
||||
accountsFeatureToggles = accountsFeatureToggles,
|
||||
)
|
||||
|
||||
private val userWalletId = paramsContainer.require<OrganizeTokensComponent.Params>().userWalletId
|
||||
|
||||
private var cachedTokenList: TokenList? = null
|
||||
private var cachedAccountStatusList: AccountStatusList? = null
|
||||
|
||||
private var isAccountsModeEnabled: Boolean = false
|
||||
|
|
@ -113,68 +87,35 @@ internal class OrganizeTokensModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onSortClick() {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val list = cachedAccountStatusList ?: return
|
||||
if (list.sortType == TokensSortType.BALANCE) return
|
||||
val list = cachedAccountStatusList ?: return
|
||||
if (list.sortType == TokensSortType.BALANCE) return
|
||||
|
||||
analyticsEventsHandler.send(PortfolioOrganizeTokensAnalyticsEvent.ByBalance())
|
||||
analyticsEventsHandler.send(PortfolioOrganizeTokensAnalyticsEvent.ByBalance())
|
||||
|
||||
modelScope.launch {
|
||||
toggleTokenListSortingUseCaseV2(list).fold(
|
||||
ifLeft = stateHolder::updateStateWithError,
|
||||
ifRight = {
|
||||
stateHolder.updateStateAfterTokenListSortingV2(it, isAccountsModeEnabled)
|
||||
cachedAccountStatusList = it
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val list = cachedTokenList ?: return
|
||||
if (list.sortedBy == TokensSortType.BALANCE) return
|
||||
|
||||
analyticsEventsHandler.send(PortfolioOrganizeTokensAnalyticsEvent.ByBalance())
|
||||
|
||||
modelScope.launch {
|
||||
toggleTokenListSortingUseCase(list).fold(
|
||||
ifLeft = stateHolder::updateStateWithError,
|
||||
ifRight = {
|
||||
stateHolder.updateStateAfterTokenListSorting(it)
|
||||
cachedTokenList = it
|
||||
},
|
||||
)
|
||||
}
|
||||
modelScope.launch {
|
||||
toggleTokenListSortingUseCase(list).fold(
|
||||
ifLeft = stateHolder::updateStateWithError,
|
||||
ifRight = { accountStatusList ->
|
||||
stateHolder.updateStateAfterTokenListSorting(accountStatusList, isAccountsModeEnabled)
|
||||
cachedAccountStatusList = accountStatusList
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGroupClick() {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val list = cachedAccountStatusList ?: return
|
||||
val list = cachedAccountStatusList ?: return
|
||||
|
||||
analyticsEventsHandler.send(PortfolioOrganizeTokensAnalyticsEvent.Group())
|
||||
analyticsEventsHandler.send(PortfolioOrganizeTokensAnalyticsEvent.Group())
|
||||
|
||||
modelScope.launch {
|
||||
toggleTokenListGroupingUseCaseV2(list).fold(
|
||||
ifLeft = stateHolder::updateStateWithError,
|
||||
ifRight = {
|
||||
stateHolder.updateStateAfterTokenListSortingV2(it, isAccountsModeEnabled)
|
||||
cachedAccountStatusList = it
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val list = cachedTokenList ?: return
|
||||
|
||||
analyticsEventsHandler.send(PortfolioOrganizeTokensAnalyticsEvent.Group())
|
||||
|
||||
modelScope.launch {
|
||||
toggleTokenListGroupingUseCase(list).fold(
|
||||
ifLeft = stateHolder::updateStateWithError,
|
||||
ifRight = {
|
||||
stateHolder.updateStateAfterTokenListSorting(it)
|
||||
cachedTokenList = it
|
||||
},
|
||||
)
|
||||
}
|
||||
modelScope.launch {
|
||||
toggleTokenListGroupingUseCase(list).fold(
|
||||
ifLeft = stateHolder::updateStateWithError,
|
||||
ifRight = { accountStatusList ->
|
||||
stateHolder.updateStateAfterTokenListSorting(accountStatusList, isAccountsModeEnabled)
|
||||
cachedAccountStatusList = accountStatusList
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,39 +124,20 @@ internal class OrganizeTokensModel @Inject constructor(
|
|||
stateHolder.updateStateToDisplayProgress()
|
||||
val resolver = CryptoCurrenciesIdsResolver()
|
||||
val isSortedByBalance = uiState.value.header.isSortedByBalance
|
||||
val tokensListUM = uiState.value.tokenListUM
|
||||
|
||||
val result = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val tokensListUM = uiState.value.tokenListUM
|
||||
val isGroupedByNetwork = tokensListUM.isGrouped
|
||||
|
||||
val isGroupedByNetwork = tokensListUM.isGrouped
|
||||
sendAnalyticsEvent(
|
||||
isGroupedByNetwork = isGroupedByNetwork,
|
||||
isSortedByBalance = isSortedByBalance,
|
||||
)
|
||||
|
||||
sendAnalyticsEvent(
|
||||
isGroupedByNetwork = isGroupedByNetwork,
|
||||
isSortedByBalance = isSortedByBalance,
|
||||
)
|
||||
|
||||
applyTokenListSortingUseCaseV2(
|
||||
sortedTokensIdsByAccount = resolver.resolveV2(tokensListUM, cachedAccountStatusList),
|
||||
isGroupedByNetwork = isGroupedByNetwork,
|
||||
isSortedByBalance = isSortedByBalance,
|
||||
)
|
||||
} else {
|
||||
val listState = uiState.value.itemsState
|
||||
|
||||
val isGroupedByNetwork = listState is OrganizeTokensListState.GroupedByNetwork
|
||||
|
||||
sendAnalyticsEvent(
|
||||
isGroupedByNetwork = isGroupedByNetwork,
|
||||
isSortedByBalance = isSortedByBalance,
|
||||
)
|
||||
|
||||
applyTokenListSortingUseCase(
|
||||
userWalletId = userWalletId,
|
||||
sortedTokensIds = resolver.resolve(listState, cachedTokenList),
|
||||
isGroupedByNetwork = isGroupedByNetwork,
|
||||
isSortedByBalance = isSortedByBalance,
|
||||
)
|
||||
}
|
||||
val result = applyTokenListSortingUseCase(
|
||||
sortedTokensIdsByAccount = resolver.resolve(tokensListUM, cachedAccountStatusList),
|
||||
isGroupedByNetwork = isGroupedByNetwork,
|
||||
isSortedByBalance = isSortedByBalance,
|
||||
)
|
||||
|
||||
result.fold(
|
||||
ifLeft = stateHolder::updateStateWithError,
|
||||
|
|
@ -235,72 +157,35 @@ internal class OrganizeTokensModel @Inject constructor(
|
|||
|
||||
private fun bootstrapTokenList() {
|
||||
modelScope.launch {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val accountList = singleAccountStatusListSupplier.getSyncOrNull(
|
||||
SingleAccountStatusListProducer.Params(userWalletId),
|
||||
) ?: return@launch
|
||||
val accountList = singleAccountStatusListSupplier.getSyncOrNull(
|
||||
SingleAccountStatusListProducer.Params(userWalletId),
|
||||
) ?: return@launch
|
||||
|
||||
isAccountsModeEnabled = isAccountsModeEnabledUseCase.invokeSync()
|
||||
isAccountsModeEnabled = isAccountsModeEnabledUseCase.invokeSync()
|
||||
|
||||
stateHolder.updateStateWithAccountList(
|
||||
accountStatusList = accountList,
|
||||
isAccountsModeEnabled = isAccountsModeEnabled,
|
||||
)
|
||||
stateHolder.updateStateWithAccountList(
|
||||
accountStatusList = accountList,
|
||||
isAccountsModeEnabled = isAccountsModeEnabled,
|
||||
)
|
||||
|
||||
cachedAccountStatusList = accountList
|
||||
} else {
|
||||
val tokenList = getTokenList() ?: return@launch
|
||||
stateHolder.updateStateWithTokenList(tokenList)
|
||||
cachedTokenList = tokenList
|
||||
}
|
||||
cachedAccountStatusList = accountList
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getTokenList(): TokenList? {
|
||||
val maybeTokenList = getTokenListUseCase.launch(userWalletId)
|
||||
.filterNot(Lce<TokenListError, TokenList>::isLoading)
|
||||
.firstOrNull()
|
||||
?: return null
|
||||
|
||||
return maybeTokenList
|
||||
.onError(stateHolder::updateStateWithError)
|
||||
.getOrNull(isPartialContentAccepted = false)
|
||||
}
|
||||
|
||||
private fun bootstrapDragAndDropUpdates() {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
dragAndDropAdapterV2.dragAndDropUpdates
|
||||
.distinctUntilChanged()
|
||||
.onEach { (type, updatedListState) ->
|
||||
disableSortingByBalanceIfListChangedV2(type)
|
||||
dragAndDropAdapter.dragAndDropUpdates
|
||||
.distinctUntilChanged()
|
||||
.onEach { (type, updatedListState) ->
|
||||
disableSortingByBalanceIfListChanged(type)
|
||||
|
||||
stateHolder.updateStateWithManualSortingV2(updatedListState)
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
} else {
|
||||
dragAndDropAdapter.dragAndDropUpdates
|
||||
.distinctUntilChanged()
|
||||
.onEach { (type, updatedListState) ->
|
||||
disableSortingByBalanceIfListChanged(type)
|
||||
|
||||
stateHolder.updateStateWithManualSorting(updatedListState)
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
stateHolder.updateStateWithManualSorting(updatedListState)
|
||||
}
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun disableSortingByBalanceIfListChanged(dragOperationType: DragAndDropAdapter.DragOperation.Type) {
|
||||
if (dragOperationType !is DragAndDropAdapter.DragOperation.Type.End) return
|
||||
|
||||
if (uiState.value.header.isSortedByBalance && dragOperationType.isItemsOrderChanged) {
|
||||
cachedTokenList = cachedTokenList?.disableSortingByBalance()
|
||||
stateHolder.disableSortingByBalance()
|
||||
}
|
||||
}
|
||||
|
||||
private fun disableSortingByBalanceIfListChangedV2(dragOperationType: DragAndDropAdapterV2.DragOperation.Type) {
|
||||
if (dragOperationType !is DragAndDropAdapterV2.DragOperation.Type.End) return
|
||||
|
||||
if (uiState.value.header.isSortedByBalance && dragOperationType.isItemsOrderChanged) {
|
||||
cachedAccountStatusList = cachedAccountStatusList?.copy(sortType = TokensSortType.NONE)
|
||||
stateHolder.disableSortingByBalance()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
package com.tangem.feature.wallet.child.organizetokens.model
|
||||
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.core.ui.event.triggeredEvent
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.error.TokenListSortingError
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensListUM
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.converter.InProgressStateConverter
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.converter.TokenListToStateConverter
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.converter.error.TokenListSortingErrorConverter
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.dnd.DragAndDropAdapter
|
||||
import com.tangem.utils.Provider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
internal class OrganizeTokensStateHolder(
|
||||
private val intents: OrganizeTokensIntents,
|
||||
private val dragAndDropAdapter: DragAndDropAdapter,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
) {
|
||||
|
||||
private val stateFlowInternal: MutableStateFlow<OrganizeTokensState> = MutableStateFlow(getInitialState())
|
||||
|
||||
private val inProgressStateConverter by lazy { InProgressStateConverter() }
|
||||
|
||||
private val tokenListSortingErrorConverter by lazy {
|
||||
TokenListSortingErrorConverter(Provider(stateFlowInternal::value), inProgressStateConverter)
|
||||
}
|
||||
|
||||
val stateFlow: StateFlow<OrganizeTokensState> = stateFlowInternal
|
||||
|
||||
fun updateStateWithAccountList(accountStatusList: AccountStatusList, isAccountsModeEnabled: Boolean) {
|
||||
updateState {
|
||||
TokenListToStateConverter(
|
||||
accountStatusList = accountStatusList,
|
||||
isAccountsMode = isAccountsModeEnabled,
|
||||
appCurrency = appCurrencyProvider(),
|
||||
).transform(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateStateAfterTokenListSorting(accountStatusList: AccountStatusList, isAccountsModeEnabled: Boolean) {
|
||||
updateState {
|
||||
TokenListToStateConverter(
|
||||
accountStatusList = accountStatusList,
|
||||
isAccountsMode = isAccountsModeEnabled,
|
||||
appCurrency = appCurrencyProvider(),
|
||||
).transform(this).copy(
|
||||
scrollListToTop = triggeredEvent(Unit, ::consumeScrollListToTopEvent),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateStateToDisplayProgress() {
|
||||
updateState { inProgressStateConverter.convert(value = this) }
|
||||
}
|
||||
|
||||
fun updateStateToHideProgress() {
|
||||
updateState { inProgressStateConverter.convertBack(value = this) }
|
||||
}
|
||||
|
||||
fun updateStateWithManualSorting(tokenListUM: OrganizeTokensListUM) {
|
||||
updateState { copy(tokenListUM = tokenListUM) }
|
||||
}
|
||||
|
||||
fun disableSortingByBalance() {
|
||||
updateState { copy(header = header.copy(isSortedByBalance = false)) }
|
||||
}
|
||||
|
||||
fun updateHiddenState(isBalanceHidden: Boolean) {
|
||||
updateState { copy(isBalanceHidden = isBalanceHidden) }
|
||||
}
|
||||
|
||||
fun updateStateWithError(error: TokenListSortingError) {
|
||||
updateState { tokenListSortingErrorConverter.convert(error) }
|
||||
}
|
||||
|
||||
private fun getInitialState(): OrganizeTokensState {
|
||||
return OrganizeTokensState(
|
||||
onBackClick = intents::onBackClick,
|
||||
tokenListUM = OrganizeTokensListUM.EmptyList,
|
||||
header = OrganizeTokensState.HeaderConfig(
|
||||
onSortClick = intents::onSortClick,
|
||||
onGroupClick = intents::onGroupClick,
|
||||
),
|
||||
actions = OrganizeTokensState.ActionsConfig(
|
||||
onApplyClick = intents::onApplyClick,
|
||||
onCancelClick = intents::onCancelClick,
|
||||
),
|
||||
dndConfig = OrganizeTokensState.DragAndDropConfig(
|
||||
onItemDragged = dragAndDropAdapter::onItemDragged,
|
||||
onItemDragStart = dragAndDropAdapter::onItemDraggingStart,
|
||||
onItemDragEnd = dragAndDropAdapter::onItemDraggingEnd,
|
||||
canDragItemOver = dragAndDropAdapter::canDragItemOver,
|
||||
),
|
||||
scrollListToTop = consumedEvent(),
|
||||
isBalanceHidden = true,
|
||||
)
|
||||
}
|
||||
|
||||
private inline fun updateState(block: OrganizeTokensState.() -> OrganizeTokensState) {
|
||||
stateFlowInternal.update(block)
|
||||
}
|
||||
|
||||
private fun consumeScrollListToTopEvent() {
|
||||
updateState { copy(scrollListToTop = consumedEvent()) }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.common
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.common
|
||||
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
|
||||
internal fun getGroupPlaceholder(index: Int, accountId: String = ""): DraggableItem.Placeholder {
|
||||
return DraggableItem.Placeholder(
|
||||
|
|
@ -1,36 +1,8 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.common
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.common
|
||||
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
|
||||
internal fun List<DraggableItem>.uniteItems(): List<DraggableItem> {
|
||||
val items = prepareItems()
|
||||
val lastItemIndex = items.lastIndex
|
||||
|
||||
return prepareItems().mapIndexed { index, item ->
|
||||
val mode = when (index) {
|
||||
// 1 index is used because the first item is always a placeholder, check `prepareItems()` function
|
||||
1 -> DraggableItem.RoundingMode.Top()
|
||||
lastItemIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> when (item) {
|
||||
is DraggableItem.Portfolio,
|
||||
is DraggableItem.Placeholder,
|
||||
-> DraggableItem.RoundingMode.None
|
||||
is DraggableItem.GroupHeader -> DraggableItem.RoundingMode.Top(showGap = true)
|
||||
is DraggableItem.Token -> if (items[index + 1] is DraggableItem.Placeholder) {
|
||||
DraggableItem.RoundingMode.Bottom(showGap = true)
|
||||
} else {
|
||||
DraggableItem.RoundingMode.None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item
|
||||
.updateRoundingMode(mode)
|
||||
.updateShadowVisibility(show = false)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun List<DraggableItem>.uniteItemsV2(isAccountsMode: Boolean): List<DraggableItem> {
|
||||
internal fun List<DraggableItem>.uniteItems(isAccountsMode: Boolean): List<DraggableItem> {
|
||||
val items = this
|
||||
val lastItemIndex = items.lastIndex
|
||||
|
||||
|
|
@ -92,27 +64,6 @@ internal fun List<DraggableItem>.divideMovingItem(movingItem: DraggableItem): Li
|
|||
return mutableList
|
||||
}
|
||||
|
||||
/**
|
||||
* !!! Workaround !!!
|
||||
*
|
||||
* We need to add a [DraggableItem.Placeholder] (since it's not draggable) as the first item of the list, because the
|
||||
* [DND library](https://github.com/aclassen/ComposeReorderable) glitches when a user tries to drag the first item.
|
||||
*
|
||||
* @since 07.09.2023
|
||||
* */
|
||||
private fun List<DraggableItem>.prepareItems(): List<DraggableItem> {
|
||||
val firstPlaceholderId = "initial_placeholder"
|
||||
val items = this
|
||||
|
||||
return mutableListOf<DraggableItem>().apply {
|
||||
add(DraggableItem.Placeholder(firstPlaceholderId))
|
||||
|
||||
val itemsWithoutFirstPlaceholder = items.filterNot { it.id == firstPlaceholderId }
|
||||
|
||||
addAll(itemsWithoutFirstPlaceholder)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applying rounding to tokens
|
||||
*
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.common
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.common
|
||||
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.feature.wallet.child.organizetokens.model.common
|
||||
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensListUM
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
internal inline fun OrganizeTokensListUM.updateItems(
|
||||
update: (PersistentList<DraggableItem>) -> List<DraggableItem>,
|
||||
): OrganizeTokensListUM {
|
||||
val updatedItems = update(items).toPersistentList()
|
||||
|
||||
return when (this) {
|
||||
is OrganizeTokensListUM.AccountList -> copy(items = updatedItems)
|
||||
is OrganizeTokensListUM.TokensList -> copy(items = updatedItems)
|
||||
OrganizeTokensListUM.EmptyList -> this
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.common
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.common
|
||||
|
||||
import com.tangem.domain.models.TokensSortType
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.converter
|
||||
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensState
|
||||
import com.tangem.utils.converter.TwoWayConverter
|
||||
|
||||
internal class InProgressStateConverter : TwoWayConverter<OrganizeTokensState, OrganizeTokensState> {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.converter
|
||||
|
||||
import com.tangem.common.ui.account.AccountCryptoPortfolioItemStateConverter
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
|
|
@ -8,17 +8,17 @@ import com.tangem.domain.models.TokensSortType
|
|||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.account.filterCryptoPortfolio
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListUM
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getGroupPlaceholder
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.uniteItemsV2
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items.OrganizedTokenListConverter
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensListUM
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.getGroupPlaceholder
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.uniteItems
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.converter.items.OrganizedTokenListConverter
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
internal class TokenListToStateConverterV2(
|
||||
internal class TokenListToStateConverter(
|
||||
private val accountStatusList: AccountStatusList,
|
||||
private val isAccountsMode: Boolean,
|
||||
private val appCurrency: AppCurrency,
|
||||
|
|
@ -82,7 +82,7 @@ internal class AccountTokenItemConverter(
|
|||
emptyList()
|
||||
}
|
||||
}.toList()
|
||||
.uniteItemsV2(true).toPersistentList(),
|
||||
.uniteItems(true).toPersistentList(),
|
||||
)
|
||||
} else {
|
||||
OrganizeTokensListUM.TokensList(
|
||||
|
|
@ -92,7 +92,7 @@ internal class AccountTokenItemConverter(
|
|||
add(getGroupPlaceholder(accountId = value.mainAccount.accountId.value, index = -1))
|
||||
}
|
||||
addAll(organizedTokenListConverter.convert(value.mainAccount))
|
||||
}.uniteItemsV2(false)
|
||||
}.uniteItems(false)
|
||||
.toPersistentList(),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.error
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.converter.error
|
||||
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.InProgressStateConverter
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.converter.InProgressStateConverter
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.error
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.converter.error
|
||||
|
||||
import com.tangem.domain.tokens.error.TokenListSortingError
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.InProgressStateConverter
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.converter.InProgressStateConverter
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.converter.items
|
||||
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
|
|
@ -11,14 +11,14 @@ import com.tangem.domain.appcurrency.model.AppCurrency
|
|||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.common.getTotalWithRewardsStakingBalance
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getGroupHeaderId
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getTokenItemId
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.getGroupHeaderId
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.getTokenItemId
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal class CryptoCurrencyToDraggableItemConverterV2(
|
||||
internal class CryptoCurrencyToDraggableItemConverter(
|
||||
private val appCurrency: AppCurrency,
|
||||
) : Converter<AccountCryptoCurrencyStatus, DraggableItem.Token> {
|
||||
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.converter.items
|
||||
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.tokenlist.TokenList.GroupedByNetwork.NetworkGroup
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getGroupHeaderId
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getGroupPlaceholder
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.getGroupHeaderId
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.getGroupPlaceholder
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
internal class NetworkGroupToDraggableItemsConverterV2(
|
||||
private val itemConverter: CryptoCurrencyToDraggableItemConverterV2,
|
||||
internal class NetworkGroupToDraggableItemsConverter(
|
||||
private val itemConverter: CryptoCurrencyToDraggableItemConverter,
|
||||
) : Converter<Pair<Account.CryptoPortfolio, NetworkGroup>, List<DraggableItem>> {
|
||||
|
||||
override fun convert(value: Pair<Account.CryptoPortfolio, NetworkGroup>): List<DraggableItem> {
|
||||
|
|
@ -42,10 +42,10 @@ internal class NetworkGroupToDraggableItemsConverterV2(
|
|||
|
||||
private fun createTokens(account: Account.CryptoPortfolio, group: NetworkGroup): List<DraggableItem.Token> {
|
||||
return itemConverter.convertList(
|
||||
group.currencies.map {
|
||||
group.currencies.map { currencyStatus ->
|
||||
AccountCryptoCurrencyStatus(
|
||||
account = account,
|
||||
status = it,
|
||||
status = currencyStatus,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.converter.items
|
||||
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrencyStatus
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.account.AccountStatus
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -14,9 +14,9 @@ internal class OrganizedTokenListConverter(
|
|||
private val appCurrency: AppCurrency,
|
||||
) : Converter<AccountStatus.CryptoPortfolio, PersistentList<DraggableItem>> {
|
||||
|
||||
private val tokensConverter by lazy { CryptoCurrencyToDraggableItemConverterV2(appCurrency) }
|
||||
private val tokensConverter by lazy { CryptoCurrencyToDraggableItemConverter(appCurrency) }
|
||||
private val groupsConverter by lazy {
|
||||
NetworkGroupToDraggableItemsConverterV2(tokensConverter)
|
||||
NetworkGroupToDraggableItemsConverter(tokensConverter)
|
||||
}
|
||||
|
||||
override fun convert(value: AccountStatus.CryptoPortfolio): PersistentList<DraggableItem> {
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.dnd
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.dnd
|
||||
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.DragAndDropIntents
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListUM
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.divideMovingItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.uniteItemsV2
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.updateItems
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensListUM
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.DragAndDropIntents
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.divideMovingItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.uniteItems
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.updateItems
|
||||
import com.tangem.utils.Provider
|
||||
import kotlinx.collections.immutable.mutate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -13,7 +13,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import org.burnoutcrew.reorderable.ItemPosition
|
||||
|
||||
internal class DragAndDropAdapterV2(
|
||||
internal class DragAndDropAdapter(
|
||||
private val tokenListUMProvider: Provider<OrganizeTokensListUM>,
|
||||
) : DragAndDropIntents {
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ internal class DragAndDropAdapterV2(
|
|||
is DraggableItem.Placeholder,
|
||||
is DraggableItem.Portfolio,
|
||||
-> items
|
||||
is DraggableItem.GroupHeader -> draggableGroupsOperations.collapseGroupV2(items, item)
|
||||
is DraggableItem.GroupHeader -> draggableGroupsOperations.collapseGroup(items, item)
|
||||
.divideMovingItem(item)
|
||||
is DraggableItem.Token -> items.divideMovingItem(item)
|
||||
}
|
||||
|
|
@ -96,11 +96,11 @@ internal class DragAndDropAdapterV2(
|
|||
updateListState(DragOperation.Type.End(isItemsOrderChanged = checkIsItemsOrderChanged())) {
|
||||
when (draggingItem) {
|
||||
is DraggableItem.GroupHeader -> {
|
||||
draggableGroupsOperations.expandGroupsV2(items)
|
||||
.uniteItemsV2(tokenListUM is OrganizeTokensListUM.AccountList)
|
||||
draggableGroupsOperations.expandGroups(items)
|
||||
.uniteItems(tokenListUM is OrganizeTokensListUM.AccountList)
|
||||
}
|
||||
is DraggableItem.Token -> {
|
||||
items.uniteItemsV2(tokenListUM is OrganizeTokensListUM.AccountList)
|
||||
items.uniteItems(tokenListUM is OrganizeTokensListUM.AccountList)
|
||||
}
|
||||
is DraggableItem.Placeholder,
|
||||
is DraggableItem.Portfolio,
|
||||
|
|
@ -1,9 +1,8 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.dnd
|
||||
package com.tangem.feature.wallet.child.organizetokens.model.dnd
|
||||
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.divideMovingItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getGroupPlaceholder
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.uniteItems
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.divideMovingItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.model.common.getGroupPlaceholder
|
||||
|
||||
internal class DraggableGroupsOperations {
|
||||
|
||||
|
|
@ -24,47 +23,9 @@ internal class DraggableGroupsOperations {
|
|||
return itemsWithoutGroupTokens.divideMovingItem(movingGroup)
|
||||
}
|
||||
|
||||
fun collapseGroupV2(items: List<DraggableItem>, movingGroup: DraggableItem.GroupHeader): List<DraggableItem> {
|
||||
if (!groupIdToTokens.isNullOrEmpty()) return items
|
||||
|
||||
groupIdToTokens = items
|
||||
.asSequence()
|
||||
.filterIsInstance<DraggableItem.Token>()
|
||||
.groupBy { it.groupId }
|
||||
|
||||
val itemsWithoutGroupTokens = items.filterNot {
|
||||
it is DraggableItem.Token && it.groupId == movingGroup.id
|
||||
}
|
||||
|
||||
return itemsWithoutGroupTokens.divideMovingItem(movingGroup)
|
||||
}
|
||||
|
||||
fun expandGroups(items: List<DraggableItem>): List<DraggableItem> {
|
||||
if (groupIdToTokens.isNullOrEmpty()) return items
|
||||
|
||||
val currentGroups = items.filterIsInstance<DraggableItem.GroupHeader>()
|
||||
val lastGroupIndex = currentGroups.lastIndex
|
||||
|
||||
val expandedGroups = currentGroups
|
||||
.flatMapIndexed { index, group ->
|
||||
buildList {
|
||||
add(group)
|
||||
addAll(groupIdToTokens?.get(group.id).orEmpty())
|
||||
if (index != lastGroupIndex) {
|
||||
add(getGroupPlaceholder(index))
|
||||
}
|
||||
}
|
||||
}
|
||||
.uniteItems()
|
||||
|
||||
groupIdToTokens = null
|
||||
|
||||
return expandedGroups
|
||||
}
|
||||
|
||||
fun expandGroupsV2(items: List<DraggableItem>): List<DraggableItem> {
|
||||
if (groupIdToTokens.isNullOrEmpty()) return items
|
||||
|
||||
val accountList = items.filterIsInstance<DraggableItem.Portfolio>()
|
||||
val currentGroups = items.filterIsInstance<DraggableItem.GroupHeader>()
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens
|
||||
package com.tangem.feature.wallet.child.organizetokens.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.activity.compose.BackHandler
|
||||
|
|
@ -44,12 +44,11 @@ import com.tangem.core.ui.res.TangemThemePreview
|
|||
import com.tangem.core.ui.test.OrganizeTokensScreenTestTags
|
||||
import com.tangem.core.ui.utils.WindowInsetsZero
|
||||
import com.tangem.core.ui.utils.lazyListItemPosition
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensListUM
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.child.organizetokens.ui.preview.OrganizeTokensPreview
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListUM
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
import org.burnoutcrew.reorderable.rememberReorderableLazyListState
|
||||
import org.burnoutcrew.reorderable.reorderable
|
||||
|
|
@ -76,7 +75,6 @@ internal fun OrganizeTokensScreen(state: OrganizeTokensState, modifier: Modifier
|
|||
.fillMaxSize(),
|
||||
listState = tokensListState,
|
||||
tokensListUM = state.tokenListUM,
|
||||
state = state.itemsState,
|
||||
dndConfig = state.dndConfig,
|
||||
isBalanceHidden = state.isBalanceHidden,
|
||||
)
|
||||
|
|
@ -98,18 +96,13 @@ internal fun OrganizeTokensScreen(state: OrganizeTokensState, modifier: Modifier
|
|||
@Composable
|
||||
private fun TokenList(
|
||||
listState: LazyListState,
|
||||
state: OrganizeTokensListState,
|
||||
tokensListUM: OrganizeTokensListUM,
|
||||
dndConfig: OrganizeTokensState.DragAndDropConfig,
|
||||
isBalanceHidden: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val tokenList = if (tokensListUM !is OrganizeTokensListUM.EmptyList) {
|
||||
tokensListUM.items
|
||||
} else {
|
||||
state.items
|
||||
}
|
||||
val tokenList = tokensListUM.items
|
||||
Box(modifier = modifier) {
|
||||
val onDragEnd: (Int, Int) -> Unit = remember {
|
||||
{ _, _ ->
|
||||
|
|
@ -423,8 +416,8 @@ private fun OrganizeTokensScreenPreview(
|
|||
|
||||
private class OrganizeTokensStateProvider : CollectionPreviewParameterProvider<OrganizeTokensState>(
|
||||
collection = listOf(
|
||||
WalletPreviewData.organizeTokensState,
|
||||
WalletPreviewData.groupedOrganizeTokensState,
|
||||
OrganizeTokensPreview.stateAccounts,
|
||||
OrganizeTokensPreview.state,
|
||||
),
|
||||
)
|
||||
// endregion Preview
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
package com.tangem.feature.wallet.child.organizetokens.ui.preview
|
||||
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.DraggableItem
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensListUM
|
||||
import com.tangem.feature.wallet.child.organizetokens.entity.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import java.util.UUID
|
||||
|
||||
internal object OrganizeTokensPreview {
|
||||
|
||||
private const val networksSize = 10
|
||||
private const val tokensSize = 3
|
||||
|
||||
private val tokenItemDragState by lazy {
|
||||
TokenItemState.Draggable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
iconState = CurrencyIconState.TokenIcon(
|
||||
url = null,
|
||||
topBadgeIconResId = R.drawable.img_polygon_22,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "3 172,14 $"),
|
||||
)
|
||||
}
|
||||
|
||||
private val draggableItems: PersistentList<DraggableItem> by lazy {
|
||||
List(networksSize) { it }
|
||||
.flatMap { index ->
|
||||
val lastNetworkIndex = networksSize - 1
|
||||
val lastTokenIndex = tokensSize - 1
|
||||
val networkNumber = index + 1
|
||||
|
||||
val group = DraggableItem.GroupHeader(
|
||||
id = networkNumber,
|
||||
networkName = "$networkNumber",
|
||||
|
||||
roundingMode = when (index) {
|
||||
0 -> DraggableItem.RoundingMode.Top()
|
||||
lastNetworkIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
},
|
||||
accountId = "account_$networkNumber",
|
||||
)
|
||||
|
||||
val tokens: MutableList<DraggableItem.Token> = mutableListOf()
|
||||
repeat(times = tokensSize) { i ->
|
||||
val tokenNumber = i + 1
|
||||
tokens.add(
|
||||
DraggableItem.Token(
|
||||
tokenItemState = tokenItemDragState.copy(
|
||||
id = "${group.id}_token_$tokenNumber",
|
||||
titleState = TokenItemState.TitleState.Content(
|
||||
text = stringReference(value = "Token $tokenNumber from $networkNumber network"),
|
||||
),
|
||||
),
|
||||
groupId = group.id,
|
||||
accountId = "account_$networkNumber",
|
||||
roundingMode = when {
|
||||
i == lastTokenIndex && index == lastNetworkIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val divider = DraggableItem.Placeholder(
|
||||
id = "divider_$networkNumber",
|
||||
accountId = "account_$networkNumber",
|
||||
)
|
||||
|
||||
buildList {
|
||||
add(group)
|
||||
addAll(tokens)
|
||||
if (index != lastNetworkIndex) {
|
||||
add(divider)
|
||||
}
|
||||
}
|
||||
}
|
||||
.toPersistentList()
|
||||
}
|
||||
|
||||
val stateAccounts by lazy {
|
||||
OrganizeTokensState(
|
||||
onBackClick = {},
|
||||
tokenListUM = OrganizeTokensListUM.AccountList(
|
||||
items = draggableItems,
|
||||
isGrouped = true,
|
||||
),
|
||||
header = OrganizeTokensState.HeaderConfig(
|
||||
onSortClick = {},
|
||||
onGroupClick = {},
|
||||
),
|
||||
dndConfig = OrganizeTokensState.DragAndDropConfig(
|
||||
onItemDragged = { _, _ -> },
|
||||
onItemDragStart = {},
|
||||
canDragItemOver = { _, _ -> false },
|
||||
onItemDragEnd = {},
|
||||
),
|
||||
actions = OrganizeTokensState.ActionsConfig(
|
||||
onApplyClick = {},
|
||||
onCancelClick = {},
|
||||
),
|
||||
scrollListToTop = consumedEvent(),
|
||||
isBalanceHidden = true,
|
||||
)
|
||||
}
|
||||
|
||||
val state by lazy {
|
||||
stateAccounts.copy(
|
||||
tokenListUM = OrganizeTokensListUM.TokensList(
|
||||
items = draggableItems,
|
||||
isGrouped = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.arkivanov.decompose.ExperimentalDecomposeApi
|
||||
import com.arkivanov.decompose.extensions.compose.subscribeAsState
|
||||
import com.arkivanov.decompose.router.slot.childSlot
|
||||
import com.arkivanov.decompose.router.slot.dismiss
|
||||
|
|
@ -14,6 +15,7 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.decompose.context.child
|
||||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.DesignFeatureToggles
|
||||
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
|
|
@ -23,12 +25,11 @@ import com.tangem.feature.wallet.child.wallet.model.WalletModel
|
|||
import com.tangem.feature.wallet.navigation.WalletRoute
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.WalletScreen
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.WalletScreen2
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.KycRejectedComponent
|
||||
import com.tangem.feature.walletsettings.component.RenameWalletComponent
|
||||
import com.tangem.features.biometry.AskBiometryComponent
|
||||
import com.tangem.features.feed.entry.components.FeedEntryComponent
|
||||
import com.tangem.features.feed.entry.featuretoggle.FeedFeatureToggle
|
||||
import com.tangem.features.markets.entry.MarketsEntryComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsBottomSheetComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsParams
|
||||
import com.tangem.features.tokenreceive.TokenReceiveComponent
|
||||
|
|
@ -38,18 +39,18 @@ import dagger.assisted.AssistedFactory
|
|||
import dagger.assisted.AssistedInject
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalDecomposeApi::class)
|
||||
@Suppress("LongParameterList")
|
||||
internal class WalletComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted navigate: (WalletRoute) -> Unit,
|
||||
marketsEntryComponentFactory: MarketsEntryComponent.Factory,
|
||||
feedEntryComponentFactory: FeedEntryComponent.Factory,
|
||||
private val renameWalletComponentFactory: RenameWalletComponent.Factory,
|
||||
private val askBiometryComponentFactory: AskBiometryComponent.Factory,
|
||||
private val pushNotificationsBottomSheetComponent: PushNotificationsBottomSheetComponent.Factory,
|
||||
private val tokenReceiveComponentFactory: TokenReceiveComponent.Factory,
|
||||
private val yieldSupplyDepositedWarningComponent: YieldSupplyDepositedWarningComponent.Factory,
|
||||
private val feedFeatureToggle: FeedFeatureToggle,
|
||||
private val designFeatureToggles: DesignFeatureToggles,
|
||||
) : ComposableContentComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: WalletModel = getOrCreateModel()
|
||||
|
|
@ -60,9 +61,6 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
entryRoute = null,
|
||||
)
|
||||
}
|
||||
private val marketsEntryComponent by lazy {
|
||||
marketsEntryComponentFactory.create(child("marketsEntryComponent"))
|
||||
}
|
||||
|
||||
init {
|
||||
lifecycle.subscribe(model.screenLifecycleProvider)
|
||||
|
|
@ -148,18 +146,33 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
var headerSize by remember { mutableStateOf(0.dp) }
|
||||
val dialog by dialog.subscribeAsState()
|
||||
|
||||
WalletScreen(
|
||||
state = model.uiState.collectAsStateWithLifecycle().value,
|
||||
bottomSheetContent = {
|
||||
BottomSheetContent(
|
||||
bottomSheetState = bottomSheetState,
|
||||
onHeaderSizeChange = { headerSize = it },
|
||||
modifier = modifier,
|
||||
)
|
||||
},
|
||||
bottomSheetHeaderHeightProvider = { headerSize },
|
||||
onBottomSheetStateChange = { bottomSheetState.value = it },
|
||||
)
|
||||
if (designFeatureToggles.isRedesignEnabled) {
|
||||
WalletScreen2(
|
||||
state = model.uiState.collectAsStateWithLifecycle().value,
|
||||
bottomSheetContent = {
|
||||
BottomSheetContent(
|
||||
bottomSheetState = bottomSheetState,
|
||||
onHeaderSizeChange = { headerSize = it },
|
||||
modifier = modifier,
|
||||
)
|
||||
},
|
||||
bottomSheetHeaderHeightProvider = { headerSize },
|
||||
onBottomSheetStateChange = { bottomSheetState.value = it },
|
||||
)
|
||||
} else {
|
||||
WalletScreen(
|
||||
state = model.uiState.collectAsStateWithLifecycle().value,
|
||||
bottomSheetContent = {
|
||||
BottomSheetContent(
|
||||
bottomSheetState = bottomSheetState,
|
||||
onHeaderSizeChange = { headerSize = it },
|
||||
modifier = modifier,
|
||||
)
|
||||
},
|
||||
bottomSheetHeaderHeightProvider = { headerSize },
|
||||
onBottomSheetStateChange = { bottomSheetState.value = it },
|
||||
)
|
||||
}
|
||||
|
||||
when (val dialog = dialog.child?.instance) {
|
||||
is ComposableDialogComponent -> dialog.Dialog()
|
||||
|
|
@ -174,19 +187,11 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
onHeaderSizeChange: (Dp) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (feedFeatureToggle.isFeedEnabled) {
|
||||
feedEntryComponent.BottomSheetContent(
|
||||
bottomSheetState = bottomSheetState,
|
||||
onHeaderSizeChange = onHeaderSizeChange,
|
||||
modifier = modifier,
|
||||
)
|
||||
} else {
|
||||
marketsEntryComponent.BottomSheetContent(
|
||||
bottomSheetState = bottomSheetState,
|
||||
onHeaderSizeChange = onHeaderSizeChange,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
feedEntryComponent.BottomSheetContent(
|
||||
bottomSheetState = bottomSheetState,
|
||||
onHeaderSizeChange = onHeaderSizeChange,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import com.tangem.core.analytics.utils.TrackingContextProxy
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.supplier.SingleAccountListSupplier
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
import com.tangem.domain.apptheme.GetAppThemeModeUseCase
|
||||
|
|
@ -31,7 +30,10 @@ import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
|||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.SelectedWalletAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.OnrampStatusFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletContentFetcher
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletNameMigrationUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig
|
||||
|
|
@ -43,11 +45,8 @@ import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSend
|
|||
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.KycRejectedCallbacks
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
|
||||
import com.tangem.features.biometry.AskBiometryComponent
|
||||
import com.tangem.features.feed.entry.featuretoggle.FeedFeatureToggle
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import com.tangem.features.wallet.deeplink.WalletDeepLinkActionListener
|
||||
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.coroutines.*
|
||||
import kotlinx.coroutines.*
|
||||
|
|
@ -80,7 +79,6 @@ internal class WalletModel @Inject constructor(
|
|||
private val walletNameMigrationUseCase: WalletNameMigrationUseCase,
|
||||
private val refreshMultiCurrencyWalletQuotesUseCase: RefreshMultiCurrencyWalletQuotesUseCase,
|
||||
private val walletImageResolver: WalletImageResolver,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val onrampStatusFactory: OnrampStatusFactory,
|
||||
private val analyticsEventsHandler: AnalyticsEventHandler,
|
||||
private val walletContentFetcher: WalletContentFetcher,
|
||||
|
|
@ -90,17 +88,13 @@ internal class WalletModel @Inject constructor(
|
|||
private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase,
|
||||
private val getIsHuaweiDeviceWithoutGoogleServicesUseCase: GetIsHuaweiDeviceWithoutGoogleServicesUseCase,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
|
||||
private val yieldSupplyApyUpdateUseCase: YieldSupplyApyUpdateUseCase,
|
||||
private val tangemPayOnboardingRepository: OnboardingRepository,
|
||||
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val tangemPayMainScreenCustomerInfoUseCase: TangemPayMainScreenCustomerInfoUseCase,
|
||||
private val getAppThemeModeUseCase: GetAppThemeModeUseCase,
|
||||
private val trackingContextProxy: TrackingContextProxy,
|
||||
private val singleAccountListSupplier: SingleAccountListSupplier,
|
||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
private val feedFeatureToggle: FeedFeatureToggle,
|
||||
private val bindRefcodeWithWalletUseCase: BindRefcodeWithWalletUseCase,
|
||||
private val appsFlyerStore: AppsFlyerStore,
|
||||
val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
|
|
@ -116,13 +110,12 @@ internal class WalletModel @Inject constructor(
|
|||
private val refreshWalletJobHolder = JobHolder()
|
||||
private val updateTangemPayJobHolder = JobHolder()
|
||||
|
||||
private var needToRefreshWallet = false
|
||||
private var expressTxStatusTaskScheduler = SingleTaskScheduler<Unit>()
|
||||
private var shouldRefreshWallet = false
|
||||
private val expressTxStatusTaskScheduler = SingleTaskScheduler<Unit>()
|
||||
|
||||
init {
|
||||
trackScreenOpened()
|
||||
|
||||
updateMarketToggle()
|
||||
suggestToOpenMarkets()
|
||||
|
||||
maybeMigrateNames()
|
||||
|
|
@ -159,17 +152,9 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateMarketToggle() {
|
||||
stateHolder.update {
|
||||
it.copy(isNewMarketEnabled = feedFeatureToggle.isFeedEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateYieldSupplyApy() {
|
||||
if (yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled) {
|
||||
modelScope.launch(dispatchers.default) {
|
||||
yieldSupplyApyUpdateUseCase()
|
||||
}
|
||||
modelScope.launch(dispatchers.default) {
|
||||
yieldSupplyApyUpdateUseCase()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +173,6 @@ internal class WalletModel @Inject constructor(
|
|||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
|
||||
tokenListStore.clear()
|
||||
stateHolder.clear()
|
||||
walletScreenContentLoader.cancelAll()
|
||||
}
|
||||
|
|
@ -267,9 +251,9 @@ internal class WalletModel @Inject constructor(
|
|||
getWalletsUseCase()
|
||||
.conflate()
|
||||
.distinctUntilChanged()
|
||||
.map {
|
||||
.map { userWallets ->
|
||||
walletsUpdateActionResolver.resolve(
|
||||
wallets = it,
|
||||
wallets = userWallets,
|
||||
currentState = stateHolder.value,
|
||||
)
|
||||
}
|
||||
|
|
@ -361,7 +345,7 @@ internal class WalletModel @Inject constructor(
|
|||
refreshWalletJobHolder.cancel()
|
||||
when {
|
||||
isBackground -> needToRefreshTimer()
|
||||
needToRefreshWallet && !isBackground -> {
|
||||
shouldRefreshWallet && !isBackground -> {
|
||||
triggerRefreshWalletQuotes()
|
||||
}
|
||||
}
|
||||
|
|
@ -394,7 +378,6 @@ internal class WalletModel @Inject constructor(
|
|||
* Update state each time a user opens/returns to wallet screen
|
||||
* and every minute while user stays on the main screen
|
||||
*/
|
||||
if (!tangemPayFeatureToggles.isTangemPayEnabled) return
|
||||
|
||||
combine(
|
||||
flow = screenLifecycleProvider.isBackgroundState,
|
||||
|
|
@ -433,12 +416,12 @@ internal class WalletModel @Inject constructor(
|
|||
private fun needToRefreshTimer() {
|
||||
modelScope.launch {
|
||||
delay(REFRESH_WALLET_BACKGROUND_TIMER_MILLIS)
|
||||
needToRefreshWallet = true
|
||||
shouldRefreshWallet = true
|
||||
}.saveIn(refreshWalletJobHolder)
|
||||
}
|
||||
|
||||
private fun triggerRefreshWalletQuotes() {
|
||||
needToRefreshWallet = false
|
||||
shouldRefreshWallet = false
|
||||
val state = stateHolder.uiState.value
|
||||
val wallet = state.wallets.getOrNull(state.selectedWalletIndex) ?: return
|
||||
modelScope.launch {
|
||||
|
|
@ -469,7 +452,6 @@ internal class WalletModel @Inject constructor(
|
|||
// refresh loader to use actual user wallet
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = action.selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
isRefresh = true,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
|
|
@ -517,10 +499,9 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun reloadWarnings(action: WalletsUpdateActionResolver.Action.ReloadWallets) {
|
||||
action.wallets.forEach {
|
||||
action.wallets.forEach { userWallet ->
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = it,
|
||||
clickIntents = clickIntents,
|
||||
userWallet = userWallet,
|
||||
coroutineScope = modelScope,
|
||||
isRefresh = true,
|
||||
)
|
||||
|
|
@ -539,7 +520,6 @@ internal class WalletModel @Inject constructor(
|
|||
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = action.selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
|
||||
|
|
@ -566,11 +546,9 @@ internal class WalletModel @Inject constructor(
|
|||
|
||||
private fun reinitializeNewWallet(action: WalletsUpdateActionResolver.Action.ReinitializeNewWallet) {
|
||||
walletScreenContentLoader.cancel(action.prevWalletId)
|
||||
tokenListStore.remove(action.prevWalletId)
|
||||
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = action.selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
|
||||
|
|
@ -589,11 +567,9 @@ internal class WalletModel @Inject constructor(
|
|||
private fun reinitializeWallets(action: WalletsUpdateActionResolver.Action.ReinitializeWallets) {
|
||||
action.wallets.forEach { userWallet ->
|
||||
walletScreenContentLoader.cancel(userWallet.walletId)
|
||||
tokenListStore.remove(userWallet.walletId)
|
||||
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
|
||||
|
|
@ -610,39 +586,20 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun addWallet(action: WalletsUpdateActionResolver.Action.AddWallet) {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
fetchWalletContent(userWallet = action.selectedWallet)
|
||||
fetchWalletContent(userWallet = action.selectedWallet)
|
||||
|
||||
stateHolder.update(
|
||||
AddWalletTransformer(
|
||||
userWallet = action.selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
),
|
||||
)
|
||||
|
||||
walletScreenContentLoader.load(
|
||||
stateHolder.update(
|
||||
AddWalletTransformer(
|
||||
userWallet = action.selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
} else {
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = action.selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
walletImageResolver = walletImageResolver,
|
||||
),
|
||||
)
|
||||
|
||||
fetchWalletContent(userWallet = action.selectedWallet)
|
||||
|
||||
stateHolder.update(
|
||||
AddWalletTransformer(
|
||||
userWallet = action.selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
walletImageResolver = walletImageResolver,
|
||||
),
|
||||
)
|
||||
}
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = action.selectedWallet,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
|
||||
scrollToWallet(prevIndex = action.prevWalletIndex, newIndex = action.selectedWalletIndex) {
|
||||
stateHolder.update {
|
||||
|
|
@ -655,11 +612,9 @@ internal class WalletModel @Inject constructor(
|
|||
|
||||
private fun deleteWallet(action: WalletsUpdateActionResolver.Action.DeleteWallet) {
|
||||
walletScreenContentLoader.cancel(action.deletedWalletId)
|
||||
tokenListStore.remove(action.deletedWalletId)
|
||||
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = action.selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
|
||||
|
|
@ -703,7 +658,6 @@ internal class WalletModel @Inject constructor(
|
|||
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = action.selectedWallet,
|
||||
clickIntents = clickIntents,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletType
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -110,7 +111,7 @@ internal class WalletsUpdateActionResolver @Inject constructor(
|
|||
when (walletState) {
|
||||
is WalletState.MultiCurrency -> {
|
||||
val wallet = wallets.firstOrNull { it.walletId == walletState.walletCardState.id }
|
||||
walletState.type == WalletState.MultiCurrency.WalletType.Hot && wallet is UserWallet.Cold
|
||||
walletState.type == WalletType.Hot && wallet is UserWallet.Cold
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
|
@ -212,7 +213,7 @@ internal class WalletsUpdateActionResolver @Inject constructor(
|
|||
val previousState = state.wallets.firstOrNull { it.walletCardState.id == wallet.walletId }
|
||||
?: return@filter false
|
||||
wallet is UserWallet.Cold && previousState is WalletState.MultiCurrency &&
|
||||
previousState.type == WalletState.MultiCurrency.WalletType.Hot
|
||||
previousState.type == WalletType.Hot
|
||||
}
|
||||
return Action.ReinitializeWallets(selectedWallet, walletsToUpdate)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogCon
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayHideOnboardingStateTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayRefreshNeededStateTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.TangemPayRefreshShowProgressTransformer
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -64,7 +63,6 @@ internal interface TangemPayIntents {
|
|||
@ModelScoped
|
||||
internal class TangemPayClickIntentsImplementor @Inject constructor(
|
||||
private val stateHolder: WalletStateController,
|
||||
private val featureToggles: TangemPayFeatureToggles,
|
||||
private val onboardingRepository: OnboardingRepository,
|
||||
private val produceInitialDataTangemPay: ProduceTangemPayInitialDataUseCase,
|
||||
private val getWalletMetainfoUseCase: GetWalletMetaInfoUseCase,
|
||||
|
|
@ -77,9 +75,7 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
|
|||
|
||||
override suspend fun onPullToRefresh() {
|
||||
val userWalletId = stateHolder.getSelectedWalletId()
|
||||
if (!featureToggles.isTangemPayEnabled ||
|
||||
!onboardingRepository.isTangemPayInitialDataProduced(userWalletId)
|
||||
) {
|
||||
if (!onboardingRepository.isTangemPayInitialDataProduced(userWalletId)) {
|
||||
return
|
||||
}
|
||||
tangemPayMainScreenCustomerInfoUseCase.fetch(userWalletId)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ internal class WalletClickIntents @Inject constructor(
|
|||
private val currencyActionsClickIntentsImplementor: WalletCurrencyActionsClickIntentsImplementor,
|
||||
private val contentClickIntentsImplementor: WalletContentClickIntentsImplementor,
|
||||
private val pushPermissionClickIntentsImplementor: WalletPushPermissionClickIntentsImplementor,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val stateController: WalletStateController,
|
||||
private val walletScreenContentLoader: WalletScreenContentLoader,
|
||||
private val getSelectedWalletSyncUseCase: GetSelectedWalletSyncUseCase,
|
||||
private val selectWalletUseCase: SelectWalletUseCase,
|
||||
|
|
@ -62,7 +62,7 @@ internal class WalletClickIntents @Inject constructor(
|
|||
|
||||
fun onWalletChange(index: Int, onlyState: Boolean) {
|
||||
if (onlyState) {
|
||||
stateHolder.update { it.copy(selectedWalletIndex = index) }
|
||||
stateController.update { it.copy(selectedWalletIndex = index) }
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -70,27 +70,23 @@ internal class WalletClickIntents @Inject constructor(
|
|||
launch { neverToShowWalletsScrollPreview() }
|
||||
|
||||
val maybeUserWallet = selectWalletUseCase(
|
||||
userWalletId = stateHolder.value.wallets[index].walletCardState.id,
|
||||
userWalletId = stateController.value.wallets[index].walletCardState.id,
|
||||
)
|
||||
|
||||
stateHolder.update { it.copy(selectedWalletIndex = index) }
|
||||
stateController.update { it.copy(selectedWalletIndex = index) }
|
||||
|
||||
maybeUserWallet.onRight {
|
||||
if (!it.isLocked) {
|
||||
launch { walletContentFetcher(userWalletId = it.walletId) }
|
||||
maybeUserWallet.onRight { userWallet ->
|
||||
if (!userWallet.isLocked) {
|
||||
launch { walletContentFetcher(userWalletId = userWallet.walletId) }
|
||||
}
|
||||
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = it,
|
||||
clickIntents = this@WalletClickIntents,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
walletScreenContentLoader.load(userWallet = userWallet, coroutineScope = modelScope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onRefreshSwipe(showRefreshState: Boolean) {
|
||||
when (stateHolder.getSelectedWallet()) {
|
||||
when (stateController.getSelectedWallet()) {
|
||||
is WalletState.MultiCurrency.Content -> {
|
||||
refreshMultiCurrencyContent(showRefreshState)
|
||||
}
|
||||
|
|
@ -111,7 +107,7 @@ internal class WalletClickIntents @Inject constructor(
|
|||
private fun refreshMultiCurrencyContent(showRefreshState: Boolean) {
|
||||
val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
|
||||
|
||||
stateHolder.update(
|
||||
stateController.update(
|
||||
SetRefreshStateTransformer(userWalletId = userWallet.walletId, isRefreshing = showRefreshState),
|
||||
)
|
||||
|
||||
|
|
@ -126,7 +122,7 @@ internal class WalletClickIntents @Inject constructor(
|
|||
}
|
||||
.awaitAll()
|
||||
|
||||
stateHolder.update(
|
||||
stateController.update(
|
||||
SetRefreshStateTransformer(userWalletId = userWallet.walletId, isRefreshing = false),
|
||||
)
|
||||
}
|
||||
|
|
@ -137,7 +133,7 @@ internal class WalletClickIntents @Inject constructor(
|
|||
private fun refreshSingleCurrencyContent(showRefreshState: Boolean) {
|
||||
val userWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
|
||||
|
||||
stateHolder.update(
|
||||
stateController.update(
|
||||
SetRefreshStateTransformer(userWalletId = userWallet.walletId, isRefreshing = showRefreshState),
|
||||
)
|
||||
|
||||
|
|
@ -147,12 +143,11 @@ internal class WalletClickIntents @Inject constructor(
|
|||
onrampStatusFactory.updateOnrmapTransactionStatuses(userWallet)
|
||||
walletScreenContentLoader.load(
|
||||
userWallet = userWallet,
|
||||
clickIntents = this@WalletClickIntents,
|
||||
isRefresh = true,
|
||||
coroutineScope = modelScope,
|
||||
)
|
||||
|
||||
stateHolder.update(
|
||||
stateController.update(
|
||||
SetRefreshStateTransformer(userWalletId = userWallet.walletId, isRefreshing = false),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,10 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
|
|||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.event.MainScreenAnalyticsEvent
|
||||
import com.tangem.core.analytics.models.event.OfframpAnalyticsEvent
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.clipboard.ClipboardManager
|
||||
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
|
@ -20,7 +22,6 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
import com.tangem.core.ui.message.DialogMessage
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
|
|
@ -36,13 +37,12 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
|||
import com.tangem.domain.models.network.NetworkAddress
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.offramp.GetOfframpUrlUseCase
|
||||
import com.tangem.domain.onramp.model.OnrampSource
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.promo.models.StoryContentIds
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.staking.model.StakingOption
|
||||
import com.tangem.domain.tokens.*
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.domain.tokens.model.ScenarioUnavailabilityReason
|
||||
import com.tangem.domain.tokens.model.analytics.TokenReceiveCopyActionSource
|
||||
import com.tangem.domain.tokens.model.analytics.TokenReceiveNewAnalyticsEvent
|
||||
|
|
@ -63,7 +63,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.CloseBottomSheetTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
|
||||
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -136,19 +135,17 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
private val getOfframpUrlUseCase: GetOfframpUrlUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val vibratorHapticManager: VibratorHapticManager,
|
||||
private val clipboardManager: ClipboardManager,
|
||||
private val appRouter: AppRouter,
|
||||
private val rampStateManager: RampStateManager,
|
||||
private val saveViewedTokenReceiveWarningUseCase: SaveViewedTokenReceiveWarningUseCase,
|
||||
private val receiveAddressesFactory: ReceiveAddressesFactory,
|
||||
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
|
||||
private val needShowYieldSupplyDepositedWarningUseCase: NeedShowYieldSupplyDepositedWarningUseCase,
|
||||
private val saveViewedYieldSupplyWarningUseCase: SaveViewedYieldSupplyWarningUseCase,
|
||||
private val isCryptoCurrencyCoinCouldHide: IsCryptoCurrencyCoinCouldHideUseCase,
|
||||
private val removeCurrencyUseCase: RemoveCurrencyUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
|
|
@ -289,23 +286,19 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
|
||||
override fun onPerformHideToken(userWalletId: UserWalletId, cryptoCurrencyStatus: CryptoCurrencyStatus) {
|
||||
modelScope.launch(dispatchers.io) {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val accountId = getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = userWalletId,
|
||||
currency = cryptoCurrencyStatus.currency,
|
||||
)
|
||||
.map { it.account.accountId }
|
||||
.getOrNull()
|
||||
val accountId = getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = userWalletId,
|
||||
currency = cryptoCurrencyStatus.currency,
|
||||
)
|
||||
.map { it.account.accountId }
|
||||
.getOrNull()
|
||||
|
||||
if (accountId == null) {
|
||||
Timber.e("Account ID is null, cannot hide currency ${cryptoCurrencyStatus.currency.id}")
|
||||
return@launch
|
||||
}
|
||||
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, remove = cryptoCurrencyStatus.currency)
|
||||
} else {
|
||||
removeCurrencyUseCase(userWalletId, cryptoCurrencyStatus.currency)
|
||||
if (accountId == null) {
|
||||
Timber.e("Account ID is null, cannot hide currency ${cryptoCurrencyStatus.currency.id}")
|
||||
return@launch
|
||||
}
|
||||
|
||||
manageCryptoCurrenciesUseCase(accountId = accountId, remove = cryptoCurrencyStatus.currency)
|
||||
.fold(
|
||||
ifLeft = {
|
||||
walletEventSender.send(
|
||||
|
|
@ -335,12 +328,13 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
|
||||
showErrorIfDemoModeOrElse {
|
||||
modelScope.launch(dispatchers.main) {
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.Sell(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
appCurrencyCode = getSelectedAppCurrencyUseCase.unwrap().code,
|
||||
),
|
||||
)
|
||||
getOfframpUrlUseCase(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
appCurrencyCode = getSelectedAppCurrencyUseCase.unwrap().code,
|
||||
).onRight { url ->
|
||||
urlOpener.openUrl(url)
|
||||
analyticsEventHandler.send(OfframpAnalyticsEvent.ScreenOpened)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -472,9 +466,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
|
||||
override fun onMultiWalletSwapClick(userWalletId: UserWalletId) {
|
||||
val selectedWallet = stateHolder.getSelectedWallet() as? WalletState.MultiCurrency.Content ?: return
|
||||
val tokenListState = selectedWallet.tokensListState
|
||||
|
||||
when (tokenListState) {
|
||||
when (val tokenListState = selectedWallet.tokensListState) {
|
||||
is WalletTokensListState.ContentState.Content -> checkSwapCryptoAvailability(
|
||||
tokenCount = tokenListState.items.count { it is TokensListItemUM.Token },
|
||||
)
|
||||
|
|
@ -663,8 +655,7 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
}
|
||||
|
||||
private suspend fun needShowYieldSupplyWarning(cryptoCurrencyStatus: CryptoCurrencyStatus): Boolean {
|
||||
return yieldSupplyFeatureToggles.isYieldSupplyFeatureEnabled &&
|
||||
needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus)
|
||||
return needShowYieldSupplyDepositedWarningUseCase(cryptoCurrencyStatus)
|
||||
}
|
||||
|
||||
private fun navigateToSend(cryptoCurrencyStatus: CryptoCurrencyStatus, userWalletId: UserWalletId) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.account
|
||||
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusSupplier
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
|
|
@ -9,7 +8,6 @@ import javax.inject.Inject
|
|||
|
||||
@ModelScoped
|
||||
internal class AccountDependencies @Inject constructor(
|
||||
val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
val expandedAccountsHolder: ExpandedAccountsHolder,
|
||||
val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
|
|
|
|||
|
|
@ -1,24 +1,11 @@
|
|||
package com.tangem.feature.wallet.presentation.common
|
||||
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListUM
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import java.util.UUID
|
||||
|
||||
@Suppress("LargeClass")
|
||||
internal object WalletPreviewData {
|
||||
|
|
@ -68,135 +55,6 @@ internal object WalletPreviewData {
|
|||
)
|
||||
}
|
||||
|
||||
private val tokenItemDragState by lazy {
|
||||
TokenItemState.Draggable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
iconState = CurrencyIconState.TokenIcon(
|
||||
url = null,
|
||||
topBadgeIconResId = R.drawable.img_polygon_22,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
),
|
||||
titleState = TokenItemState.TitleState.Content(text = stringReference(value = "Polygon")),
|
||||
subtitle2State = TokenItemState.Subtitle2State.TextContent(text = "3 172,14 $"),
|
||||
)
|
||||
}
|
||||
|
||||
private const val networksSize = 10
|
||||
private const val tokensSize = 3
|
||||
private val draggableItems: PersistentList<DraggableItem> by lazy {
|
||||
List(networksSize) { it }
|
||||
.flatMap { index ->
|
||||
val lastNetworkIndex = networksSize - 1
|
||||
val lastTokenIndex = tokensSize - 1
|
||||
val networkNumber = index + 1
|
||||
|
||||
val group = DraggableItem.GroupHeader(
|
||||
id = networkNumber,
|
||||
networkName = "$networkNumber",
|
||||
|
||||
roundingMode = when (index) {
|
||||
0 -> DraggableItem.RoundingMode.Top()
|
||||
lastNetworkIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
},
|
||||
accountId = "account_$networkNumber",
|
||||
)
|
||||
|
||||
val tokens: MutableList<DraggableItem.Token> = mutableListOf()
|
||||
repeat(times = tokensSize) { i ->
|
||||
val tokenNumber = i + 1
|
||||
tokens.add(
|
||||
DraggableItem.Token(
|
||||
tokenItemState = tokenItemDragState.copy(
|
||||
id = "${group.id}_token_$tokenNumber",
|
||||
titleState = TokenItemState.TitleState.Content(
|
||||
text = stringReference(value = "Token $tokenNumber from $networkNumber network"),
|
||||
),
|
||||
),
|
||||
groupId = group.id,
|
||||
accountId = "account_$networkNumber",
|
||||
roundingMode = when {
|
||||
i == lastTokenIndex && index == lastNetworkIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val divider = DraggableItem.Placeholder(
|
||||
id = "divider_$networkNumber",
|
||||
accountId = "account_$networkNumber",
|
||||
)
|
||||
|
||||
buildList {
|
||||
add(group)
|
||||
addAll(tokens)
|
||||
if (index != lastNetworkIndex) {
|
||||
add(divider)
|
||||
}
|
||||
}
|
||||
}
|
||||
.toPersistentList()
|
||||
}
|
||||
|
||||
private val draggableTokens by lazy {
|
||||
draggableItems
|
||||
.filterIsInstance<DraggableItem.Token>()
|
||||
.toMutableList()
|
||||
.also {
|
||||
it[0] = it[0].copy(roundingMode = DraggableItem.RoundingMode.Top())
|
||||
}
|
||||
.toPersistentList()
|
||||
}
|
||||
|
||||
val groupedOrganizeTokensState by lazy {
|
||||
OrganizeTokensState(
|
||||
onBackClick = {},
|
||||
itemsState = OrganizeTokensListState.GroupedByNetwork(
|
||||
items = draggableItems,
|
||||
),
|
||||
tokenListUM = OrganizeTokensListUM.EmptyList,
|
||||
header = OrganizeTokensState.HeaderConfig(
|
||||
onSortClick = {},
|
||||
onGroupClick = {},
|
||||
),
|
||||
dndConfig = OrganizeTokensState.DragAndDropConfig(
|
||||
onItemDragged = { _, _ -> },
|
||||
onItemDragStart = {},
|
||||
canDragItemOver = { _, _ -> false },
|
||||
onItemDragEnd = {},
|
||||
),
|
||||
actions = OrganizeTokensState.ActionsConfig(
|
||||
onApplyClick = {},
|
||||
onCancelClick = {},
|
||||
),
|
||||
scrollListToTop = consumedEvent(),
|
||||
isBalanceHidden = true,
|
||||
)
|
||||
}
|
||||
|
||||
val organizeTokensState by lazy {
|
||||
groupedOrganizeTokensState.copy(
|
||||
itemsState = OrganizeTokensListState.Ungrouped(
|
||||
items = draggableTokens,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val bottomSheet by lazy {
|
||||
TangemBottomSheetConfig(
|
||||
isShown = false,
|
||||
onDismissRequest = {},
|
||||
content = WalletBottomSheetConfig.UnlockWallets(
|
||||
onUnlockClick = {},
|
||||
onScanClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val actionsBottomSheet = ActionsBottomSheetConfig(
|
||||
actions = listOf(
|
||||
TokenActionButtonConfig(
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ internal object WalletScreenPreviewData {
|
|||
onItemClick = { },
|
||||
),
|
||||
tangemPayState = TangemPayState.Empty,
|
||||
type = WalletState.MultiCurrency.WalletType.Cold,
|
||||
type = WalletType.Cold,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -218,12 +218,12 @@ internal object WalletScreenPreviewData {
|
|||
singleWalletLockedState,
|
||||
multiWalletState,
|
||||
),
|
||||
wallets2 = persistentListOf(),
|
||||
onWalletChange = { _, _ -> },
|
||||
event = consumedEvent(),
|
||||
isHidingMode = false,
|
||||
showMarketsOnboarding = false,
|
||||
onDismissMarketsTooltip = {},
|
||||
isNewMarketEnabled = false,
|
||||
)
|
||||
|
||||
internal val accountScreenState =
|
||||
|
|
|
|||
|
|
@ -1,166 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens
|
||||
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.core.ui.event.triggeredEvent
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.error.TokenListSortingError
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListUM
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.InProgressStateConverter
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.TokenListToStateConverter
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.TokenListToStateConverterV2
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.error.TokenListErrorConverter
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.error.TokenListSortingErrorConverter
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items.CryptoCurrencyToDraggableItemConverter
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items.NetworkGroupToDraggableItemsConverter
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items.TokenListToListStateConverter
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.dnd.DragAndDropAdapterV2
|
||||
import com.tangem.utils.Provider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
internal class OrganizeTokensStateHolder(
|
||||
private val intents: OrganizeTokensIntents,
|
||||
private val dragAndDropIntents: DragAndDropIntents,
|
||||
private val dragAndDropAdapterV2: DragAndDropAdapterV2,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
) {
|
||||
|
||||
private val stateFlowInternal: MutableStateFlow<OrganizeTokensState> = MutableStateFlow(getInitialState())
|
||||
|
||||
private val tokenListConverter by lazy {
|
||||
val tokensConverter = CryptoCurrencyToDraggableItemConverter(appCurrencyProvider)
|
||||
val itemsConverter = TokenListToListStateConverter(
|
||||
tokensConverter = tokensConverter,
|
||||
groupsConverter = NetworkGroupToDraggableItemsConverter(tokensConverter),
|
||||
)
|
||||
|
||||
TokenListToStateConverter(Provider(stateFlowInternal::value), itemsConverter)
|
||||
}
|
||||
|
||||
private val inProgressStateConverter by lazy { InProgressStateConverter() }
|
||||
|
||||
private val tokenListErrorConverter by lazy {
|
||||
TokenListErrorConverter(Provider(stateFlowInternal::value), inProgressStateConverter)
|
||||
}
|
||||
|
||||
private val tokenListSortingErrorConverter by lazy {
|
||||
TokenListSortingErrorConverter(Provider(stateFlowInternal::value), inProgressStateConverter)
|
||||
}
|
||||
|
||||
val stateFlow: StateFlow<OrganizeTokensState> = stateFlowInternal
|
||||
|
||||
fun updateStateWithTokenList(tokenList: TokenList) {
|
||||
updateState { tokenListConverter.convert(tokenList) }
|
||||
}
|
||||
|
||||
fun updateStateWithAccountList(accountStatusList: AccountStatusList, isAccountsModeEnabled: Boolean) {
|
||||
updateState {
|
||||
TokenListToStateConverterV2(
|
||||
accountStatusList = accountStatusList,
|
||||
isAccountsMode = isAccountsModeEnabled,
|
||||
appCurrency = appCurrencyProvider(),
|
||||
).transform(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateStateAfterTokenListSorting(tokenList: TokenList) {
|
||||
updateState {
|
||||
tokenListConverter.convert(tokenList).copy(
|
||||
scrollListToTop = triggeredEvent(Unit, ::consumeScrollListToTopEvent),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateStateAfterTokenListSortingV2(accountStatusList: AccountStatusList, isAccountsModeEnabled: Boolean) {
|
||||
updateState {
|
||||
TokenListToStateConverterV2(
|
||||
accountStatusList = accountStatusList,
|
||||
isAccountsMode = isAccountsModeEnabled,
|
||||
appCurrency = appCurrencyProvider(),
|
||||
).transform(this).copy(
|
||||
scrollListToTop = triggeredEvent(Unit, ::consumeScrollListToTopEvent),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateStateToDisplayProgress() {
|
||||
updateState { inProgressStateConverter.convert(value = this) }
|
||||
}
|
||||
|
||||
fun updateStateToHideProgress() {
|
||||
updateState { inProgressStateConverter.convertBack(value = this) }
|
||||
}
|
||||
|
||||
fun updateStateWithManualSortingV2(tokenListUM: OrganizeTokensListUM) {
|
||||
updateState { copy(tokenListUM = tokenListUM) }
|
||||
}
|
||||
|
||||
fun updateStateWithManualSorting(itemsState: OrganizeTokensListState) {
|
||||
updateState { copy(itemsState = itemsState) }
|
||||
}
|
||||
|
||||
fun disableSortingByBalance() {
|
||||
updateState { copy(header = header.copy(isSortedByBalance = false)) }
|
||||
}
|
||||
|
||||
fun updateHiddenState(isBalanceHidden: Boolean) {
|
||||
updateState { copy(isBalanceHidden = isBalanceHidden) }
|
||||
}
|
||||
|
||||
fun updateStateWithError(error: TokenListError) {
|
||||
updateState { tokenListErrorConverter.convert(error) }
|
||||
}
|
||||
|
||||
fun updateStateWithError(error: TokenListSortingError) {
|
||||
updateState { tokenListSortingErrorConverter.convert(error) }
|
||||
}
|
||||
|
||||
private fun getInitialState(): OrganizeTokensState {
|
||||
return OrganizeTokensState(
|
||||
onBackClick = intents::onBackClick,
|
||||
itemsState = OrganizeTokensListState.Empty,
|
||||
tokenListUM = OrganizeTokensListUM.EmptyList,
|
||||
header = OrganizeTokensState.HeaderConfig(
|
||||
onSortClick = intents::onSortClick,
|
||||
onGroupClick = intents::onGroupClick,
|
||||
),
|
||||
actions = OrganizeTokensState.ActionsConfig(
|
||||
onApplyClick = intents::onApplyClick,
|
||||
onCancelClick = intents::onCancelClick,
|
||||
),
|
||||
dndConfig = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
OrganizeTokensState.DragAndDropConfig(
|
||||
onItemDragged = dragAndDropAdapterV2::onItemDragged,
|
||||
onItemDragStart = dragAndDropAdapterV2::onItemDraggingStart,
|
||||
onItemDragEnd = dragAndDropAdapterV2::onItemDraggingEnd,
|
||||
canDragItemOver = dragAndDropAdapterV2::canDragItemOver,
|
||||
)
|
||||
} else {
|
||||
OrganizeTokensState.DragAndDropConfig(
|
||||
onItemDragged = dragAndDropIntents::onItemDragged,
|
||||
onItemDragStart = dragAndDropIntents::onItemDraggingStart,
|
||||
onItemDragEnd = dragAndDropIntents::onItemDraggingEnd,
|
||||
canDragItemOver = dragAndDropIntents::canDragItemOver,
|
||||
)
|
||||
},
|
||||
scrollListToTop = consumedEvent(),
|
||||
isBalanceHidden = true,
|
||||
)
|
||||
}
|
||||
|
||||
private inline fun updateState(block: OrganizeTokensState.() -> OrganizeTokensState) {
|
||||
stateFlowInternal.update(block)
|
||||
}
|
||||
|
||||
private fun consumeScrollListToTopEvent() {
|
||||
updateState { copy(scrollListToTop = consumedEvent()) }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils
|
||||
|
||||
import com.tangem.domain.account.models.AccountStatusList
|
||||
import com.tangem.domain.account.status.model.AccountCryptoCurrencies
|
||||
import com.tangem.domain.models.account.filterCryptoPortfolio
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListUM
|
||||
|
||||
internal class CryptoCurrenciesIdsResolver {
|
||||
|
||||
fun resolve(listState: OrganizeTokensListState, tokenList: TokenList?): List<CryptoCurrency.ID> {
|
||||
val draggableTokens = when (listState) {
|
||||
is OrganizeTokensListState.Empty -> return emptyList()
|
||||
is OrganizeTokensListState.GroupedByNetwork -> listState.items.filterIsInstance<DraggableItem.Token>()
|
||||
is OrganizeTokensListState.Ungrouped -> listState.items.filterIsInstance<DraggableItem.Token>()
|
||||
}
|
||||
val currenciesStatuses = when (tokenList) {
|
||||
is TokenList.GroupedByNetwork -> tokenList.groups.flatMap { it.currencies }
|
||||
is TokenList.Ungrouped -> tokenList.currencies
|
||||
is TokenList.Empty,
|
||||
null,
|
||||
-> return emptyList()
|
||||
}
|
||||
|
||||
return draggableTokens.mapNotNull { draggableToken ->
|
||||
val currencyStatus = currenciesStatuses.firstOrNull {
|
||||
it.currency.id.value == draggableToken.id
|
||||
}
|
||||
|
||||
currencyStatus?.currency?.id
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UseOrEmpty")
|
||||
fun resolveV2(tokensListUM: OrganizeTokensListUM, accountStatusList: AccountStatusList?): AccountCryptoCurrencies {
|
||||
val draggableTokens = when (tokensListUM) {
|
||||
OrganizeTokensListUM.EmptyList -> return emptyMap()
|
||||
is OrganizeTokensListUM.AccountList,
|
||||
is OrganizeTokensListUM.TokensList,
|
||||
-> tokensListUM.items.filterIsInstance<DraggableItem.Token>()
|
||||
}
|
||||
|
||||
return accountStatusList?.accountStatuses
|
||||
?.filterCryptoPortfolio()
|
||||
?.filter { it.tokenList != TokenList.Empty }
|
||||
?.associate { accountStatus ->
|
||||
val currencies = accountStatus.flattenCurrencies()
|
||||
accountStatus.account to draggableTokens
|
||||
.asSequence()
|
||||
.filter { it.accountId == accountStatus.account.accountId.value }
|
||||
.mapNotNull { sortedToken ->
|
||||
currencies.firstOrNull { it.currency.id.value == sortedToken.id }?.currency
|
||||
}
|
||||
.toList()
|
||||
} ?: emptyMap()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.common
|
||||
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListUM
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
internal inline fun OrganizeTokensListState.updateItems(
|
||||
update: (PersistentList<DraggableItem>) -> List<DraggableItem>,
|
||||
): OrganizeTokensListState {
|
||||
val updatedItems = update(items).toPersistentList()
|
||||
|
||||
return when (this) {
|
||||
is OrganizeTokensListState.GroupedByNetwork -> copy(items = updatedItems)
|
||||
is OrganizeTokensListState.Ungrouped -> copy(items = updatedItems)
|
||||
is OrganizeTokensListState.Empty -> this
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun OrganizeTokensListUM.updateItems(
|
||||
update: (PersistentList<DraggableItem>) -> List<DraggableItem>,
|
||||
): OrganizeTokensListUM {
|
||||
val updatedItems = update(items).toPersistentList()
|
||||
|
||||
return when (this) {
|
||||
is OrganizeTokensListUM.AccountList -> copy(items = updatedItems)
|
||||
is OrganizeTokensListUM.TokensList -> copy(items = updatedItems)
|
||||
OrganizeTokensListUM.EmptyList -> this
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter
|
||||
|
||||
import com.tangem.domain.models.TokensSortType
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items.TokenListToListStateConverter
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
internal class TokenListToStateConverter(
|
||||
private val currentState: Provider<OrganizeTokensState>,
|
||||
private val itemsConverter: TokenListToListStateConverter,
|
||||
) : Converter<TokenList, OrganizeTokensState> {
|
||||
|
||||
override fun convert(value: TokenList): OrganizeTokensState {
|
||||
val state = currentState()
|
||||
val itemsState = itemsConverter.convert(value)
|
||||
|
||||
return state.copy(
|
||||
itemsState = itemsState,
|
||||
header = state.header.copy(
|
||||
isEnabled = itemsState !is OrganizeTokensListState.Empty,
|
||||
isSortedByBalance = value.sortedBy == TokensSortType.BALANCE,
|
||||
isGrouped = value is TokenList.GroupedByNetwork,
|
||||
),
|
||||
actions = state.actions.copy(
|
||||
canApply = itemsState !is OrganizeTokensListState.Empty,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items
|
||||
|
||||
import com.tangem.common.getTotalWithRewardsStakingBalance
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.BigDecimalFormatConstants
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.staking.StakingBalance
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getGroupHeaderId
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getTokenItemId
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.converter.Converter
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import java.math.BigDecimal
|
||||
|
||||
internal class CryptoCurrencyToDraggableItemConverter(
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
) : Converter<CryptoCurrencyStatus, DraggableItem.Token> {
|
||||
|
||||
private val iconStateConverter = CryptoCurrencyToIconStateConverter()
|
||||
|
||||
override fun convert(value: CryptoCurrencyStatus): DraggableItem.Token {
|
||||
return createDraggableToken(value, appCurrencyProvider())
|
||||
}
|
||||
|
||||
override fun convertList(input: Collection<CryptoCurrencyStatus>): List<DraggableItem.Token> {
|
||||
val appCurrency = appCurrencyProvider()
|
||||
|
||||
return input.map { createDraggableToken(it, appCurrency) }
|
||||
}
|
||||
|
||||
private fun createDraggableToken(
|
||||
currencyStatus: CryptoCurrencyStatus,
|
||||
appCurrency: AppCurrency,
|
||||
): DraggableItem.Token {
|
||||
return DraggableItem.Token(
|
||||
tokenItemState = createTokenItemState(currencyStatus, appCurrency),
|
||||
groupId = getGroupHeaderId(currencyStatus.currency.network),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createTokenItemState(
|
||||
currencyStatus: CryptoCurrencyStatus,
|
||||
appCurrency: AppCurrency,
|
||||
): TokenItemState.Draggable {
|
||||
val currency = currencyStatus.currency
|
||||
|
||||
return TokenItemState.Draggable(
|
||||
id = getTokenItemId(currency.id),
|
||||
iconState = iconStateConverter.convert(currencyStatus),
|
||||
titleState = TokenItemState.TitleState.Content(text = stringReference(currency.name)),
|
||||
subtitle2State = if (currencyStatus.value.isError) {
|
||||
TokenItemState.Subtitle2State.Unreachable
|
||||
} else {
|
||||
TokenItemState.Subtitle2State.TextContent(text = getFormattedFiatAmount(currencyStatus, appCurrency))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun getFormattedFiatAmount(currency: CryptoCurrencyStatus, appCurrency: AppCurrency): String {
|
||||
val stakingBalance = currency.value.stakingBalance as? StakingBalance.Data
|
||||
val fiatRate = currency.value.fiatRate ?: BigDecimal.ZERO
|
||||
val fiatStakingBalance = stakingBalance?.getTotalWithRewardsStakingBalance(currency.currency.network.rawId)
|
||||
?.multiply(fiatRate).orZero()
|
||||
|
||||
val fiatAmount = currency.value.fiatAmount ?: return BigDecimalFormatConstants.EMPTY_BALANCE_SIGN
|
||||
return (fiatAmount + fiatStakingBalance).format { fiat(appCurrency.code, appCurrency.symbol) }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items
|
||||
|
||||
import com.tangem.domain.models.tokenlist.TokenList.GroupedByNetwork.NetworkGroup
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getGroupHeaderId
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getGroupPlaceholder
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
internal class NetworkGroupToDraggableItemsConverter(
|
||||
private val itemConverter: CryptoCurrencyToDraggableItemConverter,
|
||||
) : Converter<NetworkGroup, List<DraggableItem>> {
|
||||
|
||||
override fun convert(value: NetworkGroup): List<DraggableItem> {
|
||||
return buildList {
|
||||
add(createGroupHeader(value))
|
||||
addAll(createTokens(value))
|
||||
}
|
||||
}
|
||||
|
||||
override fun convertList(input: Collection<NetworkGroup>): List<List<DraggableItem>> {
|
||||
val lastItemIndex = input.size - 1
|
||||
|
||||
return input.mapIndexed { index, networkGroup ->
|
||||
convert(networkGroup).toMutableList()
|
||||
.also { mutableGroup ->
|
||||
if (index != lastItemIndex) {
|
||||
mutableGroup.add(getGroupPlaceholder(index))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createGroupHeader(group: NetworkGroup) = DraggableItem.GroupHeader(
|
||||
id = getGroupHeaderId(group.network),
|
||||
networkName = group.network.name,
|
||||
)
|
||||
|
||||
private fun createTokens(group: NetworkGroup): List<DraggableItem.Token> {
|
||||
return itemConverter.convertList(group.currencies)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items
|
||||
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.uniteItems
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
internal class TokenListToListStateConverter(
|
||||
private val groupsConverter: NetworkGroupToDraggableItemsConverter,
|
||||
private val tokensConverter: CryptoCurrencyToDraggableItemConverter,
|
||||
) : Converter<TokenList, OrganizeTokensListState> {
|
||||
|
||||
override fun convert(value: TokenList): OrganizeTokensListState {
|
||||
return when (value) {
|
||||
is TokenList.GroupedByNetwork -> createListState(value)
|
||||
is TokenList.Ungrouped -> createListState(value)
|
||||
is TokenList.Empty -> createEmptyListState()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createListState(tokenList: TokenList.GroupedByNetwork): OrganizeTokensListState.GroupedByNetwork {
|
||||
return OrganizeTokensListState.GroupedByNetwork(
|
||||
items = groupsConverter.convertList(tokenList.groups)
|
||||
.flatten()
|
||||
.uniteItems()
|
||||
.toPersistentList(),
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST") // Erased type
|
||||
private fun createListState(tokenList: TokenList.Ungrouped): OrganizeTokensListState.Ungrouped {
|
||||
return OrganizeTokensListState.Ungrouped(
|
||||
items = tokensConverter.convertList(tokenList.currencies)
|
||||
.uniteItems()
|
||||
.toPersistentList() as PersistentList<DraggableItem.Token>,
|
||||
)
|
||||
}
|
||||
|
||||
private fun createEmptyListState(): OrganizeTokensListState.Empty {
|
||||
return OrganizeTokensListState.Empty
|
||||
}
|
||||
}
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.dnd
|
||||
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.DragAndDropIntents
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.divideMovingItem
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.uniteItems
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.common.updateItems
|
||||
import com.tangem.utils.Provider
|
||||
import kotlinx.collections.immutable.mutate
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import org.burnoutcrew.reorderable.ItemPosition
|
||||
|
||||
internal class DragAndDropAdapter(
|
||||
private val listStateProvider: Provider<OrganizeTokensListState>,
|
||||
) : DragAndDropIntents {
|
||||
|
||||
private val draggableGroupsOperations = DraggableGroupsOperations()
|
||||
|
||||
private val externalListState: OrganizeTokensListState
|
||||
get() = listStateProvider.invoke()
|
||||
|
||||
private val dragAndDropUpdatesInternal: MutableStateFlow<DragOperation?> = MutableStateFlow(value = null)
|
||||
|
||||
private var draggingItem: DraggableItem? = null
|
||||
private var draggingListState: OrganizeTokensListState? = null
|
||||
|
||||
val dragAndDropUpdates: Flow<DragOperation>
|
||||
get() = dragAndDropUpdatesInternal.filterNotNull()
|
||||
|
||||
override fun canDragItemOver(dragOver: ItemPosition, dragging: ItemPosition): Boolean {
|
||||
val items = when (val listState = externalListState) {
|
||||
is OrganizeTokensListState.GroupedByNetwork -> listState.items
|
||||
is OrganizeTokensListState.Empty,
|
||||
is OrganizeTokensListState.Ungrouped,
|
||||
-> return true // If ungrouped then item can be moved anywhere
|
||||
}
|
||||
|
||||
val (dragOverItem, draggingItem) = findItemsToMove(
|
||||
items = items,
|
||||
moveOverItemKey = dragOver.key,
|
||||
movedItemKey = dragging.key,
|
||||
)
|
||||
|
||||
if (dragOverItem == null || draggingItem == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
return when (draggingItem) {
|
||||
is DraggableItem.GroupHeader -> checkCanMoveHeaderOver(dragOver, dragOverItem, items.lastIndex)
|
||||
is DraggableItem.Token -> checkCanMoveTokenOver(draggingItem, dragOverItem)
|
||||
is DraggableItem.Placeholder,
|
||||
is DraggableItem.Portfolio,
|
||||
-> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemDraggingStart(item: DraggableItem) {
|
||||
if (draggingItem != null) return
|
||||
draggingItem = item
|
||||
|
||||
updateListState(DragOperation.Type.Start) {
|
||||
when (item) {
|
||||
is DraggableItem.Placeholder,
|
||||
is DraggableItem.Portfolio,
|
||||
-> items
|
||||
is DraggableItem.GroupHeader -> draggableGroupsOperations.collapseGroup(items, item)
|
||||
is DraggableItem.Token -> when (this) {
|
||||
is OrganizeTokensListState.GroupedByNetwork -> items.divideMovingItem(item)
|
||||
is OrganizeTokensListState.Ungrouped -> items.divideMovingItem(item)
|
||||
is OrganizeTokensListState.Empty -> items
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draggingListState = externalListState
|
||||
}
|
||||
|
||||
override fun onItemDraggingEnd() {
|
||||
val draggingItem = draggingItem ?: return
|
||||
|
||||
updateListState(DragOperation.Type.End(isItemsOrderChanged = checkIsItemsOrderChanged())) {
|
||||
when (draggingItem) {
|
||||
is DraggableItem.GroupHeader -> draggableGroupsOperations.expandGroups(items)
|
||||
is DraggableItem.Token -> items.uniteItems()
|
||||
is DraggableItem.Placeholder,
|
||||
is DraggableItem.Portfolio,
|
||||
-> items
|
||||
}
|
||||
}
|
||||
|
||||
this.draggingItem = null
|
||||
}
|
||||
|
||||
override fun onItemDragged(from: ItemPosition, to: ItemPosition) {
|
||||
updateListState(DragOperation.Type.Dragged) {
|
||||
items.mutate {
|
||||
it.add(to.index, it.removeAt(from.index))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateListState(type: DragOperation.Type, block: OrganizeTokensListState.() -> List<DraggableItem>) {
|
||||
val updatedState = externalListState.updateItems { block(externalListState) }
|
||||
|
||||
dragAndDropUpdatesInternal.value = DragOperation(type, updatedState)
|
||||
}
|
||||
|
||||
private fun findItemsToMove(
|
||||
items: List<DraggableItem>,
|
||||
moveOverItemKey: Any?,
|
||||
movedItemKey: Any?,
|
||||
): Pair<DraggableItem?, DraggableItem?> {
|
||||
var moveOverItem: DraggableItem? = null
|
||||
var movedItem: DraggableItem? = null
|
||||
|
||||
for (item in items) {
|
||||
if (item.id == moveOverItemKey) {
|
||||
moveOverItem = item
|
||||
}
|
||||
if (item.id == movedItemKey) {
|
||||
movedItem = item
|
||||
}
|
||||
if (moveOverItem != null && movedItem != null) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return Pair(moveOverItem, movedItem)
|
||||
}
|
||||
|
||||
private fun checkCanMoveHeaderOver(
|
||||
moveOverItemPosition: ItemPosition,
|
||||
moveOverItem: DraggableItem,
|
||||
lastItemIndex: Int,
|
||||
): Boolean {
|
||||
// Group item can be moved only to group divider or to ages of the items list
|
||||
return when {
|
||||
moveOverItemPosition.index == 0 -> true
|
||||
moveOverItemPosition.index == lastItemIndex -> true
|
||||
moveOverItem is DraggableItem.Placeholder -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkCanMoveTokenOver(item: DraggableItem.Token, moveOverItem: DraggableItem): Boolean {
|
||||
// Token item can be moved only in its group
|
||||
return when (moveOverItem) {
|
||||
is DraggableItem.GroupHeader -> false // Token item can not be moved to group item
|
||||
is DraggableItem.Token -> item.groupId == moveOverItem.groupId // Token item can not be moved over its group
|
||||
is DraggableItem.Portfolio,
|
||||
is DraggableItem.Placeholder,
|
||||
-> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkIsItemsOrderChanged(): Boolean {
|
||||
fun OrganizeTokensListState?.getItemsIds(): List<Any>? = this?.items?.mapNotNull { item ->
|
||||
if (item is DraggableItem.Placeholder) {
|
||||
null
|
||||
} else {
|
||||
item.id
|
||||
}
|
||||
}
|
||||
|
||||
return externalListState.getItemsIds() != draggingListState.getItemsIds()
|
||||
}
|
||||
|
||||
data class DragOperation(
|
||||
val type: Type,
|
||||
val listState: OrganizeTokensListState,
|
||||
) {
|
||||
|
||||
sealed class Type {
|
||||
|
||||
data object Start : Type()
|
||||
|
||||
data object Dragged : Type()
|
||||
|
||||
data class End(val isItemsOrderChanged: Boolean) : Type()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package com.tangem.feature.wallet.presentation.preview
|
||||
|
||||
import com.tangem.core.ui.extensions.combinedReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.styledStringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletBalanceUM
|
||||
|
||||
internal object WalletBalancePreview {
|
||||
|
||||
val content: WalletBalanceUM.Content = WalletBalanceUM.Content(
|
||||
id = UserWalletId("0"),
|
||||
name = "My Wallet",
|
||||
balance = combinedReference(
|
||||
stringReference("1,234"),
|
||||
styledStringReference(
|
||||
".56",
|
||||
{
|
||||
TangemTheme.typography2.headingRegular28.toSpanStyle()
|
||||
},
|
||||
),
|
||||
stringReference(" $"),
|
||||
),
|
||||
isBalanceFlickering = false,
|
||||
isZeroBalance = false,
|
||||
)
|
||||
|
||||
val loading: WalletBalanceUM.Loading = WalletBalanceUM.Loading(
|
||||
id = UserWalletId("1"),
|
||||
name = "My Wallet",
|
||||
)
|
||||
|
||||
val error: WalletBalanceUM.Error = WalletBalanceUM.Error(
|
||||
id = UserWalletId("2"),
|
||||
name = "My Wallet",
|
||||
)
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.analytics.utils
|
|||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.pay.model.CustomerInfo
|
||||
import com.tangem.domain.models.kyc.KycStatus
|
||||
import com.tangem.domain.pay.model.MainScreenCustomerInfo
|
||||
import com.tangem.domain.pay.model.OrderStatus
|
||||
import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
|
||||
|
|
@ -29,7 +29,7 @@ internal class WalletTangemPayAnalyticsEventSender @Inject constructor(
|
|||
// ignore cancelled state on analytics
|
||||
customerInfo.orderStatus == OrderStatus.CANCELED -> return
|
||||
// ignore kyc not approved state on analytics
|
||||
customerInfo.info.kycStatus != CustomerInfo.KycStatus.APPROVED -> return
|
||||
customerInfo.info.kycStatus != KycStatus.APPROVED -> return
|
||||
cardInfo != null && productInstance != null -> return
|
||||
else -> TangemPayAnalyticsEvents.IssuingBannerDisplayed()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ import com.tangem.domain.tokens.model.analytics.PromoAnalyticsEvent.*
|
|||
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.PushBannerPromo.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.PushBannerPromo.PushBanner
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -34,10 +33,29 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun send(displayedWalletUM: WalletUM?, newNotifications: List<WalletNotificationUM>) {
|
||||
if (screenLifecycleProvider.isBackgroundState.value) return
|
||||
if (newNotifications.isEmpty()) return
|
||||
if (displayedWalletUM == null || displayedWalletUM.pullToRefreshConfig.isRefreshing) return
|
||||
|
||||
val totalNotifications = displayedWalletUM.notifications + displayedWalletUM.notificationsCarousel
|
||||
val notificationsDiff = newNotifications.filter { it !in totalNotifications }
|
||||
|
||||
val eventsToSend = getEvents2(notificationsDiff)
|
||||
|
||||
eventsToSend.forEach { event ->
|
||||
analyticsEventHandler.send(event)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEvents(warnings: List<WalletNotification>): Set<AnalyticsEvent> {
|
||||
return warnings.mapNotNullTo(mutableSetOf(), ::getEvent)
|
||||
}
|
||||
|
||||
private fun getEvents2(notifications: List<WalletNotificationUM>): Set<AnalyticsEvent> {
|
||||
return notifications.mapNotNullTo(mutableSetOf(), ::getEvent2)
|
||||
}
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private fun getEvent(warning: WalletNotification): AnalyticsEvent? {
|
||||
return when (warning) {
|
||||
|
|
@ -106,4 +124,53 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
|
|||
is WalletNotification.UpgradeHotWalletPromo -> null
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private fun getEvent2(notificationUM: WalletNotificationUM): AnalyticsEvent? {
|
||||
return when (notificationUM) {
|
||||
WalletNotificationUM.DevCard -> DevelopmentCard()
|
||||
WalletNotificationUM.FailedCardValidation -> ProductSampleCard()
|
||||
is WalletNotificationUM.MissingBackup -> BackupYourWallet()
|
||||
is WalletNotificationUM.NumberOfSignedHashesIncorrect -> CardSignedTransactions()
|
||||
WalletNotificationUM.TestnetCard -> TestnetCard()
|
||||
WalletNotificationUM.DemoCard -> DemoCard()
|
||||
is WalletNotificationUM.MissingAddresses -> MissingAddresses()
|
||||
is WalletNotificationUM.RateApp -> HowDoYouLikeTangem()
|
||||
is WalletNotificationUM.BackupError -> BackupError()
|
||||
is WalletNotificationUM.NoteMigration -> NotePromo()
|
||||
is WalletNotificationUM.OnePlusOnePromo -> NoticePromotionBanner(
|
||||
source = AnalyticsParam.ScreensSources.Main,
|
||||
program = Program.OnePlusOne,
|
||||
)
|
||||
is WalletNotificationUM.YieldPromo -> NoticePromotionBanner(
|
||||
source = AnalyticsParam.ScreensSources.Main,
|
||||
program = Program.YieldPromo,
|
||||
)
|
||||
is WalletNotificationUM.FinishWalletActivation -> {
|
||||
val activationState = if (notificationUM.isBackupExists) {
|
||||
NoticeFinishActivation.ActivationState.Unfinished
|
||||
} else {
|
||||
NoticeFinishActivation.ActivationState.NotStarted
|
||||
}
|
||||
val balanceState = when (notificationUM.type) {
|
||||
WalletNotificationType.Warning -> AnalyticsParam.EmptyFull.Full
|
||||
else -> AnalyticsParam.EmptyFull.Empty
|
||||
}
|
||||
NoticeFinishActivation(
|
||||
activationState = activationState,
|
||||
balanceState = balanceState,
|
||||
)
|
||||
}
|
||||
is WalletNotificationUM.SeedPhraseNotification -> NoticeSeedPhraseSupport()
|
||||
is WalletNotificationUM.SeedPhraseSecondNotification -> NoticeSeedPhraseSupportSecond()
|
||||
is WalletNotificationUM.PushNotifications -> PushBanner()
|
||||
is WalletNotificationUM.UnlockWallets,
|
||||
is WalletNotificationUM.NoAccount,
|
||||
is WalletNotificationUM.LowSignatures,
|
||||
WalletNotificationUM.SomeNetworksUnreachable,
|
||||
is WalletNotificationUM.UsedOutdatedData,
|
||||
is WalletNotificationUM.CloreMigration,
|
||||
-> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,12 +4,8 @@ import com.tangem.common.routing.AppRoute.WalletBackup
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2
|
||||
import com.tangem.core.ui.components.bottomsheets.message.icon
|
||||
import com.tangem.core.ui.components.bottomsheets.message.infoBlock
|
||||
import com.tangem.core.ui.components.bottomsheets.message.onClick
|
||||
import com.tangem.core.ui.components.bottomsheets.message.primaryButton
|
||||
import com.tangem.core.ui.components.bottomsheets.message.secondaryButton
|
||||
import com.tangem.core.ui.components.bottomsheets.message.*
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.message.bottomSheetMessage
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
|
|
@ -19,7 +15,9 @@ import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
|
|||
import com.tangem.feature.wallet.child.wallet.model.WalletActivationBannerType
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificationUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import javax.inject.Inject
|
||||
|
|
@ -71,6 +69,44 @@ internal class WalletWarningsSingleEventSender @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun send(
|
||||
userWalletId: UserWalletId,
|
||||
displayedWalletUM: WalletUM?,
|
||||
newNotifications: List<WalletNotificationUM>,
|
||||
) {
|
||||
if (screenLifecycleProvider.isBackgroundState.value) return
|
||||
if (newNotifications.isEmpty()) return
|
||||
if (displayedWalletUM == null || displayedWalletUM.pullToRefreshConfig.isRefreshing) return
|
||||
|
||||
val totalNotifications = displayedWalletUM.notifications + displayedWalletUM.notificationsCarousel
|
||||
val events = newNotifications.filter { it !in totalNotifications }
|
||||
|
||||
// We must show activation bs only for the first seen wallet when open the app (if need, see conditions below),
|
||||
// so we keep this wallet id and use for future checks, ignore other wallets during the app session.
|
||||
if (isActivationBottomSheetShown.isEmpty()) {
|
||||
isActivationBottomSheetShown[userWalletId] = false
|
||||
}
|
||||
|
||||
events.forEach { event ->
|
||||
when (event) {
|
||||
is WalletNotificationUM.SeedPhraseNotification -> {
|
||||
seedPhraseNotificationUseCase.notified(userWalletId = userWalletId)
|
||||
}
|
||||
is WalletNotificationUM.FinishWalletActivation -> {
|
||||
// We check that map contains the first seen wallet (will return null instead false/true otherwise)
|
||||
// and for this wallet we haven't shown the activation bs yet (check that returns false, not true)
|
||||
if (isActivationBottomSheetShown[userWalletId] == false) {
|
||||
if (event.messageEffect == TangemMessageEffect.Warning && event.isBackupExists.not()) {
|
||||
showFinishActivationBottomSheet(userWalletId)
|
||||
}
|
||||
isActivationBottomSheetShown[userWalletId] = true
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showFinishActivationBottomSheet(userWalletId: UserWalletId) {
|
||||
val userWallet = getUserWalletUseCase(userWalletId).getOrNull() ?: return
|
||||
if (userWallet !is UserWallet.Hot) return
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
|||
import com.tangem.domain.card.CardTypesResolver
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.core.lce.Lce
|
||||
import com.tangem.domain.core.lce.LceFlow
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.hotwallet.CheckHotWalletUpgradeBannerUseCase
|
||||
import com.tangem.domain.hotwallet.GetAccessCodeSkippedUseCase
|
||||
|
|
@ -52,7 +51,6 @@ import javax.inject.Inject
|
|||
@Suppress("LongParameterList", "LargeClass")
|
||||
@ModelScoped
|
||||
internal class GetMultiWalletWarningsFactory @Inject constructor(
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase,
|
||||
private val isNeedToBackupUseCase: IsNeedToBackupUseCase,
|
||||
|
|
@ -71,30 +69,15 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow<ImmutableList<WalletNotification>> {
|
||||
val cardTypesResolver = (userWallet as? UserWallet.Cold)?.scanResponse?.cardTypesResolver
|
||||
|
||||
val accountStatusList by lazy {
|
||||
val accountStatusListFlow by lazy {
|
||||
val params = SingleAccountStatusListProducer.Params(userWallet.walletId)
|
||||
accountDependencies.singleAccountStatusListSupplier(params)
|
||||
.map { it.totalFiatBalance to it.flattenCurrencies() }
|
||||
.map { Lce.Content(it) }
|
||||
}
|
||||
|
||||
fun tokenListFlow(): LceFlow<TokenListError, Pair<TotalFiatBalance, List<CryptoCurrencyStatus>>> {
|
||||
return if (accountDependencies.accountsFeatureToggles.isFeatureEnabled) {
|
||||
accountStatusList
|
||||
} else {
|
||||
runCatching { tokenListStore.getOrThrow(userWallet.walletId) }
|
||||
.map { result -> result.map { lce -> lce.map { it.totalFiatBalance to it.flattenCurrencies() } } }
|
||||
.getOrNull()
|
||||
// in case of runtime change ft in tester menu
|
||||
?: accountStatusList
|
||||
}
|
||||
}
|
||||
|
||||
// val params = SingleAccountStatusListProducer.Params(userWallet.walletId)
|
||||
// val accountStatusListFlow = accountDependencies.singleAccountStatusListSupplier(params)
|
||||
return combine(
|
||||
// todo account just use it, after delete accountsFeatureToggles
|
||||
// accountStatusListFlow,
|
||||
accountStatusListFlow,
|
||||
isReadyToShowRateAppUseCase().distinctUntilChanged(),
|
||||
isNeedToBackupUseCase(userWallet.walletId).distinctUntilChanged(),
|
||||
seedPhraseNotificationUseCase(userWalletId = userWallet.walletId).distinctUntilChanged(),
|
||||
|
|
@ -110,7 +93,6 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
getUpgradeBannerClosureTimestampUseCase(userWallet.walletId)
|
||||
.distinctUntilChanged(),
|
||||
) { array -> array }
|
||||
.combine(tokenListFlow()) { array, any: Any? -> arrayOf(any).plus(elements = array) }
|
||||
.map { array ->
|
||||
val lceTokens = array[0] as Lce<TokenListError, Pair<TotalFiatBalance, List<CryptoCurrencyStatus>>>
|
||||
val totalFiatBalance = lceTokens.map { it.first }
|
||||
|
|
@ -149,9 +131,19 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
|
|||
|
||||
addYieldPromoNotification(clickIntents, shouldShowYieldPromo)
|
||||
|
||||
addInformationalNotifications(userWallet, cardTypesResolver, flattenCurrencies, clickIntents)
|
||||
addInformationalNotifications(
|
||||
userWallet = userWallet,
|
||||
cardTypesResolver = cardTypesResolver,
|
||||
flattenCurrencies = flattenCurrencies,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
addWarningNotifications(cardTypesResolver, flattenCurrencies, isNeedToBackup, clickIntents)
|
||||
addWarningNotifications(
|
||||
cardTypesResolver = cardTypesResolver,
|
||||
flattenCurrencies = flattenCurrencies,
|
||||
isNeedToBackup = isNeedToBackup,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
addPushReminderNotification(
|
||||
clickIntents = clickIntents,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.tangem.feature.wallet.presentation.wallet.domain
|
|||
import arrow.core.Either
|
||||
import arrow.core.right
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusProducer
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusSupplier
|
||||
import com.tangem.domain.card.CardTypesResolver
|
||||
|
|
@ -15,7 +14,6 @@ import com.tangem.domain.models.account.AccountStatus
|
|||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
|
||||
|
|
@ -30,8 +28,6 @@ import javax.inject.Inject
|
|||
@ModelScoped
|
||||
@Suppress("LongParameterList")
|
||||
internal class GetSingleWalletWarningsFactory @Inject constructor(
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val singleAccountStatusSupplier: SingleAccountStatusSupplier,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase,
|
||||
|
|
@ -40,7 +36,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
private val getWalletsUseCase: GetWalletsUseCase,
|
||||
) {
|
||||
|
||||
private var readyForRateAppNotification = false
|
||||
private var isReadyForRateAppNotification = false
|
||||
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow<ImmutableList<WalletNotification>> {
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
|
|
@ -54,7 +50,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
flow3 = isNeedToBackupUseCase(userWallet.walletId).conflate(),
|
||||
flow4 = getWalletsUseCase().conflate(),
|
||||
) { maybePrimaryCurrencyStatus, isReadyToShowRating, isNeedToBackup, userWallets ->
|
||||
readyForRateAppNotification = true
|
||||
isReadyForRateAppNotification = true
|
||||
buildList {
|
||||
addUsedOutdatedDataNotification(maybePrimaryCurrencyStatus)
|
||||
|
||||
|
|
@ -120,8 +116,8 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
cardTypesResolver: CardTypesResolver,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val userHasWalletOrWallet2 = userWallets.filterIsInstance<UserWallet.Cold>().any {
|
||||
val typesResolver = it.scanResponse.cardTypesResolver
|
||||
val hasWalletOrWallet2 = userWallets.filterIsInstance<UserWallet.Cold>().any { coldWallet ->
|
||||
val typesResolver = coldWallet.scanResponse.cardTypesResolver
|
||||
typesResolver.isTangemWallet() || typesResolver.isWallet2()
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +125,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
element = WalletNotification.NoteMigration(
|
||||
onClick = { clickIntents.onNoteMigrationButtonClick(NOTE_MIGRATION_URL) },
|
||||
),
|
||||
condition = cardTypesResolver.isTangemNote() && !userHasWalletOrWallet2,
|
||||
condition = cardTypesResolver.isTangemNote() && !hasWalletOrWallet2,
|
||||
)
|
||||
|
||||
addIf(
|
||||
|
|
@ -191,8 +187,8 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
selectedWallet: UserWallet.Cold,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus?,
|
||||
): Boolean {
|
||||
return cryptoCurrencyStatus?.currency?.network?.let {
|
||||
hasSingleWalletSignedHashesUseCase(userWallet = selectedWallet, network = it)
|
||||
return cryptoCurrencyStatus?.currency?.network?.let { network ->
|
||||
hasSingleWalletSignedHashesUseCase(userWallet = selectedWallet, network = network)
|
||||
.conflate()
|
||||
.distinctUntilChanged()
|
||||
.firstOrNull()
|
||||
|
|
@ -209,7 +205,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
onDislikeClick = clickIntents::onDislikeAppClick,
|
||||
onCloseClick = clickIntents::onCloseRateAppWarningClick,
|
||||
),
|
||||
condition = isReadyToShowRating && readyForRateAppNotification,
|
||||
condition = isReadyToShowRating && isReadyForRateAppNotification,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +215,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
element is WalletNotification.Warning ||
|
||||
element is WalletNotification.NoteMigration
|
||||
) {
|
||||
readyForRateAppNotification = false
|
||||
isReadyForRateAppNotification = false
|
||||
}
|
||||
|
||||
element
|
||||
|
|
@ -229,16 +225,12 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
|
|||
private fun getPrimaryCurrencyStatusFlow(
|
||||
userWallet: UserWallet,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountStatusFlow(userWallet).mapNotNull { accountStatus ->
|
||||
accountStatus.flattenCurrencies().firstOrNull()
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.conflate()
|
||||
.map { it.right() }
|
||||
} else {
|
||||
getSingleCryptoCurrencyStatusUseCase.invokeSingleWallet(userWallet.walletId)
|
||||
return getAccountStatusFlow(userWallet).mapNotNull { accountStatus ->
|
||||
accountStatus.flattenCurrencies().firstOrNull()
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.conflate()
|
||||
.map { it.right() }
|
||||
}
|
||||
|
||||
private fun getAccountStatusFlow(userWallet: UserWallet): Flow<AccountStatus.CryptoPortfolio> {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.domain
|
||||
|
||||
import com.tangem.common.TangemSiteUrlBuilder
|
||||
import com.tangem.common.ui.notifications.NotificationId
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
import com.tangem.domain.promo.ShouldShowPromoWalletUseCase
|
||||
import com.tangem.domain.promo.models.PromoId
|
||||
import com.tangem.domain.settings.IsReadyToShowRateAppUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificationUM
|
||||
import com.tangem.utils.extensions.addIf
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Factory for creating a list of notifications that can be shown on the wallet screen.
|
||||
* These notifications are not critical and can be stacked with each other.
|
||||
*/
|
||||
@ModelScoped
|
||||
internal class GetWalletNotificationsCarouselFactory @Inject constructor(
|
||||
private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase,
|
||||
private val shouldShowPromoWalletUseCase: ShouldShowPromoWalletUseCase,
|
||||
private val getWalletsUseCase: GetWalletsUseCase,
|
||||
private val notificationsRepository: NotificationsRepository,
|
||||
) {
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow<ImmutableList<WalletNotificationUM>> {
|
||||
return combine(
|
||||
flow = shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.YieldPromo)
|
||||
.distinctUntilChanged(),
|
||||
flow2 = notificationsRepository.getShouldShowNotification(
|
||||
NotificationId.EnablePushesReminderNotification.key,
|
||||
).distinctUntilChanged(),
|
||||
flow3 = shouldShowPromoWalletUseCase(userWalletId = userWallet.walletId, promoId = PromoId.OnePlusOne)
|
||||
.distinctUntilChanged(),
|
||||
flow4 = isReadyToShowRateAppUseCase().distinctUntilChanged(),
|
||||
flow5 = getWalletsUseCase().conflate(),
|
||||
) { showYieldPromo, showPushesNotification, showOnePlusOnePromo, showRateAppPromo, wallets ->
|
||||
|
||||
buildList {
|
||||
addNoteMigrationNotification(userWallet, wallets, clickIntents)
|
||||
addRateAppNotification(showRateAppPromo, clickIntents)
|
||||
addOnePlusOnePromoNotification(clickIntents, showOnePlusOnePromo)
|
||||
addYieldPromoNotification(clickIntents, showYieldPromo)
|
||||
|
||||
addPushNotification(
|
||||
shouldShow = showPushesNotification,
|
||||
isPushesAllowed = notificationsRepository.isUserAllowToSubscribeOnPushNotifications(),
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
}.sortedBy { it.type.ordinal }.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addRateAppNotification(
|
||||
isReadyToShowRating: Boolean,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
addIf(isReadyToShowRating) {
|
||||
WalletNotificationUM.RateApp(
|
||||
onLikeClick = clickIntents::onLikeAppClick,
|
||||
onDislikeClick = clickIntents::onDislikeAppClick,
|
||||
onCloseClick = clickIntents::onCloseRateAppWarningClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addYieldPromoNotification(
|
||||
clickIntents: WalletClickIntents,
|
||||
shouldShowPromo: Boolean,
|
||||
) {
|
||||
addIf(shouldShowPromo) {
|
||||
WalletNotificationUM.YieldPromo(
|
||||
onCloseClick = { clickIntents.onClosePromoClick(promoId = PromoId.YieldPromo) },
|
||||
onTermsAndConditionsClick = { clickIntents.onYieldPromoTermsAndConditionsClick() },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addOnePlusOnePromoNotification(
|
||||
clickIntents: WalletClickIntents,
|
||||
shouldShowPromo: Boolean,
|
||||
) {
|
||||
addIf(shouldShowPromo) {
|
||||
WalletNotificationUM.OnePlusOnePromo(
|
||||
onCloseClick = { clickIntents.onClosePromoClick(promoId = PromoId.OnePlusOne) },
|
||||
onClick = { clickIntents.onPromoClick(promoId = PromoId.OnePlusOne) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addNoteMigrationNotification(
|
||||
userWallet: UserWallet,
|
||||
userWallets: List<UserWallet>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val cardTypesResolver = (userWallet as? UserWallet.Cold)?.scanResponse?.cardTypesResolver
|
||||
|
||||
val isUserHasWalletOrWallet2 = userWallets.filterIsInstance<UserWallet.Cold>().any { wallet ->
|
||||
val typesResolver = wallet.scanResponse.cardTypesResolver
|
||||
typesResolver.isTangemWallet() || typesResolver.isWallet2()
|
||||
}
|
||||
|
||||
addIf(cardTypesResolver != null && cardTypesResolver.isTangemNote() && !isUserHasWalletOrWallet2) {
|
||||
WalletNotificationUM.NoteMigration(
|
||||
onClick = { clickIntents.onNoteMigrationButtonClick(TangemSiteUrlBuilder.NOTE_MIGRATION_URL) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addPushNotification(
|
||||
shouldShow: Boolean,
|
||||
isPushesAllowed: Boolean,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
addIf(shouldShow && !isPushesAllowed) {
|
||||
WalletNotificationUM.PushNotifications(
|
||||
onCloseClick = clickIntents::onDenyPermissions,
|
||||
onEnabledClick = clickIntents::onAllowPermissions,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,326 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.domain
|
||||
|
||||
import com.tangem.common.ui.userwallet.ext.walletInterationIcon
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.domain.account.status.producer.SingleAccountStatusListProducer
|
||||
import com.tangem.domain.card.CardTypesResolver
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.hotwallet.GetAccessCodeSkippedUseCase
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.models.TotalFiatBalance
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.models.SeedPhraseNotificationsStatus
|
||||
import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase
|
||||
import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificationUM
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.lib.crypto.BlockchainUtils
|
||||
import com.tangem.utils.extensions.addIf
|
||||
import com.tangem.utils.extensions.isPositive
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.*
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Factory for creating a list of notifications that can be shown on the wallet screen.
|
||||
* These notifications are critical and should be shown separately from each other.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class GetWalletWarningsFactory @Inject constructor(
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val isNeedToBackupUseCase: IsNeedToBackupUseCase,
|
||||
private val backupValidator: BackupValidator,
|
||||
private val seedPhraseNotificationUseCase: SeedPhraseNotificationUseCase,
|
||||
private val accountDependencies: AccountDependencies,
|
||||
private val getAccessCodeSkippedUseCase: GetAccessCodeSkippedUseCase,
|
||||
private val hasSingleWalletSignedHashesUseCase: HasSingleWalletSignedHashesUseCase,
|
||||
) {
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow<ImmutableList<WalletNotificationUM>> {
|
||||
val cardTypesResolver = (userWallet as? UserWallet.Cold)?.scanResponse?.cardTypesResolver
|
||||
|
||||
val params = SingleAccountStatusListProducer.Params(userWallet.walletId)
|
||||
val accountStatusListFlow = accountDependencies.singleAccountStatusListSupplier(params)
|
||||
|
||||
return combine(
|
||||
flow = accountStatusListFlow,
|
||||
flow2 = isNeedToBackupUseCase(userWallet.walletId).distinctUntilChanged(),
|
||||
flow3 = seedPhraseNotificationUseCase(userWalletId = userWallet.walletId).distinctUntilChanged(),
|
||||
flow4 = getAccessCodeSkippedUseCase(userWallet.walletId).distinctUntilChanged(),
|
||||
) { accountList, isNeedToBackup, seedPhraseIssueStatus, shouldAccessCodeSkipped ->
|
||||
val totalFiatBalance = accountList.totalFiatBalance
|
||||
val flattenCurrencies = accountList.flattenCurrencies()
|
||||
|
||||
buildList {
|
||||
addUsedOutdatedDataNotification(totalFiatBalance)
|
||||
|
||||
addCriticalNotifications(userWallet, seedPhraseIssueStatus, clickIntents)
|
||||
|
||||
addFinishWalletActivationNotification(
|
||||
userWallet = userWallet,
|
||||
totalFiatBalance = totalFiatBalance,
|
||||
clickIntents = clickIntents,
|
||||
shouldAccessCodeSkipped = shouldAccessCodeSkipped,
|
||||
)
|
||||
|
||||
addInformationalNotifications(
|
||||
userWallet = userWallet,
|
||||
cardTypesResolver = cardTypesResolver,
|
||||
flattenCurrencies = flattenCurrencies,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
addWarningNotifications(
|
||||
userWallet = userWallet,
|
||||
cardTypesResolver = cardTypesResolver,
|
||||
flattenCurrencies = flattenCurrencies,
|
||||
isNeedToBackup = isNeedToBackup,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
}.sortedBy { it.type.ordinal }.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addUsedOutdatedDataNotification(totalFiatBalance: TotalFiatBalance) {
|
||||
addIf(
|
||||
element = WalletNotificationUM.UsedOutdatedData,
|
||||
condition = (totalFiatBalance as? TotalFiatBalance.Loaded)?.source == StatusSource.ONLY_CACHE,
|
||||
)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addCriticalNotifications(
|
||||
userWallet: UserWallet,
|
||||
seedPhraseIssueStatus: SeedPhraseNotificationsStatus,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return
|
||||
}
|
||||
|
||||
addSeedNotificationIfNeeded(userWallet, seedPhraseIssueStatus, clickIntents)
|
||||
|
||||
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
|
||||
addIf(
|
||||
element = WalletNotificationUM.BackupError { clickIntents.onSupportClick() },
|
||||
condition = !backupValidator.isValidBackupStatus(userWallet.scanResponse.card) || userWallet.hasBackupError,
|
||||
)
|
||||
|
||||
addIf(
|
||||
element = WalletNotificationUM.DevCard,
|
||||
condition = !cardTypesResolver.isReleaseFirmwareType(),
|
||||
)
|
||||
|
||||
addIf(
|
||||
element = WalletNotificationUM.FailedCardValidation,
|
||||
condition = cardTypesResolver.isReleaseFirmwareType() && cardTypesResolver.isAttestationFailed(),
|
||||
)
|
||||
|
||||
cardTypesResolver.getRemainingSignatures()?.let { remainingSignatures ->
|
||||
addIf(
|
||||
element = WalletNotificationUM.LowSignatures(count = remainingSignatures),
|
||||
condition = remainingSignatures <= MAX_REMAINING_SIGNATURES_COUNT,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addInformationalNotifications(
|
||||
userWallet: UserWallet,
|
||||
cardTypesResolver: CardTypesResolver?,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
addIf(
|
||||
element = WalletNotificationUM.DemoCard,
|
||||
condition = cardTypesResolver != null && isDemoCardUseCase(cardId = cardTypesResolver.getCardId()),
|
||||
)
|
||||
|
||||
addMissingAddressesNotification(userWallet, flattenCurrencies, clickIntents)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addMissingAddressesNotification(
|
||||
userWallet: UserWallet,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val currencies = flattenCurrencies.getMissingAddressCurrencies().ifEmpty { return }
|
||||
|
||||
addIf(
|
||||
element = WalletNotificationUM.MissingAddresses(
|
||||
tangemIcon = walletInterationIcon(userWallet),
|
||||
missingAddressesCount = currencies.count(),
|
||||
onGenerateClick = {
|
||||
clickIntents.onGenerateMissedAddressesClick(missedAddressCurrencies = currencies)
|
||||
},
|
||||
),
|
||||
condition = currencies.isNotEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun List<CryptoCurrencyStatus>.getMissingAddressCurrencies(): List<CryptoCurrency> {
|
||||
return this
|
||||
.filter { it.value is CryptoCurrencyStatus.MissedDerivation }
|
||||
.map(CryptoCurrencyStatus::currency)
|
||||
}
|
||||
|
||||
private suspend fun MutableList<WalletNotificationUM>.addWarningNotifications(
|
||||
userWallet: UserWallet,
|
||||
cardTypesResolver: CardTypesResolver?,
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
isNeedToBackup: Boolean,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
addIf(
|
||||
element = WalletNotificationUM.MissingBackup(
|
||||
onClick = clickIntents::onAddBackupCardClick,
|
||||
),
|
||||
condition = isNeedToBackup,
|
||||
)
|
||||
|
||||
addIf(
|
||||
element = WalletNotificationUM.TestnetCard,
|
||||
condition = cardTypesResolver?.isTestCard() == true,
|
||||
)
|
||||
|
||||
addIf(
|
||||
element = WalletNotificationUM.SomeNetworksUnreachable,
|
||||
condition = flattenCurrencies.hasUnreachableNetworks(),
|
||||
)
|
||||
|
||||
addCloreMigrationNotification(flattenCurrencies, clickIntents)
|
||||
|
||||
addNoAccountWarning(cryptoCurrencyStatus = flattenCurrencies.firstOrNull())
|
||||
|
||||
addIf(
|
||||
element = WalletNotificationUM.NumberOfSignedHashesIncorrect(
|
||||
onCloseClick = clickIntents::onCloseAlreadySignedHashesWarningClick,
|
||||
),
|
||||
condition = hasSignedHashes(userWallet, flattenCurrencies.firstOrNull()),
|
||||
)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addNoAccountWarning(cryptoCurrencyStatus: CryptoCurrencyStatus?) {
|
||||
val noAccountStatus = cryptoCurrencyStatus?.value as? CryptoCurrencyStatus.NoAccount
|
||||
if (noAccountStatus != null) {
|
||||
add(
|
||||
element = WalletNotificationUM.NoAccount(
|
||||
network = cryptoCurrencyStatus.currency.name,
|
||||
amount = noAccountStatus.amountToCreateAccount.toString(),
|
||||
symbol = cryptoCurrencyStatus.currency.symbol,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addCloreMigrationNotification(
|
||||
flattenCurrencies: List<CryptoCurrencyStatus>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val cloreCurrency = flattenCurrencies.findCloreCurrency() ?: return
|
||||
|
||||
add(
|
||||
WalletNotificationUM.CloreMigration(
|
||||
onStartMigrationClick = { clickIntents.onCloreMigrationClick(cloreCurrency) },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun List<CryptoCurrencyStatus>.findCloreCurrency(): CryptoCurrencyStatus? {
|
||||
return find { currencyStatus ->
|
||||
BlockchainUtils.isClore(currencyStatus.currency.network.rawId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<CryptoCurrencyStatus>.hasUnreachableNetworks(): Boolean {
|
||||
return any { it.value is CryptoCurrencyStatus.Unreachable }
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addFinishWalletActivationNotification(
|
||||
userWallet: UserWallet,
|
||||
totalFiatBalance: TotalFiatBalance,
|
||||
clickIntents: WalletClickIntents,
|
||||
shouldAccessCodeSkipped: Boolean,
|
||||
) {
|
||||
if (userWallet !is UserWallet.Hot) return
|
||||
|
||||
val isBackupExists = userWallet.backedUp
|
||||
val isAccessCodeRequired = userWallet.hotWalletId.authType == HotWalletId.AuthType.NoPassword &&
|
||||
!shouldAccessCodeSkipped
|
||||
val shouldShowFinishActivation = !isBackupExists || isAccessCodeRequired
|
||||
|
||||
val messageEffect = when (totalFiatBalance) {
|
||||
TotalFiatBalance.Failed,
|
||||
TotalFiatBalance.Loading,
|
||||
-> TangemMessageEffect.None
|
||||
is TotalFiatBalance.Loaded -> if (totalFiatBalance.amount.orZero().isPositive()) {
|
||||
TangemMessageEffect.Warning
|
||||
} else {
|
||||
TangemMessageEffect.None
|
||||
}
|
||||
}
|
||||
|
||||
addIf(
|
||||
element = WalletNotificationUM.FinishWalletActivation(
|
||||
messageEffect = messageEffect,
|
||||
onClick = { clickIntents.onFinishWalletActivationClick(isBackupExists) },
|
||||
isBackupExists = isBackupExists,
|
||||
),
|
||||
condition = shouldShowFinishActivation,
|
||||
)
|
||||
}
|
||||
|
||||
private fun MutableList<WalletNotificationUM>.addSeedNotificationIfNeeded(
|
||||
userWallet: UserWallet.Cold,
|
||||
seedPhraseIssueStatus: SeedPhraseNotificationsStatus,
|
||||
clickIntents: WalletClickIntents,
|
||||
) {
|
||||
val isNotificationAvailable = with(userWallet) {
|
||||
val isDemo = isDemoCardUseCase(cardId = userWallet.cardId)
|
||||
val isWalletWithSeedPhrase = scanResponse.cardTypesResolver.isWallet2() && userWallet.isImported
|
||||
|
||||
!isDemo && isWalletWithSeedPhrase
|
||||
}
|
||||
|
||||
when (seedPhraseIssueStatus) {
|
||||
SeedPhraseNotificationsStatus.SHOW_FIRST -> addIf(
|
||||
element = WalletNotificationUM.SeedPhraseNotification(
|
||||
onDeclineClick = clickIntents::onSeedPhraseNotificationDecline,
|
||||
onConfirmClick = clickIntents::onSeedPhraseNotificationConfirm,
|
||||
),
|
||||
condition = isNotificationAvailable,
|
||||
)
|
||||
SeedPhraseNotificationsStatus.SHOW_SECOND -> addIf(
|
||||
element = WalletNotificationUM.SeedPhraseSecondNotification(
|
||||
onDeclineClick = clickIntents::onSeedPhraseSecondNotificationReject,
|
||||
onConfirmClick = clickIntents::onSeedPhraseSecondNotificationAccept,
|
||||
),
|
||||
condition = isNotificationAvailable,
|
||||
)
|
||||
SeedPhraseNotificationsStatus.NOT_NEEDED -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun hasSignedHashes(
|
||||
selectedWallet: UserWallet,
|
||||
cryptoCurrencyStatus: CryptoCurrencyStatus?,
|
||||
): Boolean {
|
||||
if (selectedWallet !is UserWallet.Cold || !selectedWallet.isMultiCurrency) return false
|
||||
val network = cryptoCurrencyStatus?.currency?.network ?: return false
|
||||
|
||||
return hasSingleWalletSignedHashesUseCase(userWallet = selectedWallet, network = network)
|
||||
.conflate()
|
||||
.distinctUntilChanged()
|
||||
.firstOrNull() == true
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val MAX_REMAINING_SIGNATURES_COUNT = 10
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.domain
|
||||
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.core.lce.LceFlow
|
||||
import com.tangem.domain.models.tokenlist.TokenList
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.GetTokenListUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
import timber.log.Timber
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
internal class MultiWalletTokenListStore @Inject constructor(
|
||||
private val getTokenListUseCase: GetTokenListUseCase,
|
||||
) {
|
||||
|
||||
private val flows: ConcurrentHashMap<UserWalletId, LceFlow<TokenListError, TokenList>> by lazy {
|
||||
ConcurrentHashMap()
|
||||
}
|
||||
|
||||
fun addIfNot(userWalletId: UserWalletId, coroutineScope: CoroutineScope) {
|
||||
if (flows[userWalletId] != null) {
|
||||
Timber.d("Flow with token list for $userWalletId already exists")
|
||||
return
|
||||
}
|
||||
|
||||
coroutineScope.ensureActive()
|
||||
|
||||
flows[userWalletId] = getTokenListUseCase
|
||||
.launch(userWalletId)
|
||||
.shareIn(
|
||||
scope = coroutineScope,
|
||||
started = SharingStarted.WhileSubscribed(),
|
||||
replay = 1,
|
||||
)
|
||||
|
||||
Timber.d("Flow with token list for $userWalletId created")
|
||||
}
|
||||
|
||||
fun getOrThrow(userWalletId: UserWalletId): LceFlow<TokenListError, TokenList> {
|
||||
return requireNotNull(flows[userWalletId]) {
|
||||
"Flow with token list for $userWalletId doesn't exist"
|
||||
}
|
||||
}
|
||||
|
||||
fun remove(userWalletId: UserWalletId) {
|
||||
flows.remove(userWalletId)
|
||||
|
||||
Timber.d("Flow with token list for $userWalletId removed")
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
flows.clear()
|
||||
|
||||
Timber.d("All flows with token list cleared")
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.domain
|
||||
|
||||
import com.tangem.domain.tokens.wallet.WalletBalanceFetcher
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.wallet.WalletBalanceFetcher
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveInAndJoin
|
||||
|
|
@ -27,6 +28,7 @@ import javax.inject.Singleton
|
|||
internal class WalletContentFetcher @Inject constructor(
|
||||
private val walletBalanceFetcher: WalletBalanceFetcher,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
|
||||
) {
|
||||
|
||||
private val fetchingJobMap = ConcurrentHashMap<UserWalletId, JobHolder>()
|
||||
|
|
@ -64,8 +66,12 @@ internal class WalletContentFetcher @Inject constructor(
|
|||
Timber.d("Start fetching for $userWalletId")
|
||||
|
||||
val maybeResult = launch {
|
||||
walletBalanceFetcher(params = WalletBalanceFetcher.Params(userWalletId = userWalletId))
|
||||
.onLeft(Timber::e)
|
||||
walletBalanceFetcher(
|
||||
params = WalletBalanceFetcher.Params(
|
||||
userWalletId = userWalletId,
|
||||
isPaymentAccountRefactorEnabled = tangemPayFeatureToggles.isTangemPayAccountsRefactorEnabled,
|
||||
),
|
||||
).onLeft(Timber::e)
|
||||
}
|
||||
.saveInAndJoin(jobHolder)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,52 +1,33 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders
|
||||
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.implementors.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.implementors.MultiWalletContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.implementors.SingleWalletContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.implementors.SingleWalletWithTokenContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.implementors.WalletContentLoader
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class WalletContentLoaderFactory @Inject constructor(
|
||||
private val multiWalletContentLoaderFactory: MultiWalletContentLoaderFactory,
|
||||
private val multiWalletContentLoaderV2Factory: MultiWalletContentLoaderV2.Factory,
|
||||
private val singleWalletWithTokenContentLoaderFactory: SingleWalletWithTokenContentLoaderFactory,
|
||||
private val singleWalletWithTokenContentLoaderV2Factory: SingleWalletWithTokenContentLoaderV2.Factory,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val singleWalletContentLoaderFactory: SingleWalletContentLoaderFactory,
|
||||
private val singleWalletContentLoaderV2Factory: SingleWalletContentLoaderV2.Factory,
|
||||
private val multiWalletContentLoaderFactory: MultiWalletContentLoader.Factory,
|
||||
private val singleWalletWithTokenContentLoaderFactory: SingleWalletWithTokenContentLoader.Factory,
|
||||
private val singleWalletContentLoaderFactory: SingleWalletContentLoader.Factory,
|
||||
) {
|
||||
|
||||
fun create(
|
||||
userWallet: UserWallet,
|
||||
clickIntents: WalletClickIntents,
|
||||
isRefresh: Boolean = false,
|
||||
): WalletContentLoader? {
|
||||
fun create(userWallet: UserWallet, isRefresh: Boolean = false): WalletContentLoader? {
|
||||
return when {
|
||||
userWallet.isMultiCurrency -> {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
multiWalletContentLoaderV2Factory.create(userWallet)
|
||||
} else {
|
||||
multiWalletContentLoaderFactory.create(userWallet, clickIntents)
|
||||
}
|
||||
multiWalletContentLoaderFactory.create(userWallet)
|
||||
}
|
||||
userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken() -> {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
singleWalletWithTokenContentLoaderV2Factory.create(userWallet)
|
||||
} else {
|
||||
singleWalletWithTokenContentLoaderFactory.create(userWallet, clickIntents)
|
||||
}
|
||||
singleWalletWithTokenContentLoaderFactory.create(userWallet)
|
||||
}
|
||||
userWallet is UserWallet.Cold && !userWallet.isMultiCurrency -> {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
singleWalletContentLoaderV2Factory.create(userWallet, isRefresh)
|
||||
} else {
|
||||
singleWalletContentLoaderFactory.create(userWallet, clickIntents, isRefresh)
|
||||
}
|
||||
singleWalletContentLoaderFactory.create(userWallet, isRefresh)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ internal class WalletLoaderStorage @Inject constructor() {
|
|||
}
|
||||
|
||||
fun remove(id: UserWalletId) {
|
||||
loaders[id]?.let {
|
||||
it.forEach(Job::cancel)
|
||||
loaders[id]?.let { jobs ->
|
||||
jobs.forEach(Job::cancel)
|
||||
loaders.remove(id)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import com.tangem.core.decompose.di.ModelScoped
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import kotlinx.coroutines.CloseableCoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.newSingleThreadContext
|
||||
|
|
@ -14,9 +13,8 @@ import javax.inject.Inject
|
|||
/**
|
||||
* Base wallet screen content loader. Use it to load content by [UserWallet].
|
||||
*
|
||||
* @property factory factory that creates loader
|
||||
* @property storage storage that save loader's jobs
|
||||
* @property dispatchers coroutine dispatchers provider
|
||||
* @property factory factory that creates loader
|
||||
* @property storage storage that save loader's jobs
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
@ -33,25 +31,19 @@ internal class WalletScreenContentLoader @Inject constructor(
|
|||
* Load content by [UserWallet]
|
||||
*
|
||||
* @param userWallet user wallet
|
||||
* @param clickIntents click intents
|
||||
* @param isRefresh flag that determinate if content must load again
|
||||
* @param coroutineScope coroutine scope
|
||||
*/
|
||||
fun load(
|
||||
userWallet: UserWallet,
|
||||
clickIntents: WalletClickIntents,
|
||||
isRefresh: Boolean = false,
|
||||
coroutineScope: CoroutineScope,
|
||||
) {
|
||||
fun load(userWallet: UserWallet, isRefresh: Boolean = false, coroutineScope: CoroutineScope) {
|
||||
if (userWallet.isLocked) return
|
||||
|
||||
val id = userWallet.walletId
|
||||
if (!storage.contains(id)) {
|
||||
loadInternal(userWallet, clickIntents, coroutineScope, isRefresh)
|
||||
loadInternal(userWallet, coroutineScope, isRefresh)
|
||||
} else {
|
||||
if (isRefresh) {
|
||||
storage.remove(id)
|
||||
loadInternal(userWallet, clickIntents, coroutineScope, isRefresh = true)
|
||||
loadInternal(userWallet, coroutineScope, isRefresh = true)
|
||||
} else {
|
||||
Timber.d("$id content loading has already started")
|
||||
}
|
||||
|
|
@ -70,15 +62,9 @@ internal class WalletScreenContentLoader @Inject constructor(
|
|||
singleBackgroundDispatcher.close()
|
||||
}
|
||||
|
||||
private fun loadInternal(
|
||||
userWallet: UserWallet,
|
||||
clickIntents: WalletClickIntents,
|
||||
coroutineScope: CoroutineScope,
|
||||
isRefresh: Boolean,
|
||||
) {
|
||||
private fun loadInternal(userWallet: UserWallet, coroutineScope: CoroutineScope, isRefresh: Boolean) {
|
||||
val loader = factory.create(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
isRefresh = isRefresh,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,96 +1,33 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.nft.GetNFTCollectionsUseCase
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.staking.usecase.StakingAvailabilityListUseCase
|
||||
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetShouldShowMainPromoUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Deprecated("Use MultiWalletContentLoaderV2 instead")
|
||||
@ModelScoped
|
||||
internal class MultiWalletContentLoader(
|
||||
private val userWallet: UserWallet,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val tokenListAnalyticsSender: TokenListAnalyticsSender,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender,
|
||||
private val walletWithFundsChecker: WalletWithFundsChecker,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val getNFTCollectionsUseCase: GetNFTCollectionsUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase,
|
||||
private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory,
|
||||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val walletsRepository: WalletsRepository,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
|
||||
private val stakingAvailabilityListUseCase: StakingAvailabilityListUseCase,
|
||||
private val yieldSupplyGetShouldShowMainPromoUseCase: YieldSupplyGetShouldShowMainPromoUseCase,
|
||||
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
|
||||
internal class MultiWalletContentLoader @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet,
|
||||
private val accountListSubscriberFactory: AccountListSubscriber.Factory,
|
||||
private val walletNFTListSubscriberFactory: WalletNFTListSubscriberV2.Factory,
|
||||
private val checkWalletWithFundsSubscriberFactory: CheckWalletWithFundsSubscriber.Factory,
|
||||
private val multiWalletWarningsSubscriberFactory: MultiWalletWarningsSubscriber.Factory,
|
||||
private val multiWalletActionButtonsSubscriberFactory: MultiWalletActionButtonsSubscriber.Factory,
|
||||
private val tangemPayMainSubscriberFactory: TangemPayMainSubscriber.Factory,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> {
|
||||
return buildList {
|
||||
MultiWalletTokenListSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
tokenListAnalyticsSender = tokenListAnalyticsSender,
|
||||
walletWithFundsChecker = walletWithFundsChecker,
|
||||
tokenListStore = tokenListStore,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
applyTokenListSortingUseCase = applyTokenListSortingUseCase,
|
||||
yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase,
|
||||
stakingAvailabilityListUseCase = stakingAvailabilityListUseCase,
|
||||
yieldSupplyGetShouldShowMainPromoUseCase = yieldSupplyGetShouldShowMainPromoUseCase,
|
||||
).let(::add)
|
||||
override fun create(): List<WalletSubscriber> = listOf(
|
||||
accountListSubscriberFactory.create(userWallet),
|
||||
walletNFTListSubscriberFactory.create(userWallet),
|
||||
checkWalletWithFundsSubscriberFactory.create(userWallet),
|
||||
multiWalletWarningsSubscriberFactory.create(userWallet),
|
||||
multiWalletActionButtonsSubscriberFactory.create(userWallet),
|
||||
tangemPayMainSubscriberFactory.create(userWallet),
|
||||
)
|
||||
|
||||
WalletNFTListSubscriber(
|
||||
userWallet = userWallet,
|
||||
getNFTCollectionsUseCase = getNFTCollectionsUseCase,
|
||||
stateHolder = stateHolder,
|
||||
walletsRepository = walletsRepository,
|
||||
clickIntents = clickIntents,
|
||||
currenciesRepository = currenciesRepository,
|
||||
).let(::add)
|
||||
|
||||
MultiWalletWarningsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getMultiWalletWarningsFactory = getMultiWalletWarningsFactory,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
walletWarningsSingleEventSender = walletWarningsSingleEventSender,
|
||||
).let(::add)
|
||||
|
||||
MultiWalletActionButtonsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
getStoryContentUseCase = getStoryContentUseCase,
|
||||
).let(::add)
|
||||
|
||||
if (tangemPayFeatureToggles.isTangemPayEnabled) {
|
||||
add(tangemPayMainSubscriberFactory.create(userWallet))
|
||||
}
|
||||
}
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet): MultiWalletContentLoader
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.nft.GetNFTCollectionsUseCase
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.staking.usecase.StakingAvailabilityListUseCase
|
||||
import com.tangem.domain.tokens.ApplyTokenListSortingUseCase
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetShouldShowMainPromoUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.TangemPayMainSubscriber
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Deprecated("Use MultiWalletContentLoaderV2.Factory instead")
|
||||
@ModelScoped
|
||||
internal class MultiWalletContentLoaderFactory @Inject constructor(
|
||||
private val stateHolder: WalletStateController,
|
||||
private val tokenListAnalyticsSender: TokenListAnalyticsSender,
|
||||
private val walletWithFundsChecker: WalletWithFundsChecker,
|
||||
private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender,
|
||||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val walletsRepository: WalletsRepository,
|
||||
private val getNFTCollectionsUseCase: GetNFTCollectionsUseCase,
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
|
||||
private val stakingAvailabilityListUseCase: StakingAvailabilityListUseCase,
|
||||
private val yieldSupplyGetShouldShowMainPromoUseCase: YieldSupplyGetShouldShowMainPromoUseCase,
|
||||
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
|
||||
private val tangemPayMainSubscriberFactory: TangemPayMainSubscriber.Factory,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): WalletContentLoader {
|
||||
return MultiWalletContentLoader(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
stateHolder = stateHolder,
|
||||
tokenListAnalyticsSender = tokenListAnalyticsSender,
|
||||
walletWithFundsChecker = walletWithFundsChecker,
|
||||
tokenListStore = tokenListStore,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
getMultiWalletWarningsFactory = getMultiWalletWarningsFactory,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
walletWarningsSingleEventSender = walletWarningsSingleEventSender,
|
||||
applyTokenListSortingUseCase = applyTokenListSortingUseCase,
|
||||
getStoryContentUseCase = getStoryContentUseCase,
|
||||
walletsRepository = walletsRepository,
|
||||
getNFTCollectionsUseCase = getNFTCollectionsUseCase,
|
||||
currenciesRepository = currenciesRepository,
|
||||
yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase,
|
||||
stakingAvailabilityListUseCase = stakingAvailabilityListUseCase,
|
||||
tangemPayFeatureToggles = tangemPayFeatureToggles,
|
||||
tangemPayMainSubscriberFactory = tangemPayMainSubscriberFactory,
|
||||
yieldSupplyGetShouldShowMainPromoUseCase = yieldSupplyGetShouldShowMainPromoUseCase,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
||||
import com.tangem.features.tangempay.TangemPayFeatureToggles
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class MultiWalletContentLoaderV2 @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet,
|
||||
private val accountListSubscriberFactory: AccountListSubscriber.Factory,
|
||||
private val tokenListAnalyticsSubscriberFactory: TokenListAnalyticsSubscriber.Factory,
|
||||
private val walletNFTListSubscriberV2Factory: WalletNFTListSubscriberV2.Factory,
|
||||
private val stateController: WalletStateController,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender,
|
||||
private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory,
|
||||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val checkWalletWithFundsSubscriberFactory: CheckWalletWithFundsSubscriber.Factory,
|
||||
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
|
||||
private val tangemPayMainSubscriberFactory: TangemPayMainSubscriber.Factory,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> = listOfNotNull(
|
||||
accountListSubscriberFactory.create(userWallet = userWallet),
|
||||
tokenListAnalyticsSubscriberFactory.create(userWallet = userWallet),
|
||||
walletNFTListSubscriberV2Factory.create(userWallet = userWallet),
|
||||
checkWalletWithFundsSubscriberFactory.create(userWallet = userWallet),
|
||||
MultiWalletWarningsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateController,
|
||||
clickIntents = clickIntents,
|
||||
getMultiWalletWarningsFactory = getMultiWalletWarningsFactory,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
walletWarningsSingleEventSender = walletWarningsSingleEventSender,
|
||||
),
|
||||
MultiWalletActionButtonsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateController,
|
||||
getStoryContentUseCase = getStoryContentUseCase,
|
||||
),
|
||||
|
||||
if (tangemPayFeatureToggles.isTangemPayEnabled) {
|
||||
tangemPayMainSubscriberFactory.create(userWallet)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet): MultiWalletContentLoaderV2
|
||||
}
|
||||
}
|
||||
|
|
@ -1,83 +1,34 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.onramp.GetOnrampTransactionsUseCase
|
||||
import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase
|
||||
import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletContentLoader(
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val isRefresh: Boolean,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
private val getSingleWalletWarningsFactory: GetSingleWalletWarningsFactory,
|
||||
private val setWalletWithFundsFoundUseCase: SetWalletWithFundsFoundUseCase,
|
||||
private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase,
|
||||
private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase,
|
||||
private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
internal class SingleWalletContentLoader @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet.Cold,
|
||||
@Assisted private val isRefresh: Boolean,
|
||||
private val primaryCurrencySubscriberFactory: PrimaryCurrencySubscriber.Factory,
|
||||
private val singleWalletButtonsSubscriberFactory: SingleWalletButtonsSubscriber.Factory,
|
||||
private val singleWalletNotificationsSubscriberFactory: SingleWalletNotificationsSubscriber.Factory,
|
||||
private val singleWalletExpressStatusesSubscriberFactory: SingleWalletExpressStatusesSubscriber.Factory,
|
||||
private val txHistorySubscriberFactory: TxHistorySubscriber.Factory,
|
||||
private val checkWalletWithFundsSubscriberFactory: CheckWalletWithFundsSubscriber.Factory,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> {
|
||||
return listOf(
|
||||
PrimaryCurrencySubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
setWalletWithFundsFoundUseCase = setWalletWithFundsFoundUseCase,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
),
|
||||
SingleWalletButtonsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
getCryptoCurrencyActionsUseCase = getCryptoCurrencyActionsUseCase,
|
||||
),
|
||||
SingleWalletNotificationsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getSingleWalletWarningsFactory = getSingleWalletWarningsFactory,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
),
|
||||
SingleWalletExpressStatusesSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
getOnrampTransactionsUseCase = getOnrampTransactionsUseCase,
|
||||
onrampRemoveTransactionUseCase = onrampRemoveTransactionUseCase,
|
||||
),
|
||||
TxHistorySubscriber(
|
||||
userWallet = userWallet,
|
||||
isRefresh = isRefresh,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
txHistoryItemsCountUseCase = txHistoryItemsCountUseCase,
|
||||
txHistoryItemsUseCase = txHistoryItemsUseCase,
|
||||
),
|
||||
)
|
||||
override fun create(): List<WalletSubscriber> = listOf(
|
||||
primaryCurrencySubscriberFactory.create(userWallet),
|
||||
singleWalletButtonsSubscriberFactory.create(userWallet),
|
||||
singleWalletNotificationsSubscriberFactory.create(userWallet),
|
||||
singleWalletExpressStatusesSubscriberFactory.create(userWallet),
|
||||
txHistorySubscriberFactory.create(userWallet, isRefresh),
|
||||
checkWalletWithFundsSubscriberFactory.create(userWallet),
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet.Cold, isRefresh: Boolean): SingleWalletContentLoader
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.onramp.GetOnrampTransactionsUseCase
|
||||
import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase
|
||||
import com.tangem.domain.settings.SetWalletWithFundsFoundUseCase
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
||||
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
@Suppress("LongParameterList")
|
||||
@Deprecated("Use SingleWalletContentLoaderV2.Factory instead")
|
||||
internal class SingleWalletContentLoaderFactory @Inject constructor(
|
||||
private val stateHolder: WalletStateController,
|
||||
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
private val getSingleWalletWarningsFactory: GetSingleWalletWarningsFactory,
|
||||
private val setWalletWithFundsFoundUseCase: SetWalletWithFundsFoundUseCase,
|
||||
private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase,
|
||||
private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase,
|
||||
private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents, isRefresh: Boolean): WalletContentLoader {
|
||||
return SingleWalletContentLoader(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
isRefresh = isRefresh,
|
||||
stateHolder = stateHolder,
|
||||
getSingleCryptoCurrencyStatusUseCase = getSingleCryptoCurrencyStatusUseCase,
|
||||
getCryptoCurrencyActionsUseCase = getCryptoCurrencyActionsUseCase,
|
||||
getSingleWalletWarningsFactory = getSingleWalletWarningsFactory,
|
||||
setWalletWithFundsFoundUseCase = setWalletWithFundsFoundUseCase,
|
||||
txHistoryItemsCountUseCase = txHistoryItemsCountUseCase,
|
||||
txHistoryItemsUseCase = txHistoryItemsUseCase,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
getOnrampTransactionsUseCase = getOnrampTransactionsUseCase,
|
||||
onrampRemoveTransactionUseCase = onrampRemoveTransactionUseCase,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.account.status.usecase.GetCryptoCurrencyActionsUseCaseV2
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.onramp.GetOnrampTransactionsUseCase
|
||||
import com.tangem.domain.onramp.OnrampRemoveTransactionUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.account.AccountDependencies
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetSingleWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.*
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletContentLoaderV2 @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet.Cold,
|
||||
@Assisted private val isRefresh: Boolean,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val getCryptoCurrencyActionsUseCaseV2: GetCryptoCurrencyActionsUseCaseV2,
|
||||
private val getSingleWalletWarningsFactory: GetSingleWalletWarningsFactory,
|
||||
private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase,
|
||||
private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getOnrampTransactionsUseCase: GetOnrampTransactionsUseCase,
|
||||
private val onrampRemoveTransactionUseCase: OnrampRemoveTransactionUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val accountDependencies: AccountDependencies,
|
||||
private val walletWithFundsChecker: WalletWithFundsChecker,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> = listOf(
|
||||
PrimaryCurrencySubscriberV2(
|
||||
userWallet = userWallet,
|
||||
singleAccountStatusListSupplier = accountDependencies.singleAccountStatusListSupplier,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
stateController = stateHolder,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
),
|
||||
SingleWalletButtonsSubscriberV2(
|
||||
userWallet = userWallet,
|
||||
singleAccountStatusListSupplier = accountDependencies.singleAccountStatusListSupplier,
|
||||
stateController = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getCryptoCurrencyActionsUseCaseV2 = getCryptoCurrencyActionsUseCaseV2,
|
||||
),
|
||||
SingleWalletNotificationsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getSingleWalletWarningsFactory = getSingleWalletWarningsFactory,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
),
|
||||
SingleWalletExpressStatusesSubscriberV2(
|
||||
userWallet = userWallet,
|
||||
singleAccountStatusListSupplier = accountDependencies.singleAccountStatusListSupplier,
|
||||
getOnrampTransactionsUseCase = getOnrampTransactionsUseCase,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
onrampRemoveTransactionUseCase = onrampRemoveTransactionUseCase,
|
||||
stateController = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
),
|
||||
TxHistorySubscriberV2(
|
||||
userWallet = userWallet,
|
||||
singleAccountStatusListSupplier = accountDependencies.singleAccountStatusListSupplier,
|
||||
txHistoryItemsCountUseCase = txHistoryItemsCountUseCase,
|
||||
txHistoryItemsUseCase = txHistoryItemsUseCase,
|
||||
isRefresh = isRefresh,
|
||||
stateController = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
),
|
||||
CheckWalletWithFundsSubscriber(
|
||||
userWallet = userWallet,
|
||||
singleAccountStatusListSupplier = accountDependencies.singleAccountStatusListSupplier,
|
||||
walletWithFundsChecker = walletWithFundsChecker,
|
||||
dispatchers = dispatchers,
|
||||
),
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet.Cold, isRefresh: Boolean): SingleWalletContentLoaderV2
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +1,29 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.staking.usecase.StakingAvailabilityListUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetShouldShowMainPromoUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletActionButtonsSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.CheckWalletWithFundsSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletWarningsSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.SingleWalletWithTokenListSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.SingleWalletWithTokenSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.WalletSubscriber
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
@Deprecated("Use SingleWalletWithTokenContentLoaderV2 instead")
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletWithTokenContentLoader(
|
||||
private val userWallet: UserWallet.Cold,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val tokenListAnalyticsSender: TokenListAnalyticsSender,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender,
|
||||
private val walletWithFundsChecker: WalletWithFundsChecker,
|
||||
private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
|
||||
private val stakingAvailabilityListUseCase: StakingAvailabilityListUseCase,
|
||||
private val yieldSupplyGetShouldShowMainPromoUseCase: YieldSupplyGetShouldShowMainPromoUseCase,
|
||||
internal class SingleWalletWithTokenContentLoader @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet.Cold,
|
||||
private val singleWalletWithTokenSubscriberFactory: SingleWalletWithTokenSubscriber.Factory,
|
||||
private val multiWalletWarningsSubscriberFactory: MultiWalletWarningsSubscriber.Factory,
|
||||
private val checkWalletWithFundsSubscriberFactory: CheckWalletWithFundsSubscriber.Factory,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> {
|
||||
return buildList {
|
||||
SingleWalletWithTokenListSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
tokenListAnalyticsSender = tokenListAnalyticsSender,
|
||||
walletWithFundsChecker = walletWithFundsChecker,
|
||||
tokenListStore = tokenListStore,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase,
|
||||
stakingAvailabilityListUseCase = stakingAvailabilityListUseCase,
|
||||
yieldSupplyGetShouldShowMainPromoUseCase = yieldSupplyGetShouldShowMainPromoUseCase,
|
||||
).let(::add)
|
||||
MultiWalletWarningsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
clickIntents = clickIntents,
|
||||
getMultiWalletWarningsFactory = getMultiWalletWarningsFactory,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
walletWarningsSingleEventSender = walletWarningsSingleEventSender,
|
||||
).let(::add)
|
||||
MultiWalletActionButtonsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateHolder,
|
||||
getStoryContentUseCase = getStoryContentUseCase,
|
||||
).let(::add)
|
||||
}
|
||||
override fun create(): List<WalletSubscriber> = listOf(
|
||||
singleWalletWithTokenSubscriberFactory.create(userWallet),
|
||||
multiWalletWarningsSubscriberFactory.create(userWallet),
|
||||
checkWalletWithFundsSubscriberFactory.create(userWallet),
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet.Cold): SingleWalletWithTokenContentLoader
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.promo.GetStoryContentUseCase
|
||||
import com.tangem.domain.staking.usecase.StakingAvailabilityListUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyApyFlowUseCase
|
||||
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetShouldShowMainPromoUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.TokenListAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.MultiWalletTokenListStore
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletWithFundsChecker
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import javax.inject.Inject
|
||||
|
||||
// TODO: Refactor
|
||||
@Suppress("LongParameterList")
|
||||
@Deprecated("Use SingleWalletWithTokenContentLoaderV2.Factory instead")
|
||||
@ModelScoped
|
||||
internal class SingleWalletWithTokenContentLoaderFactory @Inject constructor(
|
||||
private val stateHolder: WalletStateController,
|
||||
private val tokenListAnalyticsSender: TokenListAnalyticsSender,
|
||||
private val walletWithFundsChecker: WalletWithFundsChecker,
|
||||
private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory,
|
||||
private val tokenListStore: MultiWalletTokenListStore,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender,
|
||||
private val getStoryContentUseCase: GetStoryContentUseCase,
|
||||
private val yieldSupplyApyFlowUseCase: YieldSupplyApyFlowUseCase,
|
||||
private val stakingAvailabilityListUseCase: StakingAvailabilityListUseCase,
|
||||
private val yieldSupplyGetShouldShowMainPromoUseCase: YieldSupplyGetShouldShowMainPromoUseCase,
|
||||
) {
|
||||
|
||||
fun create(userWallet: UserWallet.Cold, clickIntents: WalletClickIntents): SingleWalletWithTokenContentLoader {
|
||||
return SingleWalletWithTokenContentLoader(
|
||||
userWallet = userWallet,
|
||||
clickIntents = clickIntents,
|
||||
stateHolder = stateHolder,
|
||||
tokenListAnalyticsSender = tokenListAnalyticsSender,
|
||||
walletWithFundsChecker = walletWithFundsChecker,
|
||||
getMultiWalletWarningsFactory = getMultiWalletWarningsFactory,
|
||||
tokenListStore = tokenListStore,
|
||||
getSelectedAppCurrencyUseCase = getSelectedAppCurrencyUseCase,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
walletWarningsSingleEventSender = walletWarningsSingleEventSender,
|
||||
getStoryContentUseCase = getStoryContentUseCase,
|
||||
yieldSupplyApyFlowUseCase = yieldSupplyApyFlowUseCase,
|
||||
stakingAvailabilityListUseCase = stakingAvailabilityListUseCase,
|
||||
yieldSupplyGetShouldShowMainPromoUseCase = yieldSupplyGetShouldShowMainPromoUseCase,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.loaders.implementors
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsAnalyticsSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.analytics.utils.WalletWarningsSingleEventSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.GetMultiWalletWarningsFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.CheckWalletWithFundsSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.MultiWalletWarningsSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.SingleWalletWithTokenSubscriber
|
||||
import com.tangem.feature.wallet.presentation.wallet.subscribers.WalletSubscriber
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SingleWalletWithTokenContentLoaderV2 @AssistedInject constructor(
|
||||
@Assisted private val userWallet: UserWallet.Cold,
|
||||
private val singleWalletWithTokenSubscriberFactory: SingleWalletWithTokenSubscriber.Factory,
|
||||
private val checkWalletWithFundsSubscriberFactory: CheckWalletWithFundsSubscriber.Factory,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
private val stateController: WalletStateController,
|
||||
private val walletWarningsAnalyticsSender: WalletWarningsAnalyticsSender,
|
||||
private val walletWarningsSingleEventSender: WalletWarningsSingleEventSender,
|
||||
private val getMultiWalletWarningsFactory: GetMultiWalletWarningsFactory,
|
||||
) : WalletContentLoader(id = userWallet.walletId) {
|
||||
|
||||
override fun create(): List<WalletSubscriber> = listOf(
|
||||
singleWalletWithTokenSubscriberFactory.create(userWallet),
|
||||
MultiWalletWarningsSubscriber(
|
||||
userWallet = userWallet,
|
||||
stateHolder = stateController,
|
||||
clickIntents = clickIntents,
|
||||
getMultiWalletWarningsFactory = getMultiWalletWarningsFactory,
|
||||
walletWarningsAnalyticsSender = walletWarningsAnalyticsSender,
|
||||
walletWarningsSingleEventSender = walletWarningsSingleEventSender,
|
||||
),
|
||||
checkWalletWithFundsSubscriberFactory.create(userWallet),
|
||||
)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(userWallet: UserWallet.Cold): SingleWalletWithTokenContentLoaderV2
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state
|
||||
|
||||
import com.tangem.core.ui.DesignFeatureToggles
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.NOT_INITIALIZED_WALLET_INDEX
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTopBarConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.CloseBottomSheetTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.OpenBottomSheetTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.WalletScreenStateTransformer
|
||||
|
|
@ -25,7 +23,9 @@ import javax.inject.Singleton
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Singleton
|
||||
internal class WalletStateController @Inject constructor() {
|
||||
internal class WalletStateController @Inject constructor(
|
||||
private val designFeatureToggles: DesignFeatureToggles,
|
||||
) {
|
||||
|
||||
val uiState: StateFlow<WalletScreenState> get() = mutableUiState
|
||||
|
||||
|
|
@ -53,6 +53,10 @@ internal class WalletStateController @Inject constructor() {
|
|||
return value.wallets.firstOrNull { it.walletCardState.id == userWalletId }
|
||||
}
|
||||
|
||||
fun getWalletUM(userWalletId: UserWalletId): WalletUM? {
|
||||
return value.wallets2.firstOrNull { it.walletsBalanceUM.id == userWalletId }
|
||||
}
|
||||
|
||||
fun getWalletStateIfSelected(walletId: UserWalletId): WalletState? {
|
||||
val selectedWalletId = getSelectedWalletId()
|
||||
|
||||
|
|
@ -61,16 +65,40 @@ internal class WalletStateController @Inject constructor() {
|
|||
}
|
||||
}
|
||||
|
||||
fun getWalletUMIfSelected(walletId: UserWalletId): WalletUM? {
|
||||
val selectedWalletId = getSelectedWalletId()
|
||||
|
||||
return value.wallets2.firstOrNull {
|
||||
it.walletsBalanceUM.id == walletId && it.walletsBalanceUM.id == selectedWalletId
|
||||
}
|
||||
}
|
||||
|
||||
fun getSelectedWallet(): WalletState {
|
||||
return with(value) { wallets[selectedWalletIndex] }
|
||||
}
|
||||
|
||||
fun getSelectedWalletUM(): WalletUM {
|
||||
return with(value) { wallets2[selectedWalletIndex] }
|
||||
}
|
||||
|
||||
fun getSelectedWalletId(): UserWalletId {
|
||||
return with(value) { wallets[selectedWalletIndex].walletCardState.id }
|
||||
return with(value) {
|
||||
if (designFeatureToggles.isRedesignEnabled) {
|
||||
wallets2[selectedWalletIndex].walletsBalanceUM.id
|
||||
} else {
|
||||
wallets[selectedWalletIndex].walletCardState.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getWalletIndexByWalletId(userWalletId: UserWalletId): Int? {
|
||||
return with(value) { wallets.indexOfFirstOrNull { it.walletCardState.id == userWalletId } }
|
||||
return with(value) {
|
||||
if (designFeatureToggles.isRedesignEnabled) {
|
||||
wallets2.indexOfFirstOrNull { it.walletsBalanceUM.id == userWalletId }
|
||||
} else {
|
||||
wallets.indexOfFirstOrNull { it.walletCardState.id == userWalletId }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun showBottomSheet(
|
||||
|
|
@ -105,12 +133,12 @@ internal class WalletStateController @Inject constructor() {
|
|||
topBarConfig = WalletTopBarConfig(onDetailsClick = {}),
|
||||
selectedWalletIndex = NOT_INITIALIZED_WALLET_INDEX,
|
||||
wallets = persistentListOf(),
|
||||
wallets2 = persistentListOf(),
|
||||
onWalletChange = { _, _ -> },
|
||||
event = consumedEvent(),
|
||||
isHidingMode = false,
|
||||
showMarketsOnboarding = false,
|
||||
onDismissMarketsTooltip = {},
|
||||
isNewMarketEnabled = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
/**
|
||||
* Represents the state of the wallet balance in the UI.
|
||||
*
|
||||
* The sealed interface has three implementations:
|
||||
* - [Content]: Represents the state when the wallet balance is successfully loaded.
|
||||
* - [Error]: Represents the state when there was an error loading the wallet balance.
|
||||
* - [Loading]: Represents the state when the wallet balance is currently being loaded.
|
||||
*
|
||||
* @property id The unique identifier of the wallet.
|
||||
* @property name The name of the wallet.
|
||||
*/
|
||||
@Immutable
|
||||
internal sealed interface WalletBalanceUM {
|
||||
|
||||
/** Wallet Id */
|
||||
val id: UserWalletId
|
||||
|
||||
/** Wallet Name */
|
||||
val name: String
|
||||
|
||||
/**
|
||||
* Wallet card content state
|
||||
*
|
||||
* @property id wallet id
|
||||
* @property name wallet name
|
||||
* @property balance wallet balance
|
||||
*/
|
||||
data class Content(
|
||||
override val id: UserWalletId,
|
||||
override val name: String,
|
||||
val balance: TextReference,
|
||||
val isBalanceFlickering: Boolean,
|
||||
val isZeroBalance: Boolean?,
|
||||
) : WalletBalanceUM
|
||||
|
||||
/**
|
||||
* Wallet card error state
|
||||
*
|
||||
* @property id wallet id
|
||||
* @property name wallet name
|
||||
*/
|
||||
data class Error(
|
||||
override val id: UserWalletId,
|
||||
override val name: String,
|
||||
) : WalletBalanceUM
|
||||
|
||||
/**
|
||||
* Wallet card loading state
|
||||
*
|
||||
* @property id wallet id
|
||||
* @property name wallet name
|
||||
*/
|
||||
data class Loading(
|
||||
override val id: UserWalletId,
|
||||
override val name: String,
|
||||
) : WalletBalanceUM
|
||||
|
||||
fun copySealed(name: String): WalletBalanceUM {
|
||||
return when (this) {
|
||||
is Content -> copy(name = name)
|
||||
is Error -> copy(name = name)
|
||||
is Loading -> copy(name = name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
||||
/**
|
||||
* Wallet bottom sheet config
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
sealed class WalletBottomSheetConfig(
|
||||
open val title: TextReference,
|
||||
open val subtitle: TextReference,
|
||||
@DrawableRes open val iconResId: Int,
|
||||
val primaryButtonConfig: ButtonConfig,
|
||||
val secondaryButtonConfig: ButtonConfig,
|
||||
) : TangemBottomSheetConfigContent {
|
||||
|
||||
data class ButtonConfig(
|
||||
val text: TextReference,
|
||||
val onClick: () -> Unit,
|
||||
@DrawableRes val iconResId: Int? = null,
|
||||
)
|
||||
|
||||
data class UnlockWallets(val onUnlockClick: () -> Unit, val onScanClick: () -> Unit) : WalletBottomSheetConfig(
|
||||
title = resourceReference(id = R.string.common_access_denied),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.unlock_wallet_description_full,
|
||||
formatArgs = wrappedList(
|
||||
resourceReference(R.string.common_biometrics),
|
||||
),
|
||||
),
|
||||
iconResId = R.drawable.ic_locked_24,
|
||||
primaryButtonConfig = ButtonConfig(
|
||||
text = resourceReference(
|
||||
id = R.string.user_wallet_list_unlock_all_with,
|
||||
formatArgs = wrappedList(resourceReference(R.string.common_biometrics)),
|
||||
),
|
||||
onClick = onUnlockClick,
|
||||
),
|
||||
secondaryButtonConfig = ButtonConfig(
|
||||
text = resourceReference(id = R.string.welcome_unlock_card),
|
||||
onClick = onScanClick,
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,496 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.tangem.core.ui.ds.button.TangemButtonType
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.message.TangemMessageButtonUM
|
||||
import com.tangem.core.ui.ds.message.TangemMessageEffect
|
||||
import com.tangem.core.ui.ds.message.TangemMessageUM
|
||||
import com.tangem.core.ui.extensions.pluralReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/**
|
||||
* Wallet notification types
|
||||
*/
|
||||
internal enum class WalletNotificationType {
|
||||
Status,
|
||||
Critical,
|
||||
Warning,
|
||||
Promo,
|
||||
Survey,
|
||||
Informational,
|
||||
}
|
||||
|
||||
/**
|
||||
* Wallet notification UI model
|
||||
*
|
||||
* @property messageUM - message to show in notification
|
||||
* @property type - type of notification, affects design and priority
|
||||
*/
|
||||
internal sealed class WalletNotificationUM(val messageUM: TangemMessageUM, val type: WalletNotificationType) {
|
||||
|
||||
// region Status
|
||||
data object SomeNetworksUnreachable : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "SomeNetworksUnreachableNotification",
|
||||
title = resourceReference(id = R.string.warning_some_networks_unreachable_title),
|
||||
subtitle = resourceReference(id = R.string.warning_some_networks_unreachable_message),
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.status.attention },
|
||||
),
|
||||
messageEffect = TangemMessageEffect.None,
|
||||
),
|
||||
type = WalletNotificationType.Status,
|
||||
)
|
||||
|
||||
data object UsedOutdatedData : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "UsedOutdatedDataNotification",
|
||||
title = stringReference("Missing some token balances"), // todo redesign main lokalise
|
||||
subtitle = stringReference("Will be updated as soon as possible"), // todo redesign main lokalise
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_error_sync_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.status.attention },
|
||||
),
|
||||
messageEffect = TangemMessageEffect.None,
|
||||
),
|
||||
type = WalletNotificationType.Status,
|
||||
)
|
||||
|
||||
data object FailedCardValidation : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "FailedCardValidationNotification",
|
||||
title = resourceReference(id = R.string.warning_failed_to_verify_card_title),
|
||||
subtitle = resourceReference(id = R.string.warning_failed_to_verify_card_message),
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
messageEffect = TangemMessageEffect.Warning,
|
||||
),
|
||||
type = WalletNotificationType.Status,
|
||||
)
|
||||
|
||||
data object DevCard : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "DevCardNotification",
|
||||
title = resourceReference(id = R.string.warning_developer_card_title),
|
||||
subtitle = resourceReference(id = R.string.warning_developer_card_message),
|
||||
messageEffect = TangemMessageEffect.None,
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Status,
|
||||
)
|
||||
|
||||
data object TestnetCard : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "TestnetCardNotification",
|
||||
title = resourceReference(id = R.string.warning_testnet_card_title),
|
||||
subtitle = resourceReference(id = R.string.warning_testnet_card_message),
|
||||
messageEffect = TangemMessageEffect.None,
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Status,
|
||||
)
|
||||
|
||||
data object DemoCard : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "DemoCardNotification",
|
||||
title = resourceReference(id = R.string.warning_demo_mode_title),
|
||||
subtitle = resourceReference(id = R.string.warning_demo_mode_message),
|
||||
messageEffect = TangemMessageEffect.None,
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Status,
|
||||
)
|
||||
// endregion
|
||||
|
||||
// region Critical
|
||||
data class BackupError(val onClick: () -> Unit) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "BackupErrorNotification",
|
||||
title = resourceReference(id = R.string.warning_backup_errors_title),
|
||||
subtitle = resourceReference(id = R.string.warning_backup_errors_message),
|
||||
messageEffect = TangemMessageEffect.Warning,
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.common_contact_support),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onClick,
|
||||
),
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Critical,
|
||||
)
|
||||
|
||||
data class SeedPhraseNotification(
|
||||
val onDeclineClick: () -> Unit,
|
||||
val onConfirmClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "SeedPhraseIssueNotification",
|
||||
title = resourceReference(id = R.string.warning_seedphrase_issue_title),
|
||||
subtitle = resourceReference(id = R.string.warning_seedphrase_issue_message),
|
||||
messageEffect = TangemMessageEffect.Warning,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.common_no),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onDeclineClick,
|
||||
),
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.common_yes),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onConfirmClick,
|
||||
),
|
||||
),
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Critical,
|
||||
)
|
||||
|
||||
data class SeedPhraseSecondNotification(
|
||||
val onDeclineClick: () -> Unit,
|
||||
val onConfirmClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "SeedPhraseSecondIssueNotification",
|
||||
title = resourceReference(id = R.string.warning_seedphrase_action_required_title),
|
||||
subtitle = resourceReference(id = R.string.warning_seedphrase_contacted_support),
|
||||
messageEffect = TangemMessageEffect.Warning,
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.seed_warning_no),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onDeclineClick,
|
||||
),
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.seed_warning_yes),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onConfirmClick,
|
||||
),
|
||||
),
|
||||
|
||||
),
|
||||
type = WalletNotificationType.Critical,
|
||||
)
|
||||
|
||||
data class MissingBackup(val onClick: () -> Unit) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "MissingBackupNotification",
|
||||
title = resourceReference(id = R.string.warning_no_backup_title),
|
||||
subtitle = resourceReference(id = R.string.warning_no_backup_message),
|
||||
messageEffect = TangemMessageEffect.Warning,
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.button_start_backup_process),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onClick,
|
||||
),
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Critical,
|
||||
)
|
||||
|
||||
data class LowSignatures(val count: Int) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "LowSignaturesNotification",
|
||||
title = resourceReference(id = R.string.warning_low_signatures_title),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.warning_low_signatures_message,
|
||||
formatArgs = wrappedList(count.toString()),
|
||||
),
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
messageEffect = TangemMessageEffect.None,
|
||||
),
|
||||
type = WalletNotificationType.Critical,
|
||||
)
|
||||
|
||||
data class FinishWalletActivation(
|
||||
val messageEffect: TangemMessageEffect,
|
||||
val isBackupExists: Boolean,
|
||||
val onClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "FinishWalletActivationNotification",
|
||||
title = resourceReference(R.string.hw_activation_need_title),
|
||||
subtitle = if (isBackupExists) {
|
||||
resourceReference(R.string.hw_activation_need_warning_description)
|
||||
} else {
|
||||
resourceReference(R.string.hw_activation_need_description)
|
||||
},
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.img_knight_shield_32,
|
||||
tintReference = {
|
||||
when (messageEffect) {
|
||||
TangemMessageEffect.Warning -> TangemTheme.colors2.graphic.neutral.primary
|
||||
else -> TangemTheme.colors2.graphic.status.attention
|
||||
}
|
||||
},
|
||||
),
|
||||
messageEffect = messageEffect,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(R.string.hw_activation_need_finish),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onClick,
|
||||
),
|
||||
),
|
||||
),
|
||||
type = when (messageEffect) {
|
||||
TangemMessageEffect.Warning -> WalletNotificationType.Critical
|
||||
else -> WalletNotificationType.Warning
|
||||
},
|
||||
)
|
||||
|
||||
data class NumberOfSignedHashesIncorrect(val onCloseClick: () -> Unit) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "NumberOfSignedHashesIncorrectNotification",
|
||||
title = resourceReference(id = R.string.warning_number_of_signed_hashes_incorrect_title),
|
||||
subtitle = resourceReference(id = R.string.warning_number_of_signed_hashes_incorrect_message),
|
||||
messageEffect = TangemMessageEffect.Warning,
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.img_knight_shield_32,
|
||||
tintReference = { TangemTheme.colors2.graphic.neutral.primary },
|
||||
),
|
||||
onCloseClick = onCloseClick,
|
||||
),
|
||||
type = WalletNotificationType.Critical,
|
||||
)
|
||||
// endregion
|
||||
|
||||
// region Warning
|
||||
data class MissingAddresses(
|
||||
@DrawableRes val tangemIcon: Int?,
|
||||
val missingAddressesCount: Int,
|
||||
val onGenerateClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "MissingAddressesNotification",
|
||||
title = resourceReference(id = R.string.warning_missing_derivation_title),
|
||||
subtitle = pluralReference(
|
||||
id = R.plurals.warning_missing_derivation_message,
|
||||
count = missingAddressesCount,
|
||||
formatArgs = wrappedList(missingAddressesCount),
|
||||
),
|
||||
isCentered = true,
|
||||
messageEffect = TangemMessageEffect.Card,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.common_generate_addresses),
|
||||
type = TangemButtonType.Primary,
|
||||
iconRes = tangemIcon,
|
||||
onClick = onGenerateClick,
|
||||
),
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Warning,
|
||||
)
|
||||
|
||||
data class NoAccount(val network: String, val symbol: String, val amount: String) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "NoAccountNotification",
|
||||
title = resourceReference(id = R.string.warning_no_account_title),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.no_account_generic,
|
||||
wrappedList(network, amount, symbol),
|
||||
),
|
||||
messageEffect = TangemMessageEffect.None,
|
||||
),
|
||||
type = WalletNotificationType.Warning,
|
||||
)
|
||||
|
||||
data class UnlockWallets(val onClick: () -> Unit) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "UnlockWalletsNotification",
|
||||
title = resourceReference(id = R.string.common_access_denied),
|
||||
subtitle = resourceReference(
|
||||
id = R.string.warning_access_denied_message,
|
||||
formatArgs = wrappedList(
|
||||
resourceReference(R.string.common_biometrics),
|
||||
),
|
||||
),
|
||||
onClick = onClick,
|
||||
messageEffect = TangemMessageEffect.Card,
|
||||
isCentered = true,
|
||||
),
|
||||
type = WalletNotificationType.Warning,
|
||||
)
|
||||
// endregion
|
||||
|
||||
// region Promo
|
||||
data class NoteMigration(val onClick: () -> Unit) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "NoteMigrationNotification",
|
||||
title = resourceReference(R.string.wallet_promo_banner_title),
|
||||
subtitle = resourceReference(R.string.wallet_promo_banner_description),
|
||||
messageEffect = TangemMessageEffect.Magic,
|
||||
isCentered = true,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(R.string.wallet_promo_banner_button_title),
|
||||
onClick = onClick,
|
||||
type = TangemButtonType.Primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Promo,
|
||||
)
|
||||
|
||||
data class OnePlusOnePromo(
|
||||
val onCloseClick: () -> Unit,
|
||||
val onClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "OnePlusOnePromoNotification",
|
||||
title = resourceReference(R.string.notification_one_plus_one_title),
|
||||
subtitle = resourceReference(R.string.notification_one_plus_one_text),
|
||||
messageEffect = TangemMessageEffect.Magic,
|
||||
onCloseClick = onCloseClick,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(R.string.notification_one_plus_one_button),
|
||||
type = TangemButtonType.Primary,
|
||||
onClick = onClick,
|
||||
),
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Promo,
|
||||
)
|
||||
|
||||
data class YieldPromo(
|
||||
val onCloseClick: () -> Unit,
|
||||
val onTermsAndConditionsClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "YieldPromoNotification",
|
||||
title = resourceReference(R.string.notification_yield_promo_title),
|
||||
subtitle = resourceReference(R.string.notification_yield_promo_text),
|
||||
onCloseClick = onCloseClick,
|
||||
messageEffect = TangemMessageEffect.Magic,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(R.string.notification_yield_promo_button),
|
||||
type = TangemButtonType.Primary,
|
||||
onClick = onTermsAndConditionsClick,
|
||||
),
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Promo,
|
||||
)
|
||||
// endregion
|
||||
|
||||
// region Survey
|
||||
data class RateApp(
|
||||
val onLikeClick: () -> Unit,
|
||||
val onDislikeClick: () -> Unit,
|
||||
val onCloseClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "RateAppNotification",
|
||||
title = resourceReference(id = R.string.warning_rate_app_title),
|
||||
subtitle = resourceReference(id = R.string.warning_rate_app_message),
|
||||
isCentered = true,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.warning_button_could_be_better),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onDislikeClick,
|
||||
),
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(id = R.string.warning_button_like_it),
|
||||
type = TangemButtonType.Primary,
|
||||
onClick = onLikeClick,
|
||||
),
|
||||
),
|
||||
messageEffect = TangemMessageEffect.None,
|
||||
onCloseClick = onCloseClick,
|
||||
),
|
||||
type = WalletNotificationType.Survey,
|
||||
)
|
||||
// endregion
|
||||
|
||||
// region Informational
|
||||
data class PushNotifications(
|
||||
val onCloseClick: () -> Unit,
|
||||
val onEnabledClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "PushNotificationsNotification",
|
||||
title = resourceReference(R.string.user_push_notification_banner_title),
|
||||
subtitle = resourceReference(R.string.user_push_notification_banner_subtitle),
|
||||
onCloseClick = onCloseClick,
|
||||
messageEffect = TangemMessageEffect.Magic,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(R.string.common_later),
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
onClick = onCloseClick,
|
||||
),
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(R.string.common_enable),
|
||||
type = TangemButtonType.Primary,
|
||||
onClick = onEnabledClick,
|
||||
),
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Informational,
|
||||
)
|
||||
|
||||
data class CloreMigration(
|
||||
val onStartMigrationClick: () -> Unit,
|
||||
) : WalletNotificationUM(
|
||||
messageUM = TangemMessageUM(
|
||||
id = "CloreMigrationNotification",
|
||||
title = resourceReference(com.tangem.core.res.R.string.warning_clore_migration_title),
|
||||
subtitle = resourceReference(com.tangem.core.res.R.string.warning_clore_migration_description),
|
||||
iconUM = TangemIconUM.Icon(
|
||||
iconRes = R.drawable.ic_attention_default_24,
|
||||
tintReference = { TangemTheme.colors2.graphic.status.attention },
|
||||
),
|
||||
messageEffect = TangemMessageEffect.None,
|
||||
buttonsUM = persistentListOf(
|
||||
TangemMessageButtonUM(
|
||||
text = resourceReference(com.tangem.core.res.R.string.warning_clore_migration_button),
|
||||
onClick = onStartMigrationClick,
|
||||
type = TangemButtonType.PrimaryInverse,
|
||||
),
|
||||
),
|
||||
),
|
||||
type = WalletNotificationType.Informational,
|
||||
)
|
||||
// endregion
|
||||
}
|
||||
|
|
@ -9,10 +9,10 @@ internal data class WalletScreenState(
|
|||
val topBarConfig: WalletTopBarConfig,
|
||||
val selectedWalletIndex: Int,
|
||||
val wallets: ImmutableList<WalletState>,
|
||||
val wallets2: ImmutableList<WalletUM>,
|
||||
val onWalletChange: (index: Int, onlyState: Boolean) -> Unit,
|
||||
val event: StateEvent<WalletEvent>,
|
||||
val isHidingMode: Boolean,
|
||||
val showMarketsOnboarding: Boolean,
|
||||
val isNewMarketEnabled: Boolean,
|
||||
val onDismissMarketsTooltip: () -> Unit,
|
||||
)
|
||||
|
|
@ -55,11 +55,6 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
override val nftState: WalletNFTItemUM = WalletNFTItemUM.Hidden
|
||||
override val tangemPayState: TangemPayState = TangemPayState.Empty
|
||||
}
|
||||
|
||||
enum class WalletType {
|
||||
Hot,
|
||||
Cold,
|
||||
}
|
||||
}
|
||||
|
||||
sealed class SingleCurrency : WalletState, TxHistoryStateHolder {
|
||||
|
|
@ -96,4 +91,9 @@ internal sealed interface WalletState : WalletStateHolder {
|
|||
override val marketPriceBlockState: MarketPriceBlockState? = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class WalletType {
|
||||
Hot,
|
||||
Cold,
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||
import com.tangem.core.ui.ds.row.TangemRowUM
|
||||
import com.tangem.core.ui.ds.row.header.TangemHeaderRowUM
|
||||
import com.tangem.core.ui.ds.row.token.TangemTokenRowUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/**
|
||||
* State of the tokens list in the wallet screen
|
||||
*
|
||||
* @property tokenList list of tokens to display
|
||||
* @property organizeButtonUM configuration for the "Organize Tokens" button, if it should
|
||||
*/
|
||||
@Immutable
|
||||
internal sealed class WalletTokensListUM {
|
||||
|
||||
abstract val tokenList: ImmutableList<TokensListItemUM2>
|
||||
abstract val organizeButtonUM: TangemButtonUM?
|
||||
|
||||
data object Empty : WalletTokensListUM() {
|
||||
override val tokenList: ImmutableList<TokensListItemUM2.Portfolio> = persistentListOf()
|
||||
override val organizeButtonUM: TangemButtonUM? = null
|
||||
}
|
||||
|
||||
data object Loading : WalletTokensListUM() {
|
||||
override val tokenList: ImmutableList<TokensListItemUM2> = persistentListOf(
|
||||
TokensListItemUM2.Portfolio(
|
||||
tokenRowUM = TangemTokenRowUM.Loading(id = "0"),
|
||||
tokenList = persistentListOf(),
|
||||
isExpanded = false,
|
||||
isCollapsable = true,
|
||||
),
|
||||
TokensListItemUM2.Portfolio(
|
||||
tokenRowUM = TangemTokenRowUM.Loading(id = "1"),
|
||||
tokenList = persistentListOf(),
|
||||
isExpanded = false,
|
||||
isCollapsable = true,
|
||||
),
|
||||
TokensListItemUM2.Portfolio(
|
||||
tokenRowUM = TangemTokenRowUM.Loading(id = "2"),
|
||||
tokenList = persistentListOf(),
|
||||
isExpanded = false,
|
||||
isCollapsable = true,
|
||||
),
|
||||
)
|
||||
override val organizeButtonUM: TangemButtonUM? = null
|
||||
}
|
||||
|
||||
data class Content(
|
||||
override val tokenList: ImmutableList<TokensListItemUM2>,
|
||||
override val organizeButtonUM: TangemButtonUM?,
|
||||
) : WalletTokensListUM()
|
||||
}
|
||||
|
||||
/**
|
||||
* State of token list item in the wallet screen
|
||||
*/
|
||||
@Immutable
|
||||
internal sealed interface TokensListItemUM2 {
|
||||
val tokenRowUM: TangemRowUM
|
||||
|
||||
data class GroupTitle(
|
||||
override val tokenRowUM: TangemHeaderRowUM,
|
||||
) : TokensListItemUM2
|
||||
|
||||
data class Token(
|
||||
override val tokenRowUM: TangemTokenRowUM,
|
||||
) : TokensListItemUM2
|
||||
|
||||
data class Portfolio(
|
||||
override val tokenRowUM: TangemTokenRowUM,
|
||||
val tokenList: ImmutableList<TokensListItemUM2>,
|
||||
val isExpanded: Boolean,
|
||||
val isCollapsable: Boolean,
|
||||
) : TokensListItemUM2
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.model
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.ds.button.TangemButtonUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Immutable
|
||||
internal sealed interface WalletUM {
|
||||
|
||||
val pullToRefreshConfig: PullToRefreshConfig
|
||||
val walletsBalanceUM: WalletBalanceUM
|
||||
|
||||
val buttons: PersistentList<TangemButtonUM>
|
||||
val notifications: ImmutableList<WalletNotificationUM>
|
||||
val notificationsCarousel: ImmutableList<WalletNotificationUM>
|
||||
|
||||
val tokensListUM: WalletTokensListUM
|
||||
|
||||
val nftState: WalletNFTItemUM
|
||||
|
||||
val type: WalletType
|
||||
|
||||
val tangemPayState: TangemPayState
|
||||
|
||||
data class Content(
|
||||
override val pullToRefreshConfig: PullToRefreshConfig,
|
||||
override val walletsBalanceUM: WalletBalanceUM,
|
||||
override val buttons: PersistentList<TangemButtonUM>,
|
||||
override val notifications: ImmutableList<WalletNotificationUM>,
|
||||
override val notificationsCarousel: ImmutableList<WalletNotificationUM>,
|
||||
override val tokensListUM: WalletTokensListUM,
|
||||
override val nftState: WalletNFTItemUM,
|
||||
override val type: WalletType,
|
||||
override val tangemPayState: TangemPayState,
|
||||
) : WalletUM
|
||||
|
||||
data class Locked(
|
||||
override val walletsBalanceUM: WalletBalanceUM,
|
||||
override val buttons: PersistentList<TangemButtonUM>,
|
||||
override val type: WalletType,
|
||||
override val notifications: ImmutableList<WalletNotificationUM> = persistentListOf(),
|
||||
) : WalletUM {
|
||||
override val notificationsCarousel: ImmutableList<WalletNotificationUM> = persistentListOf()
|
||||
override val pullToRefreshConfig = PullToRefreshConfig(false, {})
|
||||
override val tokensListUM: WalletTokensListUM = WalletTokensListUM.Empty // todo redesign main locked state
|
||||
override val nftState: WalletNFTItemUM = WalletNFTItemUM.Hidden
|
||||
override val tangemPayState: TangemPayState = TangemPayState.Empty
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class CloseBottomSheetTransformer(userWalletId: UserWalletId) : WalletStateTransformer(userWalletId) {
|
||||
|
||||
|
|
@ -22,6 +23,10 @@ internal class CloseBottomSheetTransformer(userWalletId: UserWalletId) : WalletS
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun updateConfig(prevState: WalletState) = prevState.bottomSheetConfig?.copy(
|
||||
isShown = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState.MultiCurrency.WalletType
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletLoadingStateFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.createStateByWalletType
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
|||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class OpenBottomSheetTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -28,6 +29,10 @@ internal class OpenBottomSheetTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun updateConfig() = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = onDismissBottomSheet,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.domain.models.wallet.UserWallet
|
|||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletLoadingStateFactory
|
||||
|
||||
/**
|
||||
|
|
@ -26,6 +27,10 @@ internal class ReinitializeWalletTransformer(
|
|||
)
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return walletLoadingStateFactory.create(
|
||||
userWallet = userWallet,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNFTItemUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class RemoveNFTCollectionsTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -17,4 +18,13 @@ internal class RemoveNFTCollectionsTransformer(
|
|||
is WalletState.SingleCurrency.Locked,
|
||||
-> prevState
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return when (walletUM) {
|
||||
is WalletUM.Content -> walletUM.copy(
|
||||
nftState = WalletNFTItemUM.Hidden,
|
||||
)
|
||||
is WalletUM.Locked -> walletUM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import com.tangem.domain.tokens.model.TokenActionsState
|
|||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletManageButton
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import timber.log.Timber
|
||||
|
|
@ -35,6 +36,10 @@ internal class SetCryptoCurrencyActionsTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun TokenActionsState.toManageButtons(): PersistentList<WalletManageButton> {
|
||||
return states
|
||||
.filterIfS2C()
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.onramp.model.cache.OnrampTransaction
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.SingleWalletOnrampTransactionConverter
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import timber.log.Timber
|
||||
|
|
@ -56,6 +57,10 @@ internal class SetExpressStatusesTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun TangemBottomSheetConfig.updateStateWithExpressStatusBottomSheet(
|
||||
expressState: ExpressTransactionStateUM?,
|
||||
): TangemBottomSheetConfig {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.domain.nft.models.NFTCollections
|
|||
import com.tangem.domain.nft.models.allLoadedCollectionsEmpty
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNFTItemUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
internal class SetNFTCollectionsTransformer(
|
||||
|
|
@ -28,6 +29,19 @@ internal class SetNFTCollectionsTransformer(
|
|||
-> prevState
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return when (walletUM) {
|
||||
is WalletUM.Content -> walletUM.copy(
|
||||
nftState = when {
|
||||
nftCollections.allLoadedCollectionsEmpty() ->
|
||||
WalletNFTItemUM.Empty(onItemClick)
|
||||
else -> createContentNFTItemUM(onItemClick)
|
||||
},
|
||||
)
|
||||
is WalletUM.Locked -> walletUM
|
||||
}
|
||||
}
|
||||
|
||||
private fun createContentNFTItemUM(onItemClick: () -> Unit): WalletNFTItemUM.Content {
|
||||
val collectionsContent = nftCollections
|
||||
.map { it.content }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.SingleWalletCardStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.SingleWalletMarketPriceConverter
|
||||
import timber.log.Timber
|
||||
|
|
@ -35,6 +36,10 @@ internal class SetPrimaryCurrencyTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun WalletCardState.toLoadedSingleCurrencyState(): WalletCardState {
|
||||
return SingleWalletCardStateConverter(status.value, userWallet, appCurrency).convert(value = this)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletManageButton
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.mutate
|
||||
|
||||
|
|
@ -33,6 +34,10 @@ internal class SetRefreshStateTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun PullToRefreshConfig.toUpdatedState(isRefreshing: Boolean): PullToRefreshConfig {
|
||||
return copy(isRefreshing = isRefreshing)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@ import com.tangem.domain.card.common.util.getCardsCount
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.disableButtons
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -51,6 +49,20 @@ internal class SetTokenListErrorTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return when (walletUM) {
|
||||
is WalletUM.Content -> {
|
||||
walletUM.copy(
|
||||
tokensListUM = WalletTokensListUM.Empty,
|
||||
)
|
||||
}
|
||||
is WalletUM.Locked -> {
|
||||
Timber.w("Impossible to load tokens list for locked wallet")
|
||||
walletUM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun WalletCardState.toLoadedState(): WalletCardState {
|
||||
return WalletCardState.Content(
|
||||
id = id,
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@ import com.tangem.domain.models.currency.CryptoCurrency
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.staking.model.StakingAvailability
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.MultiWalletCardStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TokenListStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.WalletTokensListUMTransformer
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.enableButtons
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
|
|
@ -22,6 +21,7 @@ internal class SetTokenListTransformer(
|
|||
private val yieldSupplyApyMap: Map<String, BigDecimal> = emptyMap(),
|
||||
private val stakingAvailabilityMap: Map<CryptoCurrency, StakingAvailability> = emptyMap(),
|
||||
private val shouldShowMainPromo: Boolean,
|
||||
private val isAccountsModeEnabled: Boolean,
|
||||
) : WalletStateTransformer(userWallet.walletId) {
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
|
|
@ -45,6 +45,20 @@ internal class SetTokenListTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return when (walletUM) {
|
||||
is WalletUM.Content -> {
|
||||
walletUM.copy(
|
||||
tokensListUM = toLoadedState(),
|
||||
)
|
||||
}
|
||||
is WalletUM.Locked -> {
|
||||
Timber.w("Impossible to load tokens list for locked wallet")
|
||||
walletUM
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun WalletCardState.toLoadedState(): WalletCardState {
|
||||
val fiatBalance = when (params) {
|
||||
is TokenConverterParams.Account -> params.accountList.totalFiatBalance
|
||||
|
|
@ -68,4 +82,19 @@ internal class SetTokenListTransformer(
|
|||
shouldShowMainPromo = shouldShowMainPromo,
|
||||
).convert(value = this)
|
||||
}
|
||||
|
||||
private fun toLoadedState(): WalletTokensListUM {
|
||||
if (params !is TokenConverterParams.Account) return WalletTokensListUM.Empty
|
||||
|
||||
return WalletTokensListUMTransformer(
|
||||
selectedWallet = userWallet,
|
||||
appCurrency = appCurrency,
|
||||
clickIntents = clickIntents,
|
||||
yieldModuleApyMap = yieldSupplyApyMap,
|
||||
stakingAvailabilityMap = stakingAvailabilityMap,
|
||||
shouldShowMainPromo = shouldShowMainPromo,
|
||||
isAccountsModeEnabled = isAccountsModeEnabled,
|
||||
expandedAccounts = params.expandedAccounts,
|
||||
).convert(value = params.accountList)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import com.tangem.domain.models.wallet.UserWallet
|
|||
import com.tangem.domain.txhistory.models.TxHistoryStateError
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TxHistoryItemStateConverter
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import timber.log.Timber
|
||||
|
|
@ -35,6 +36,10 @@ internal class SetTxHistoryCountErrorTransformer(
|
|||
)
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
return when (prevState) {
|
||||
is WalletState.SingleCurrency.Content -> prevState.copy(txHistoryState = createErrorState())
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import timber.log.Timber
|
||||
|
|
@ -33,6 +34,10 @@ internal class SetTxHistoryCountTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun TxHistoryState.toLoadingState(): TxHistoryState {
|
||||
return if (this is TxHistoryState.Content) {
|
||||
Timber.d("Load transactions history: $transactionsCount")
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.txhistory.models.TxHistoryListError
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import timber.log.Timber
|
||||
|
||||
internal class SetTxHistoryItemsErrorTransformer(
|
||||
|
|
@ -27,6 +28,10 @@ internal class SetTxHistoryItemsErrorTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun createErrorState(): TxHistoryState.Error = when (error) {
|
||||
is TxHistoryListError.DataError -> {
|
||||
TxHistoryState.Error(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
|||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.TxHistoryItemFlowConverter
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import timber.log.Timber
|
||||
|
|
@ -32,6 +33,10 @@ internal class SetTxHistoryItemsTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun TxHistoryState.toContentState(): TxHistoryState {
|
||||
val converter = TxHistoryItemFlowConverter(
|
||||
currentState = this,
|
||||
|
|
|
|||
|
|
@ -2,13 +2,18 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificationUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import timber.log.Timber
|
||||
|
||||
internal class SetWarningsTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
private val warnings: ImmutableList<WalletNotification>,
|
||||
private val notifications: ImmutableList<WalletNotificationUM> = persistentListOf(),
|
||||
private val notificationsCarousel: ImmutableList<WalletNotificationUM> = persistentListOf(),
|
||||
) : WalletStateTransformer(userWalletId) {
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
|
|
@ -23,4 +28,17 @@ internal class SetWarningsTransformer(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return when (walletUM) {
|
||||
is WalletUM.Content -> walletUM.copy(
|
||||
notifications = notifications,
|
||||
notificationsCarousel = notificationsCarousel,
|
||||
)
|
||||
is WalletUM.Locked -> {
|
||||
Timber.w("Impossible to update notifications for locked wallet")
|
||||
walletUM
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class TangemPayExposedDeviceTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -14,4 +15,8 @@ internal class TangemPayExposedDeviceTransformer(
|
|||
prevState
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class TangemPayHiddenStateTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -15,4 +16,8 @@ internal class TangemPayHiddenStateTransformer(
|
|||
prevState
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class TangemPayHideOnboardingStateTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -15,4 +16,8 @@ internal class TangemPayHideOnboardingStateTransformer(
|
|||
prevState
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class TangemPayLoadingStateTransformer(userWalletId: UserWalletId) : WalletStateTransformer(userWalletId) {
|
||||
override fun transform(prevState: WalletState): WalletState {
|
||||
|
|
@ -12,4 +13,8 @@ internal class TangemPayLoadingStateTransformer(userWalletId: UserWalletId) : Wa
|
|||
prevState
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class TangemPayOnboardingBannerStateTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -22,4 +23,8 @@ internal class TangemPayOnboardingBannerStateTransformer(
|
|||
prevState
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import com.tangem.feature.wallet.impl.R
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification.Warning.TangemPayRefreshNeeded
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class TangemPayRefreshNeededStateTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -32,4 +33,8 @@ internal class TangemPayRefreshNeededStateTransformer(
|
|||
prevState
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class TangemPayRefreshShowProgressTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -21,4 +22,8 @@ internal class TangemPayRefreshShowProgressTransformer(
|
|||
),
|
||||
)
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
|
||||
internal class TangemPayUnavailableStateTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
@ -20,4 +21,8 @@ internal class TangemPayUnavailableStateTransformer(
|
|||
prevState
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import com.tangem.core.ui.extensions.TextReference
|
|||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.format.bigdecimal.fiat
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.models.kyc.KycStatus
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.pay.TangemPayDetailsConfig
|
||||
import com.tangem.domain.pay.model.CustomerInfo.CardInfo
|
||||
|
|
@ -16,8 +17,7 @@ import com.tangem.feature.wallet.child.wallet.model.intents.TangemPayIntents
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState.Progress
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.domain.pay.model.CustomerInfo.KycStatus.APPROVED
|
||||
import com.tangem.domain.pay.model.CustomerInfo
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import java.util.Currency
|
||||
|
||||
/**
|
||||
|
|
@ -42,6 +42,10 @@ internal class TangemPayUpdateInfoStateTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
|
||||
private fun createInitialState(): TangemPayState {
|
||||
val cardInfo = value.info.cardInfo
|
||||
val productInstance = value.info.productInstance
|
||||
|
|
@ -50,7 +54,7 @@ internal class TangemPayUpdateInfoStateTransformer(
|
|||
// when statement copied to WalletTangemPayAnalyticsEventSender. Be careful when editing.
|
||||
return when {
|
||||
value.orderStatus == OrderStatus.CANCELED -> createCancelledState(customerId)
|
||||
value.info.kycStatus != APPROVED && !value.info.customerId.isNullOrEmpty() ->
|
||||
value.info.kycStatus != KycStatus.APPROVED && !value.info.customerId.isNullOrEmpty() ->
|
||||
createKycInProgressState(kycStatus = value.info.kycStatus, customerId = customerId)
|
||||
cardInfo != null && productInstance != null ->
|
||||
getCardInfoState(customerId, cardInfo, productInstance)
|
||||
|
|
@ -74,7 +78,6 @@ internal class TangemPayUpdateInfoStateTransformer(
|
|||
cardId = productInstance.cardId,
|
||||
isPinSet = cardInfo.isPinSet,
|
||||
cardFrozenState = cardFrozenState,
|
||||
customerWalletAddress = cardInfo.customerWalletAddress,
|
||||
cardNumberEnd = cardInfo.lastFourDigits,
|
||||
chainId = POLYGON_CHAIN_ID,
|
||||
),
|
||||
|
|
@ -89,25 +92,24 @@ internal class TangemPayUpdateInfoStateTransformer(
|
|||
}
|
||||
}
|
||||
|
||||
private fun createKycInProgressState(kycStatus: CustomerInfo.KycStatus, customerId: String): TangemPayState =
|
||||
Progress(
|
||||
title = TextReference.Res(R.string.tangempay_payment_account),
|
||||
description = when (kycStatus) {
|
||||
CustomerInfo.KycStatus.REJECTED -> TextReference.Res(R.string.tangempay_kyc_has_failed)
|
||||
else -> TextReference.Res(R.string.tangempay_kyc_in_progress)
|
||||
},
|
||||
buttonText = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_button),
|
||||
iconRes = R.drawable.ic_promo_kyc_36,
|
||||
onButtonClick = {
|
||||
when (kycStatus) {
|
||||
CustomerInfo.KycStatus.REJECTED -> tangemPayClickIntents.onKycRejectedClicked(
|
||||
userWalletId = userWalletId,
|
||||
customerId = customerId,
|
||||
)
|
||||
else -> tangemPayClickIntents.onKycProgressClicked(userWalletId)
|
||||
}
|
||||
},
|
||||
)
|
||||
private fun createKycInProgressState(kycStatus: KycStatus, customerId: String): TangemPayState = Progress(
|
||||
title = TextReference.Res(R.string.tangempay_payment_account),
|
||||
description = when (kycStatus) {
|
||||
KycStatus.REJECTED -> TextReference.Res(R.string.tangempay_kyc_has_failed)
|
||||
else -> TextReference.Res(R.string.tangempay_kyc_in_progress)
|
||||
},
|
||||
buttonText = TextReference.Res(R.string.tangempay_kyc_in_progress_notification_button),
|
||||
iconRes = R.drawable.ic_promo_kyc_36,
|
||||
onButtonClick = {
|
||||
when (kycStatus) {
|
||||
KycStatus.REJECTED -> tangemPayClickIntents.onKycRejectedClicked(
|
||||
userWalletId = userWalletId,
|
||||
customerId = customerId,
|
||||
)
|
||||
else -> tangemPayClickIntents.onKycProgressClicked(userWalletId)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
private fun createIssueProgressState(): TangemPayState = Progress(
|
||||
title = TextReference.Res(R.string.tangempay_payment_account),
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
||||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
internal abstract class TypedWalletStateTransformer<S : WalletState>(
|
||||
userWalletId: UserWalletId,
|
||||
protected val targetStateClass: KClass<S>,
|
||||
) : WalletStateTransformer(userWalletId) {
|
||||
|
||||
abstract fun transformTyped(prevState: S): WalletState
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
final override fun transform(prevState: WalletState): WalletState {
|
||||
return if (prevState::class == targetStateClass) {
|
||||
transformTyped(prevState as S)
|
||||
} else {
|
||||
prevState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
|||
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.utils.showSwapBadge
|
||||
|
||||
internal class UpdateMultiWalletActionButtonBadgeTransformer(
|
||||
|
|
@ -16,4 +17,8 @@ internal class UpdateMultiWalletActionButtonBadgeTransformer(
|
|||
else -> prevState
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(walletUM: WalletUM): WalletUM {
|
||||
return walletUM // todo redesign main
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue