diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCase.kt index 2094f6fdfb..e57b268e68 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCase.kt @@ -9,7 +9,6 @@ import arrow.core.toNonEmptyListOrNull import arrow.core.toNonEmptySetOrNull import com.tangem.domain.tokens.error.TokenListSortingError import com.tangem.domain.tokens.models.CryptoCurrency -import com.tangem.domain.tokens.models.Network import com.tangem.domain.tokens.repository.CurrenciesRepository import com.tangem.domain.wallets.models.UserWalletId import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -23,7 +22,7 @@ class ApplyTokenListSortingUseCase( suspend operator fun invoke( userWalletId: UserWalletId, - sortedTokensIds: List>, + sortedTokensIds: List, isGroupedByNetwork: Boolean, isSortedByBalance: Boolean, ): Either { @@ -40,7 +39,7 @@ class ApplyTokenListSortingUseCase( } private suspend fun Raise.sortTokens( - sortedTokensIds: List>, + sortedTokensIds: List, unsortedTokens: List, ): List = withContext(dispatchers.default) { val nonEmptySortedTokensIds = ensureNotNull(sortedTokensIds.toNonEmptySetOrNull()) { @@ -49,13 +48,13 @@ class ApplyTokenListSortingUseCase( val sortedTokens = sortedMapOf() - unsortedTokens.distinct().forEach { token -> - val index = nonEmptySortedTokensIds.indexOfFirst { (networkId, tokenId) -> - networkId == token.networkId && tokenId == token.id + unsortedTokens.distinct().forEach { currency -> + val index = nonEmptySortedTokensIds.indexOfFirst { currencyId -> + currencyId == currency.id } if (index >= 0) { - sortedTokens[index] = token + sortedTokens[index] = currency } else { raise(TokenListSortingError.UnableToSortTokenList) } diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCaseTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCaseTest.kt index 77d37c2c2b..d5f180d4be 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCaseTest.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ApplyTokenListSortingUseCaseTest.kt @@ -54,7 +54,7 @@ internal class ApplyTokenListSortingUseCaseTest { // When val result = useCase( userWalletId = userWalletId, - sortedTokensIds = MockTokens.tokens.map { it.networkId to it.id }, + sortedTokensIds = MockTokens.tokens.map { it.id }, isGroupedByNetwork = false, isSortedByBalance = false, ) @@ -76,7 +76,7 @@ internal class ApplyTokenListSortingUseCaseTest { // When useCase( userWalletId = userWalletId, - sortedTokensIds = expectedTokens.map { it.networkId to it.id }, + sortedTokensIds = expectedTokens.map { it.id }, isGroupedByNetwork = expectedIsGrouped, isSortedByBalance = expectedIsSorted, ) @@ -100,7 +100,7 @@ internal class ApplyTokenListSortingUseCaseTest { // When useCase( userWalletId = userWalletId, - sortedTokensIds = expectedTokens.map { it.networkId to it.id }, + sortedTokensIds = expectedTokens.map { it.id }, isGroupedByNetwork = expectedIsGrouped, isSortedByBalance = expectedIsSorted, ) @@ -124,7 +124,7 @@ internal class ApplyTokenListSortingUseCaseTest { // When useCase( userWalletId = userWalletId, - sortedTokensIds = expectedTokens.map { it.networkId to it.id }, + sortedTokensIds = expectedTokens.map { it.id }, isGroupedByNetwork = expectedIsGrouped, isSortedByBalance = expectedIsSorted, ) @@ -148,7 +148,7 @@ internal class ApplyTokenListSortingUseCaseTest { // When useCase( userWalletId = userWalletId, - sortedTokensIds = expectedTokens.map { it.networkId to it.id }, + sortedTokensIds = expectedTokens.map { it.id }, isGroupedByNetwork = expectedIsGrouped, isSortedByBalance = expectedIsSorted, ) @@ -170,7 +170,7 @@ internal class ApplyTokenListSortingUseCaseTest { // When val result = useCase( userWalletId = userWalletId, - sortedTokensIds = getSortedTokens().drop(n = 3).map { it.networkId to it.id }, + sortedTokensIds = getSortedTokens().drop(n = 3).map { it.id }, isGroupedByNetwork = false, isSortedByBalance = false, ) diff --git a/features/wallet/impl/build.gradle.kts b/features/wallet/impl/build.gradle.kts index cc22ff78e4..48a2eca7c6 100644 --- a/features/wallet/impl/build.gradle.kts +++ b/features/wallet/impl/build.gradle.kts @@ -9,6 +9,7 @@ plugins { dependencies { /** AndroidX */ implementation(deps.androidx.activity.compose) + implementation(deps.lifecycle.compose) implementation(deps.material) /** Compose */ diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensIntents.kt index 250b29d900..84ce246245 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensIntents.kt @@ -1,8 +1,5 @@ package com.tangem.feature.wallet.presentation.organizetokens -import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem -import org.burnoutcrew.reorderable.ItemPosition - internal interface OrganizeTokensIntents { fun onBackClick() @@ -14,12 +11,4 @@ internal interface OrganizeTokensIntents { fun onApplyClick() fun onCancelClick() - - fun onItemDragged(from: ItemPosition, to: ItemPosition) - - fun canDragItemOver(dragOver: ItemPosition, dragging: ItemPosition): Boolean - - fun onItemDraggingStart(item: DraggableItem) - - fun onItemDraggingEnd() } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt index ce0aabb8b1..53616f4e93 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt @@ -1,5 +1,6 @@ package com.tangem.feature.wallet.presentation.organizetokens +import androidx.activity.compose.BackHandler import androidx.compose.animation.core.* import androidx.compose.foundation.background import androidx.compose.foundation.layout.* @@ -38,6 +39,8 @@ import org.burnoutcrew.reorderable.* @Composable internal fun OrganizeTokensScreen(state: OrganizeTokensState, modifier: Modifier = Modifier) { + BackHandler(onBack = state.onBackClick) + val tokensListState = rememberLazyListState() Scaffold( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensStateHolder.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensStateHolder.kt index 33161ae553..14fecec78d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensStateHolder.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensStateHolder.kt @@ -1,12 +1,12 @@ package com.tangem.feature.wallet.presentation.organizetokens import com.tangem.common.Provider +import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.tokens.error.TokenListSortingError import com.tangem.domain.tokens.model.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.common.updateSorting 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.error.TokenListErrorConverter @@ -17,22 +17,17 @@ import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.ite import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* -@Suppress("unused", "MemberVisibilityCanBePrivate") // TODO: Will be used in next MR internal class OrganizeTokensStateHolder( private val intents: OrganizeTokensIntents, - private val fiatCurrencyCode: String, - private val fiatCurrencySymbol: String, + private val appCurrencyProvider: Provider, private val onSubscription: () -> Unit, - scope: CoroutineScope, + stateFlowScope: CoroutineScope, ) { private val stateFlowInternal: MutableStateFlow = MutableStateFlow(getInitialState()) private val tokenListConverter by lazy { - val tokensConverter = CryptoCurrencyToDraggableItemConverter( - fiatCurrencyCode = fiatCurrencyCode, - fiatCurrencySymbol = fiatCurrencySymbol, - ) + val tokensConverter = CryptoCurrencyToDraggableItemConverter(appCurrencyProvider) val itemsConverter = TokenListToListStateConverter( tokensConverter = tokensConverter, groupsConverter = NetworkGroupToDraggableItemsConverter(tokensConverter), @@ -56,17 +51,13 @@ internal class OrganizeTokensStateHolder( val stateFlow: StateFlow = stateFlowInternal .onSubscription { onSubscription() } .stateIn( - scope = scope, + scope = stateFlowScope, started = SharingStarted.WhileSubscribed(), initialValue = getInitialState(), ) - var tokenList: TokenList? = null - private set - fun updateStateWithTokenList(tokenList: TokenList) { updateState { tokenListConverter.convert(tokenList) } - this.tokenList = tokenList } fun updateStateToDisplayProgress() { @@ -77,16 +68,6 @@ internal class OrganizeTokensStateHolder( updateState { inProgressStateConverter.convertBack(value = this) } } - fun updateStateWithManualSorting(itemsState: OrganizeTokensListState) { - updateState { - copy( - header = header.copy(isSortedByBalance = false), - itemsState = itemsState, - ) - } - tokenList = tokenList?.updateSorting(isSortedByBalance = false) - } - fun updateStateWithError(error: TokenListError) { updateState { tokenListErrorConverter.convert(error) } } @@ -107,11 +88,12 @@ internal class OrganizeTokensStateHolder( onApplyClick = intents::onApplyClick, onCancelClick = intents::onCancelClick, ), + // TODO: Will be added in next MR dndConfig = OrganizeTokensState.DragAndDropConfig( - onItemDragged = intents::onItemDragged, - onDragStart = intents::onItemDraggingStart, - onItemDragEnd = intents::onItemDraggingEnd, - canDragItemOver = intents::canDragItemOver, + onItemDragged = { _, _ -> }, + onDragStart = { }, + onItemDragEnd = { }, + canDragItemOver = { _, _ -> false }, ), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensViewModel.kt index b3fa65555b..0313bf1e7a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensViewModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensViewModel.kt @@ -1,133 +1,147 @@ package com.tangem.feature.wallet.presentation.organizetokens -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import arrow.core.getOrElse +import com.tangem.common.Provider +import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase +import com.tangem.domain.appcurrency.model.AppCurrency +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.model.TokenList import com.tangem.domain.wallets.models.UserWalletId -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.OrganizeTokensState -import com.tangem.feature.wallet.presentation.organizetokens.utils.common.* +import com.tangem.feature.wallet.presentation.organizetokens.utils.CryptoCurrenciesIdsResolver import com.tangem.feature.wallet.presentation.router.InnerWalletRouter import com.tangem.feature.wallet.presentation.router.WalletRoute import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch -import org.burnoutcrew.reorderable.ItemPosition +import kotlinx.coroutines.withContext import javax.inject.Inject -import kotlin.properties.Delegates -// FIXME: Implemented with preview data @HiltViewModel -internal class OrganizeTokensViewModel @Inject constructor(savedStateHandle: SavedStateHandle) : ViewModel() { +internal class OrganizeTokensViewModel @Inject constructor( + private val getTokenListUseCase: GetTokenListUseCase, + private val toggleTokenListGroupingUseCase: ToggleTokenListGroupingUseCase, + private val toggleTokenListSortingUseCase: ToggleTokenListSortingUseCase, + private val applyTokenListSortingUseCase: ApplyTokenListSortingUseCase, + private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase, + savedStateHandle: SavedStateHandle, +) : ViewModel(), OrganizeTokensIntents { - @Volatile - private var movingItem: DraggableItem? = null + lateinit var router: InnerWalletRouter - var router: InnerWalletRouter by Delegates.notNull() - val userWalletId: UserWalletId by lazy { + private val selectedAppCurrencyFlow = createSelectedAppCurrencyFlow() + + private val stateHolder = OrganizeTokensStateHolder( + stateFlowScope = viewModelScope, + intents = this, + appCurrencyProvider = Provider(selectedAppCurrencyFlow::value), + onSubscription = { + bootstrapTokenList() + }, + ) + + private val userWalletId: UserWalletId by lazy { val userWalletIdValue: String = checkNotNull(savedStateHandle[WalletRoute.userWalletIdKey]) UserWalletId(userWalletIdValue) } - var uiState: OrganizeTokensState by mutableStateOf(getInitialState()) - private set + private var tokenList: TokenList? = null - private fun getInitialState(): OrganizeTokensState = WalletPreviewData.organizeTokensState.copy( - itemsState = OrganizeTokensListState.Ungrouped( - items = WalletPreviewData.draggableTokens, - ), - dndConfig = OrganizeTokensState.DragAndDropConfig( - onItemDragged = this::moveItem, - canDragItemOver = this::checkCanMoveItemOver, - onItemDragEnd = this::endMoving, - onDragStart = this::startMoving, - ), - header = OrganizeTokensState.HeaderConfig( - onSortClick = { /* no-op */ }, - onGroupClick = this::toggleTokensByNetworkGrouping, - ), - ) + val uiState: StateFlow = stateHolder.stateFlow - private fun toggleTokensByNetworkGrouping() { - val newListState = when (val itemsState = uiState.itemsState) { - is OrganizeTokensListState.GroupedByNetwork -> OrganizeTokensListState.Ungrouped( - items = itemsState.items.filterIsInstance().toPersistentList(), + override fun onBackClick() { + router.popBackStack() + } + + override fun onSortClick() { + viewModelScope.launch(Dispatchers.Default) { + val list = tokenList ?: return@launch + + toggleTokenListSortingUseCase(list).fold( + ifLeft = stateHolder::updateStateWithError, + ifRight = { + stateHolder.updateStateWithTokenList(it) + tokenList = it + }, ) - is OrganizeTokensListState.Ungrouped -> OrganizeTokensListState.GroupedByNetwork( - items = WalletPreviewData.draggableItems, + } + } + + override fun onGroupClick() { + viewModelScope.launch(Dispatchers.Default) { + val list = tokenList ?: return@launch + + toggleTokenListGroupingUseCase(list).fold( + ifLeft = stateHolder::updateStateWithError, + ifRight = { + stateHolder.updateStateWithTokenList(it) + tokenList = it + }, ) - is OrganizeTokensListState.Empty -> itemsState - } - - uiState = uiState.copy(itemsState = newListState) - } - - private fun checkCanMoveItemOver(moveOverItemPosition: ItemPosition, movedItemPosition: ItemPosition): Boolean { - val items = (uiState.itemsState as? OrganizeTokensListState.GroupedByNetwork) - ?.items - ?: return true // If ungrouped then item can be moved anywhere - - val (moveOverItem, movedItem) = items.findItemsToMove(moveOverItemPosition.key, movedItemPosition.key) - - if (moveOverItem == null || movedItem == null) { - return false - } - - return when (movedItem) { - is DraggableItem.GroupHeader -> checkCanMoveHeaderOver(moveOverItemPosition, moveOverItem, items.lastIndex) - is DraggableItem.Token -> checkCanMoveTokenOver(movedItem, moveOverItem) - is DraggableItem.GroupPlaceholder -> false } } - private fun startMoving(movingItem: DraggableItem) = viewModelScope.launch(Dispatchers.Default) { - if (this@OrganizeTokensViewModel.movingItem != null) return@launch - this@OrganizeTokensViewModel.movingItem = movingItem + override fun onApplyClick() { + viewModelScope.launch(Dispatchers.Default) { + stateHolder.updateStateToDisplayProgress() - val updatedItemsState = uiState.itemsState.updateItems { items -> - when (movingItem) { - is DraggableItem.GroupHeader -> items.collapseGroup(movingItem) - is DraggableItem.Token -> when (uiState.itemsState) { - is OrganizeTokensListState.GroupedByNetwork -> items.divideGroups(movingItem) - is OrganizeTokensListState.Ungrouped -> items.divideItems(movingItem) - is OrganizeTokensListState.Empty -> uiState.itemsState.items - } - is DraggableItem.GroupPlaceholder -> items + val listState = uiState.value.itemsState + val resolver = CryptoCurrenciesIdsResolver() + + val result = applyTokenListSortingUseCase( + userWalletId = userWalletId, + sortedTokensIds = resolver.resolve(listState, tokenList), + isGroupedByNetwork = listState is OrganizeTokensListState.GroupedByNetwork, + isSortedByBalance = uiState.value.header.isSortedByBalance, + ) + + result.fold( + ifLeft = stateHolder::updateStateWithError, + ifRight = { + stateHolder.updateStateToHideProgress() + withContext(Dispatchers.Main) { router.popBackStack() } + }, + ) + } + } + + override fun onCancelClick() { + router.popBackStack() + } + + private fun bootstrapTokenList() { + viewModelScope.launch(Dispatchers.Default) { + val maybeTokenList = getTokenListUseCase(userWalletId) + .first { it.getOrNull()?.totalFiatBalance is TokenList.FiatBalance.Loaded } + + maybeTokenList.fold( + ifLeft = stateHolder::updateStateWithError, + ifRight = { + stateHolder.updateStateWithTokenList(it) + tokenList = it + }, + ) + } + } + + private fun createSelectedAppCurrencyFlow(): StateFlow { + return getSelectedAppCurrencyUseCase() + .map { maybeAppCurrency -> + maybeAppCurrency.getOrElse { AppCurrency.Default } } - } - - uiState = uiState.copy(itemsState = updatedItemsState) - } - - private fun endMoving() = viewModelScope.launch(Dispatchers.Default) { - if (movingItem == null) return@launch - - val updatedItemsState = uiState.itemsState.updateItems { items -> - when (movingItem) { - is DraggableItem.GroupHeader -> items.expandGroups() - is DraggableItem.Token -> items.uniteItems() - is DraggableItem.GroupPlaceholder, - null, - -> items - } - } - - uiState = uiState.copy(itemsState = updatedItemsState) - movingItem = null - } - - private fun moveItem(from: ItemPosition, to: ItemPosition) = viewModelScope.launch(Dispatchers.Default) { - uiState = uiState.copy( - itemsState = uiState.itemsState.updateItems { - it.moveItem(from.index, to.index) - }, - ) + .stateIn( + scope = viewModelScope, + started = SharingStarted.Eagerly, + initialValue = AppCurrency.Default, + ) } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/CryptoCurrenciesIdsResolver.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/CryptoCurrenciesIdsResolver.kt new file mode 100644 index 0000000000..71690752fb --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/CryptoCurrenciesIdsResolver.kt @@ -0,0 +1,32 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils + +import com.tangem.domain.tokens.model.TokenList +import com.tangem.domain.tokens.models.CryptoCurrency +import com.tangem.feature.wallet.presentation.organizetokens.model.DraggableItem +import com.tangem.feature.wallet.presentation.organizetokens.model.OrganizeTokensListState + +internal class CryptoCurrenciesIdsResolver { + + fun resolve(listState: OrganizeTokensListState, tokenList: TokenList?): List { + val draggableTokens = when (listState) { + is OrganizeTokensListState.Empty -> return emptyList() + is OrganizeTokensListState.GroupedByNetwork -> listState.items.filterIsInstance() + is OrganizeTokensListState.Ungrouped -> listState.items + } + val currenciesStatuses = when (tokenList) { + is TokenList.GroupedByNetwork -> tokenList.groups.flatMap { it.currencies } + is TokenList.Ungrouped -> tokenList.currencies + is TokenList.NotInitialized, + null, + -> return emptyList() + } + + return draggableTokens.mapNotNull { draggableToken -> + val currencyStatus = currenciesStatuses.firstOrNull { + it.currency.id.value == draggableToken.id + } + + currencyStatus?.currency?.id + } + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt index d92843a1f6..5284855142 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt @@ -1,7 +1,9 @@ package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items import androidx.annotation.DrawableRes +import com.tangem.common.Provider import com.tangem.core.ui.utils.BigDecimalFormatter +import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.models.CryptoCurrency import com.tangem.feature.wallet.impl.R @@ -12,8 +14,7 @@ import com.tangem.feature.wallet.presentation.organizetokens.utils.common.getTok import com.tangem.utils.converter.Converter internal class CryptoCurrencyToDraggableItemConverter( - private val fiatCurrencyCode: String, - private val fiatCurrencySymbol: String, + private val appCurrencyProvider: Provider, ) : Converter { private val CryptoCurrency.networkIconResId: Int? @@ -29,13 +30,29 @@ internal class CryptoCurrencyToDraggableItemConverter( } override fun convert(value: CryptoCurrencyStatus): DraggableItem.Token { + return createDraggableToken(value, appCurrencyProvider()) + } + + override fun convertList(input: Collection): List { + val appCurrency = appCurrencyProvider() + + return input.map { createDraggableToken(it, appCurrency) } + } + + private fun createDraggableToken( + currencyStatus: CryptoCurrencyStatus, + appCurrency: AppCurrency, + ): DraggableItem.Token { return DraggableItem.Token( - tokenItemState = createToTokenItemState(value), - groupId = getGroupHeaderId(value.currency.networkId), + tokenItemState = createTokenItemState(currencyStatus, appCurrency), + groupId = getGroupHeaderId(currencyStatus.currency.networkId), ) } - private fun createToTokenItemState(currencyStatus: CryptoCurrencyStatus): TokenItemState.Draggable { + private fun createTokenItemState( + currencyStatus: CryptoCurrencyStatus, + appCurrency: AppCurrency, + ): TokenItemState.Draggable { val currency = currencyStatus.currency return TokenItemState.Draggable( @@ -44,13 +61,13 @@ internal class CryptoCurrencyToDraggableItemConverter( tokenIconResId = currency.tokenIconResId, networkIconResId = currency.networkIconResId, name = currency.name, - fiatAmount = getFormattedFiatAmount(currencyStatus), + fiatAmount = getFormattedFiatAmount(currencyStatus, appCurrency), ) } - private fun getFormattedFiatAmount(currency: CryptoCurrencyStatus): String { + private fun getFormattedFiatAmount(currency: CryptoCurrencyStatus, appCurrency: AppCurrency): String { val fiatAmount = currency.value.fiatAmount ?: return BigDecimalFormatter.EMPTY_BALANCE_SIGN - return BigDecimalFormatter.formatFiatAmount(fiatAmount, fiatCurrencyCode, fiatCurrencySymbol) + return BigDecimalFormatter.formatFiatAmount(fiatAmount, appCurrency.code, appCurrency.symbol) } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt index aa8edc6a9c..84ca2ae72b 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt @@ -1,13 +1,15 @@ package com.tangem.feature.wallet.presentation.router -import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavHostController import androidx.navigation.NavType import androidx.navigation.compose.NavHost @@ -59,9 +61,11 @@ internal class DefaultWalletRouter(private val navigationStateHolder: Navigation router = this@DefaultWalletRouter } + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + OrganizeTokensScreen( - modifier = Modifier.systemBarsPadding(), - state = viewModel.uiState, + modifier = Modifier.statusBarsPadding(), + state = uiState, ) } } diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 1058197b94..ffcb1326b2 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -132,6 +132,7 @@ androidx-paging-runtime = { module = "androidx.paging:paging-runtime", version.r lifecycle-common-java8 = { module = "androidx.lifecycle:lifecycle-common-java8", version.ref = "androidxLifecycle" } lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidxLifecycle" } lifecycle-viewModel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidxLifecycle" } +lifecycle-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidxLifecycle" } # region AndroidX # region Compose