From 36b4671a05d085a923be91b4a2a4a828437d68d5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 28 Jul 2023 10:50:24 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../presentation/common/WalletPreviewData.kt | 10 +- .../organizetokens/OrganizeTokensIntents.kt | 24 ++ .../organizetokens/OrganizeTokensScreen.kt | 20 +- .../organizetokens/OrganizeTokensState.kt | 155 +++++++++++ .../OrganizeTokensStateHolder.kt | 253 +++++++----------- .../organizetokens/OrganizeTokensViewModel.kt | 18 +- .../utils/common/DraggableItemOperations.kt | 34 +++ .../{ => common}/DraggableItemsOperations.kt | 48 ++-- .../utils/common/IdsOperations.kt | 8 + .../OrganiseTokensListStateOperations.kt | 19 ++ .../utils/common/TokenListOperations.kt | 14 + .../converter/InProgressStateConverter.kt | 23 ++ .../converter/TokenListToStateConverter.kt | 31 +++ .../error/TokenListErrorConverter.kt | 18 ++ .../error/TokenListSortingErrorConverter.kt | 18 ++ .../CryptoCurrencyToDraggableItemConverter.kt | 56 ++++ .../NetworkGroupToDraggableItemsConverter.kt | 41 +++ .../items/TokenListToListStateConverter.kt | 42 +++ 18 files changed, 629 insertions(+), 203 deletions(-) create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensIntents.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensState.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemOperations.kt rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/{ => common}/DraggableItemsOperations.kt (78%) create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/IdsOperations.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/OrganiseTokensListStateOperations.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/TokenListOperations.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/InProgressStateConverter.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenListToStateConverter.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/error/TokenListErrorConverter.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/error/TokenListSortingErrorConverter.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/NetworkGroupToDraggableItemsConverter.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/TokenListToListStateConverter.kt diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt index 56a3cec48c..bb2f454948 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/WalletPreviewData.kt @@ -11,7 +11,7 @@ import com.tangem.feature.wallet.presentation.common.state.TokenItemState import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TokenOptionsState import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensListState -import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensStateHolder +import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensState import com.tangem.feature.wallet.presentation.wallet.state.* import com.tangem.feature.wallet.presentation.wallet.state.components.* import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState.TokensListItemState @@ -205,21 +205,21 @@ internal object WalletPreviewData { } val groupedOrganizeTokensState by lazy { - OrganizeTokensStateHolder( + OrganizeTokensState( itemsState = OrganizeTokensListState.GroupedByNetwork( items = draggableItems, ), - header = OrganizeTokensStateHolder.HeaderConfig( + header = OrganizeTokensState.HeaderConfig( onSortByBalanceClick = {}, onGroupByNetworkClick = {}, ), - dragConfig = OrganizeTokensStateHolder.DragConfig( + dndConfig = OrganizeTokensState.DragAndDropConfig( onItemDragged = { _, _ -> }, onDragStart = {}, canDragItemOver = { _, _ -> false }, onItemDragEnd = {}, ), - actions = OrganizeTokensStateHolder.ActionsConfig( + actions = OrganizeTokensState.ActionsConfig( onApplyClick = {}, onCancelClick = {}, ), 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 new file mode 100644 index 0000000000..14891fef93 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensIntents.kt @@ -0,0 +1,24 @@ +package com.tangem.feature.wallet.presentation.organizetokens + +import org.burnoutcrew.reorderable.ItemPosition + +internal interface OrganizeTokensIntents { + + fun onBackClick() + + fun onSortClick() + + fun onGroupClick() + + 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 87f1b076b2..381920e1ae 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 @@ -34,7 +34,7 @@ import com.tangem.feature.wallet.presentation.common.component.DraggableTokenIte import org.burnoutcrew.reorderable.* @Composable -internal fun OrganizeTokensScreen(state: OrganizeTokensStateHolder, modifier: Modifier = Modifier) { +internal fun OrganizeTokensScreen(state: OrganizeTokensState, modifier: Modifier = Modifier) { val tokensListState = rememberLazyListState() Scaffold( @@ -47,7 +47,7 @@ internal fun OrganizeTokensScreen(state: OrganizeTokensStateHolder, modifier: Mo modifier = Modifier.padding(paddingValues), listState = tokensListState, state = state.itemsState, - dragConfig = state.dragConfig, + dragConfig = state.dndConfig, ) }, floatingActionButtonPosition = FabPosition.Center, @@ -62,7 +62,7 @@ internal fun OrganizeTokensScreen(state: OrganizeTokensStateHolder, modifier: Mo private fun TokenList( listState: LazyListState, state: OrganizeTokensListState, - dragConfig: OrganizeTokensStateHolder.DragConfig, + dragConfig: OrganizeTokensState.DragAndDropConfig, modifier: Modifier = Modifier, ) { Box(modifier = modifier) { @@ -166,7 +166,7 @@ private fun BottomGradient(modifier: Modifier = Modifier) { @Composable private fun TopBar( - config: OrganizeTokensStateHolder.HeaderConfig, + config: OrganizeTokensState.HeaderConfig, tokensListState: LazyListState, modifier: Modifier = Modifier, ) { @@ -211,7 +211,7 @@ private fun TopBar( config = ActionButtonConfig( text = TextReference.Res(id = R.string.organize_tokens_sort_by_balance), iconResId = R.drawable.ic_sort_24, - onClick = config.onSortByBalanceClick, + onClick = config.onSortClick, ), modifier = Modifier.weight(1f), color = TangemTheme.colors.background.primary, @@ -220,7 +220,7 @@ private fun TopBar( config = ActionButtonConfig( text = TextReference.Res(id = R.string.organize_tokens_group), iconResId = R.drawable.ic_group_24, - onClick = config.onGroupByNetworkClick, + onClick = config.onGroupClick, ), modifier = Modifier.weight(1f), color = TangemTheme.colors.background.primary, @@ -230,7 +230,7 @@ private fun TopBar( } @Composable -private fun Actions(config: OrganizeTokensStateHolder.ActionsConfig, modifier: Modifier = Modifier) { +private fun Actions(config: OrganizeTokensState.ActionsConfig, modifier: Modifier = Modifier) { Row( modifier = modifier .padding(horizontal = TangemTheme.dimens.spacing16) @@ -308,7 +308,7 @@ private fun Modifier.applyShapeAndShadow(roundingMode: DraggableItem.RoundingMod @Preview(showBackground = true, widthDp = 360) @Composable private fun OrganizeTokensScreenPreview_Light( - @PreviewParameter(OrganizeTokensStateProvider::class) state: OrganizeTokensStateHolder, + @PreviewParameter(OrganizeTokensStateProvider::class) state: OrganizeTokensState, ) { TangemTheme { OrganizeTokensScreen(state) @@ -318,14 +318,14 @@ private fun OrganizeTokensScreenPreview_Light( @Preview(showBackground = true, widthDp = 360) @Composable private fun OrganizeTokensScreenPreview_Dark( - @PreviewParameter(OrganizeTokensStateProvider::class) state: OrganizeTokensStateHolder, + @PreviewParameter(OrganizeTokensStateProvider::class) state: OrganizeTokensState, ) { TangemTheme(isDark = true) { OrganizeTokensScreen(state) } } -private class OrganizeTokensStateProvider : CollectionPreviewParameterProvider( +private class OrganizeTokensStateProvider : CollectionPreviewParameterProvider( collection = listOf( WalletPreviewData.organizeTokensState, WalletPreviewData.groupedOrganizeTokensState, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensState.kt new file mode 100644 index 0000000000..872529e9b9 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensState.kt @@ -0,0 +1,155 @@ +package com.tangem.feature.wallet.presentation.organizetokens + +import androidx.compose.runtime.Immutable +import com.tangem.feature.wallet.presentation.common.state.TokenItemState +import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem.RoundingMode +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf +import org.burnoutcrew.reorderable.ItemPosition + +@Immutable +internal data class OrganizeTokensState( + val onBackClick: () -> Unit, + val itemsState: OrganizeTokensListState, + val header: HeaderConfig, + val actions: ActionsConfig, + val dndConfig: DragAndDropConfig, +) { + + data class HeaderConfig( + val isEnabled: Boolean = false, + val isSortedByBalance: Boolean = false, + val isGrouped: Boolean = false, + val onSortClick: () -> Unit, + val onGroupClick: () -> Unit, + ) + + data class ActionsConfig( + val canApply: Boolean = false, + val showApplyProgress: Boolean = false, + val onApplyClick: () -> Unit, + val onCancelClick: () -> Unit, + ) + + data class DragAndDropConfig( + val onItemDragged: (ItemPosition, ItemPosition) -> Unit, + val canDragItemOver: (ItemPosition, ItemPosition) -> Boolean, + val onItemDragEnd: () -> Unit, + val onDragStart: (DraggableItem) -> Unit, + ) +} + +@Immutable +internal sealed class OrganizeTokensListState { + abstract val items: PersistentList + + data class GroupedByNetwork( + override val items: PersistentList, + ) : OrganizeTokensListState() + + data class Ungrouped( + override val items: PersistentList, + ) : OrganizeTokensListState() + + object Empty : OrganizeTokensListState() { + override val items: PersistentList = persistentListOf() + } +} + +/** + * Helper class for the DND list items + * + * @property id ID of the item + * @property roundingMode item [RoundingMode] + * @property showShadow if true then item should be elevated + * */ +@Immutable +internal sealed class DraggableItem { + abstract val id: String + abstract val roundingMode: RoundingMode + abstract val showShadow: Boolean + + /** + * Item for network group header. + * + * @property id ID of the network group + * @property networkName network group name + * @property roundingMode item [RoundingMode] + * @property showShadow if true then item should be elevated + * */ + data class GroupHeader( + override val id: String, + val networkName: String, + override val roundingMode: RoundingMode = RoundingMode.None, + override val showShadow: Boolean = false, + ) : DraggableItem() + + /** + * Item for token. + * + * @property tokenItemState state of the token item + * @property groupId ID of the network group which contains this token + * @property id ID of the token + * @property roundingMode item [RoundingMode] + * @property showShadow if true then item should be elevated + * */ + data class Token( + val tokenItemState: TokenItemState.Draggable, + val groupId: String, + override val showShadow: Boolean = false, + override val roundingMode: RoundingMode = RoundingMode.None, + ) : DraggableItem() { + override val id: String = tokenItemState.id + } + + /** + * Helper item used to detect possible positions where a network group can be placed. + * Used only on [OrganizeTokensListState.GroupedByNetwork] and placed between network groups. + * + * @property id ID of the placeholder + * */ + data class GroupPlaceholder( + override val id: String, + ) : DraggableItem() { + override val showShadow: Boolean = false + override val roundingMode: RoundingMode = RoundingMode.None + } + + /** + * Rounding mode of the [DraggableItem] + * + * @property showGap if true then item should have padding on rounded side + * */ + @Immutable + sealed class RoundingMode { + abstract val showGap: Boolean + + /** + * In this mode, item is not rounded + * */ + object None : RoundingMode() { + override val showGap: Boolean = false + } + + /** + * In this mode, item should have a rounded top side + * + * @property showGap if true then item should have top padding + * */ + data class Top(override val showGap: Boolean = false) : RoundingMode() + + /** + * In this mode, item should have a rounded bottom side + * + * @property showGap if true then item should have bottom padding + * */ + data class Bottom(override val showGap: Boolean = false) : RoundingMode() + + /** + * In this mode, item should have a rounded all sides + * + * @property showGap if true then item should have top and bottom padding + * */ + data class All(override val showGap: Boolean = false) : RoundingMode() + } +} \ No newline at end of file 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 4da6dcb29c..6a997d5eab 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,179 +1,120 @@ package com.tangem.feature.wallet.presentation.organizetokens -import androidx.compose.runtime.Immutable -import com.tangem.feature.wallet.presentation.common.state.TokenItemState -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.toPersistentList -import org.burnoutcrew.reorderable.ItemPosition +import com.tangem.common.Provider +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.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 +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 kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.* -internal data class OrganizeTokensStateHolder( - val header: HeaderConfig, - val itemsState: OrganizeTokensListState, - val dragConfig: DragConfig, - val actions: ActionsConfig, +@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 onSubscription: () -> Unit, + scope: CoroutineScope, ) { - data class HeaderConfig( - val onSortByBalanceClick: () -> Unit, - val onGroupByNetworkClick: () -> Unit, - ) + private val stateFlowInternal: MutableStateFlow = MutableStateFlow(getInitialState()) - data class ActionsConfig( - val onApplyClick: () -> Unit, - val onCancelClick: () -> Unit, - ) + private val tokenListConverter by lazy { + val tokensConverter = CryptoCurrencyToDraggableItemConverter( + fiatCurrencyCode = fiatCurrencyCode, + fiatCurrencySymbol = fiatCurrencySymbol, + ) + val itemsConverter = TokenListToListStateConverter( + tokensConverter = tokensConverter, + groupsConverter = NetworkGroupToDraggableItemsConverter(tokensConverter), + ) - data class DragConfig( - val onItemDragged: (from: ItemPosition, to: ItemPosition) -> Unit, - val canDragItemOver: (dragOver: ItemPosition, dragging: ItemPosition) -> Boolean, - val onItemDragEnd: () -> Unit, - val onDragStart: (item: DraggableItem) -> Unit, - ) -} + TokenListToStateConverter(Provider(stateFlowInternal::value), itemsConverter) + } -@Immutable -internal sealed interface OrganizeTokensListState { - val items: PersistentList + private val inProgressStateConverter by lazy { + InProgressStateConverter() + } - data class GroupedByNetwork( - override val items: PersistentList, - ) : OrganizeTokensListState + private val tokenListErrorConverter by lazy { + TokenListErrorConverter(Provider(stateFlowInternal::value), inProgressStateConverter) + } - data class Ungrouped( - override val items: PersistentList, - ) : OrganizeTokensListState + private val tokenListSortingErrorConverter by lazy { + TokenListSortingErrorConverter(Provider(stateFlowInternal::value), inProgressStateConverter) + } - @Suppress("UNCHECKED_CAST") - fun updateItems(update: (PersistentList) -> List): OrganizeTokensListState { - val updatedItems = update(this.items).toPersistentList() + val stateFlow: StateFlow = stateFlowInternal + .onSubscription { onSubscription() } + .stateIn( + scope = scope, + started = SharingStarted.WhileSubscribed(), + initialValue = getInitialState(), + ) - return when (this) { - is GroupedByNetwork -> this.copy(items = updatedItems) - is Ungrouped -> this.copy(items = updatedItems as PersistentList) + var tokenList: TokenList? = null + private set + + fun updateStateWithTokenList(tokenList: TokenList) { + updateState { tokenListConverter.convert(tokenList) } + this.tokenList = tokenList + } + + fun updateStateToDisplayProgress() { + updateState { inProgressStateConverter.convert(value = this) } + } + + fun updateStateToHideProgress() { + updateState { inProgressStateConverter.convertBack(value = this) } + } + + fun updateStateWithManualSorting(itemsState: OrganizeTokensListState) { + updateState { + copy( + header = header.copy(isSortedByBalance = false), + itemsState = itemsState, + ) } - } -} - -/** - * Helper class for the DND list items - * - * @property id ID of the item - * @property roundingMode item [RoundingMode] - * @property showShadow if true then item should be elevated - * */ -@Immutable -internal sealed interface DraggableItem { - val id: String - val roundingMode: RoundingMode - val showShadow: Boolean - - /** - * Item for network group header. - * - * @property id ID of the network group - * @property networkName network group name - * @property roundingMode item [RoundingMode] - * @property showShadow if true then item should be elevated - * */ - data class GroupHeader( - override val id: String, - val networkName: String, - override val roundingMode: RoundingMode = RoundingMode.None, - override val showShadow: Boolean = false, - ) : DraggableItem - - /** - * Item for token. - * - * @property tokenItemState state of the token item - * @property groupId ID of the network group which contains this token - * @property id ID of the token - * @property roundingMode item [RoundingMode] - * @property showShadow if true then item should be elevated - * */ - data class Token( - val tokenItemState: TokenItemState.Draggable, - val groupId: String, - override val showShadow: Boolean = false, - override val roundingMode: RoundingMode = RoundingMode.None, - ) : DraggableItem { - override val id: String = tokenItemState.id + tokenList = tokenList?.updateSorting(isSortedByBalance = false) } - /** - * Helper item used to detect possible positions where a network group can be placed. - * Used only on [OrganizeTokensListState.GroupedByNetwork] and placed between network groups. - * - * @property id ID of the placeholder - * */ - data class GroupPlaceholder( - override val id: String, - ) : DraggableItem { - override val showShadow: Boolean = false - override val roundingMode: RoundingMode = RoundingMode.None + fun updateStateWithError(error: TokenListError) { + updateState { tokenListErrorConverter.convert(error) } } - /** - * Update item [RoundingMode] - * - * @param mode new [RoundingMode] - * - * @return updated [DraggableItem] - * */ - fun roundingMode(mode: RoundingMode): DraggableItem = when (this) { - is GroupPlaceholder -> this - is GroupHeader -> this.copy(roundingMode = mode) - is Token -> this.copy(roundingMode = mode) + fun updateStateWithError(error: TokenListSortingError) { + updateState { tokenListSortingErrorConverter.convert(error) } } - /** - * Update item shadow visibility - * - * @param show if true then item should be elevated - * - * @return updated [DraggableItem] - * */ - fun showShadow(show: Boolean): DraggableItem = when (this) { - is GroupPlaceholder -> this - is GroupHeader -> this.copy(showShadow = show) - is Token -> this.copy(showShadow = show) + private fun getInitialState(): OrganizeTokensState { + return OrganizeTokensState( + onBackClick = intents::onBackClick, + itemsState = OrganizeTokensListState.Empty, + header = OrganizeTokensState.HeaderConfig( + onSortClick = intents::onSortClick, + onGroupClick = intents::onGroupClick, + ), + actions = OrganizeTokensState.ActionsConfig( + onApplyClick = intents::onApplyClick, + onCancelClick = intents::onCancelClick, + ), + dndConfig = OrganizeTokensState.DragAndDropConfig( + onItemDragged = intents::onItemDragged, + onDragStart = intents::onItemDraggingStart, + onItemDragEnd = intents::onItemDraggingEnd, + canDragItemOver = intents::canDragItemOver, + ), + ) } - /** - * Rounding mode of the [DraggableItem] - * - * @property showGap if true then item should have padding on rounded side - * */ - @Immutable - sealed interface RoundingMode { - val showGap: Boolean - - /** - * In this mode, item is not rounded - * */ - object None : RoundingMode { - override val showGap: Boolean = false - } - - /** - * In this mode, item should have a rounded top side - * - * @property showGap if true then item should have top padding - * */ - data class Top(override val showGap: Boolean = false) : RoundingMode - - /** - * In this mode, item should have a rounded bottom side - * - * @property showGap if true then item should have bottom padding - * */ - data class Bottom(override val showGap: Boolean = false) : RoundingMode - - /** - * In this mode, item should have a rounded all sides - * - * @property showGap if true then item should have top and bottom padding - * */ - data class All(override val showGap: Boolean = false) : RoundingMode + private fun updateState(block: OrganizeTokensState.() -> OrganizeTokensState) { + stateFlowInternal.update(block) } } \ No newline at end of file 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 52f391935b..f3fce2c7ea 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 @@ -8,9 +8,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.tangem.domain.wallets.models.UserWalletId import com.tangem.feature.wallet.presentation.common.WalletPreviewData -import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensStateHolder.DragConfig -import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensStateHolder.HeaderConfig -import com.tangem.feature.wallet.presentation.organizetokens.utils.* +import com.tangem.feature.wallet.presentation.organizetokens.utils.common.* import com.tangem.feature.wallet.presentation.router.InnerWalletRouter import com.tangem.feature.wallet.presentation.router.WalletRoute import dagger.hilt.android.lifecycle.HiltViewModel @@ -35,22 +33,22 @@ internal class OrganizeTokensViewModel @Inject constructor(savedStateHandle: Sav UserWalletId(userWalletIdValue) } - var uiState: OrganizeTokensStateHolder by mutableStateOf(getInitialState()) + var uiState: OrganizeTokensState by mutableStateOf(getInitialState()) private set - private fun getInitialState(): OrganizeTokensStateHolder = WalletPreviewData.organizeTokensState.copy( + private fun getInitialState(): OrganizeTokensState = WalletPreviewData.organizeTokensState.copy( itemsState = OrganizeTokensListState.Ungrouped( items = WalletPreviewData.draggableTokens, ), - dragConfig = DragConfig( + dndConfig = OrganizeTokensState.DragAndDropConfig( onItemDragged = this::moveItem, canDragItemOver = this::checkCanMoveItemOver, onItemDragEnd = this::endMoving, onDragStart = this::startMoving, ), - header = HeaderConfig( - onSortByBalanceClick = { /* no-op */ }, - onGroupByNetworkClick = this::toggleTokensByNetworkGrouping, + header = OrganizeTokensState.HeaderConfig( + onSortClick = { /* no-op */ }, + onGroupClick = this::toggleTokensByNetworkGrouping, ), ) @@ -62,6 +60,7 @@ internal class OrganizeTokensViewModel @Inject constructor(savedStateHandle: Sav is OrganizeTokensListState.Ungrouped -> OrganizeTokensListState.GroupedByNetwork( items = WalletPreviewData.draggableItems, ) + is OrganizeTokensListState.Empty -> itemsState } uiState = uiState.copy(itemsState = newListState) @@ -95,6 +94,7 @@ internal class OrganizeTokensViewModel @Inject constructor(savedStateHandle: Sav 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 } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemOperations.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemOperations.kt new file mode 100644 index 0000000000..3fb4746efb --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemOperations.kt @@ -0,0 +1,34 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.common + +import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem +import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem.RoundingMode + +/** + * Update item [RoundingMode] + * + * @param mode new [RoundingMode] + * + * @return updated [DraggableItem] + * */ +internal fun DraggableItem.updateRoundingMode(mode: RoundingMode): DraggableItem = when (this) { + is DraggableItem.GroupPlaceholder -> this + is DraggableItem.GroupHeader -> this.copy(roundingMode = mode) + is DraggableItem.Token -> this.copy(roundingMode = mode) +} + +/** + * Update item shadow visibility + * + * @param show if true then item should be elevated + * + * @return updated [DraggableItem] + * */ +internal fun DraggableItem.updateShadowVisibility(show: Boolean): DraggableItem = when (this) { + is DraggableItem.GroupPlaceholder -> this + is DraggableItem.GroupHeader -> this.copy(showShadow = show) + is DraggableItem.Token -> this.copy(showShadow = show) +} + +internal fun getGroupPlaceholder(index: Int): DraggableItem.GroupPlaceholder { + return DraggableItem.GroupPlaceholder(id = "placeholder_${index.inc()}") +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/DraggableItemsOperations.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemsOperations.kt similarity index 78% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/DraggableItemsOperations.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemsOperations.kt index 9bad24193c..58ae4fcefd 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/DraggableItemsOperations.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemsOperations.kt @@ -1,4 +1,4 @@ -package com.tangem.feature.wallet.presentation.organizetokens.utils +package com.tangem.feature.wallet.presentation.organizetokens.utils.common import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem import kotlinx.collections.immutable.PersistentList @@ -59,13 +59,15 @@ internal fun PersistentList.moveItem(fromIndex: Int, toIndex: Int internal fun List.divideItems(movingItem: DraggableItem): List { return this.map { it - .roundingMode(DraggableItem.RoundingMode.All(showGap = true)) - .showShadow(show = it.id == movingItem.id) + .updateRoundingMode(DraggableItem.RoundingMode.All(showGap = true)) + .updateShadowVisibility(show = it.id == movingItem.id) } } -internal fun List.uniteItems(): List { +@Suppress("UNCHECKED_CAST") // Erased type +internal fun List.uniteItems(): List { val lastItemIndex = this.lastIndex + return this.mapIndexed { index, item -> val mode = when (index) { 0 -> DraggableItem.RoundingMode.Top() @@ -74,9 +76,9 @@ internal fun List.uniteItems(): List { } item - .roundingMode(mode) - .showShadow(show = false) - } + .updateRoundingMode(mode) + .updateShadowVisibility(show = false) + } as List } // TODO: Move to domain @@ -131,51 +133,51 @@ internal fun List.divideGroups(movingItem: DraggableItem): List { item - .roundingMode(DraggableItem.RoundingMode.All(showGap = true)) - .showShadow(show = true) + .updateRoundingMode(DraggableItem.RoundingMode.All(showGap = true)) + .updateShadowVisibility(show = true) } // Case when moving item is a token and current item is the group of the moving token movingItem is DraggableItem.Token && item.id == movingItem.groupId -> { item - .roundingMode(DraggableItem.RoundingMode.All(showGap = true)) - .showShadow(show = true) + .updateRoundingMode(DraggableItem.RoundingMode.All(showGap = true)) + .updateShadowVisibility(show = true) } // Case when both moving item and current item are tokens and belong to the same group movingItem is DraggableItem.Token && item is DraggableItem.Token && item.groupId == movingItem.groupId -> { item - .roundingMode(DraggableItem.RoundingMode.All(showGap = true)) - .showShadow(show = false) + .updateRoundingMode(DraggableItem.RoundingMode.All(showGap = true)) + .updateShadowVisibility(show = false) } // Case when current item is the first item in the list index == 0 -> { item - .roundingMode(DraggableItem.RoundingMode.Top()) - .showShadow(show = false) + .updateRoundingMode(DraggableItem.RoundingMode.Top()) + .updateShadowVisibility(show = false) } // Case when current item is the last item in the list index == lastItemIndex -> { item - .roundingMode(DraggableItem.RoundingMode.Bottom()) - .showShadow(show = false) + .updateRoundingMode(DraggableItem.RoundingMode.Bottom()) + .updateShadowVisibility(show = false) } // Case when previous item is a GroupPlaceholder this[index - 1] is DraggableItem.GroupPlaceholder -> { item - .roundingMode(DraggableItem.RoundingMode.Top(showGap = true)) - .showShadow(show = false) + .updateRoundingMode(DraggableItem.RoundingMode.Top(showGap = true)) + .updateShadowVisibility(show = false) } // Case when next item is a GroupPlaceholder this[index + 1] is DraggableItem.GroupPlaceholder -> { item - .roundingMode(DraggableItem.RoundingMode.Bottom(showGap = true)) - .showShadow(show = false) + .updateRoundingMode(DraggableItem.RoundingMode.Bottom(showGap = true)) + .updateShadowVisibility(show = false) } // Default case when none of the above conditions are met else -> { item - .roundingMode(DraggableItem.RoundingMode.None) - .showShadow(show = false) + .updateRoundingMode(DraggableItem.RoundingMode.None) + .updateShadowVisibility(show = false) } } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/IdsOperations.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/IdsOperations.kt new file mode 100644 index 0000000000..d7e86bcff6 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/IdsOperations.kt @@ -0,0 +1,8 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.common + +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.tokens.models.Network + +internal fun getTokenItemId(currencyId: CryptoCurrency.ID): String = currencyId.value + +internal fun getGroupHeaderId(networkId: Network.ID): String = networkId.value \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/OrganiseTokensListStateOperations.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/OrganiseTokensListStateOperations.kt new file mode 100644 index 0000000000..bf5c601b7e --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/OrganiseTokensListStateOperations.kt @@ -0,0 +1,19 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.common + +import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem +import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensListState +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.toPersistentList + +@Suppress("UNCHECKED_CAST") +internal inline fun OrganizeTokensListState.updateItems( + update: (PersistentList) -> List, +): OrganizeTokensListState { + val updatedItems = update(items).toPersistentList() + + return when (this) { + is OrganizeTokensListState.GroupedByNetwork -> copy(items = updatedItems) + is OrganizeTokensListState.Ungrouped -> copy(items = updatedItems as PersistentList) + is OrganizeTokensListState.Empty -> this + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/TokenListOperations.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/TokenListOperations.kt new file mode 100644 index 0000000000..4f1478d2bf --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/TokenListOperations.kt @@ -0,0 +1,14 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.common + +import com.tangem.domain.tokens.model.TokenList +import com.tangem.domain.tokens.model.TokenList.SortType + +internal fun TokenList.updateSorting(isSortedByBalance: Boolean): TokenList { + val sortType = if (isSortedByBalance) SortType.BALANCE else SortType.NONE + + return when (this) { + is TokenList.GroupedByNetwork -> this.copy(sortedBy = sortType) + is TokenList.Ungrouped -> this.copy(sortedBy = sortType) + is TokenList.NotInitialized -> this + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/InProgressStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/InProgressStateConverter.kt new file mode 100644 index 0000000000..fc5c571ad9 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/InProgressStateConverter.kt @@ -0,0 +1,23 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.converter + +import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensState +import com.tangem.utils.converter.TwoWayConverter + +internal class InProgressStateConverter : TwoWayConverter { + + override fun convert(value: OrganizeTokensState): OrganizeTokensState { + return value.copy( + actions = value.actions.copy( + showApplyProgress = true, + ), + ) + } + + override fun convertBack(value: OrganizeTokensState): OrganizeTokensState { + return value.copy( + actions = value.actions.copy( + showApplyProgress = false, + ), + ) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenListToStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenListToStateConverter.kt new file mode 100644 index 0000000000..be5a3a12dc --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenListToStateConverter.kt @@ -0,0 +1,31 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.converter + +import com.tangem.common.Provider +import com.tangem.domain.tokens.model.TokenList +import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensListState +import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensState +import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items.TokenListToListStateConverter +import com.tangem.utils.converter.Converter + +internal class TokenListToStateConverter( + private val currentState: Provider, + private val itemsConverter: TokenListToListStateConverter, +) : Converter { + + 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 == TokenList.SortType.BALANCE, + isGrouped = value is TokenList.GroupedByNetwork, + ), + actions = state.actions.copy( + canApply = itemsState !is OrganizeTokensListState.Empty, + ), + ) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/error/TokenListErrorConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/error/TokenListErrorConverter.kt new file mode 100644 index 0000000000..f32dfbb528 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/error/TokenListErrorConverter.kt @@ -0,0 +1,18 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.error + +import com.tangem.common.Provider +import com.tangem.domain.tokens.error.TokenListError +import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensState +import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.InProgressStateConverter +import com.tangem.utils.converter.Converter + +internal class TokenListErrorConverter( + private val currentState: Provider, + private val inProgressStateConverter: InProgressStateConverter, +) : Converter { + + // TODO: [REDACTED_JIRA] + override fun convert(value: TokenListError): OrganizeTokensState { + return inProgressStateConverter.convertBack(currentState()) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/error/TokenListSortingErrorConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/error/TokenListSortingErrorConverter.kt new file mode 100644 index 0000000000..3072cc33c4 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/error/TokenListSortingErrorConverter.kt @@ -0,0 +1,18 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.error + +import com.tangem.common.Provider +import com.tangem.domain.tokens.error.TokenListSortingError +import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensState +import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.InProgressStateConverter +import com.tangem.utils.converter.Converter + +internal class TokenListSortingErrorConverter( + private val currentState: Provider, + private val inProgressStateConverter: InProgressStateConverter, +) : Converter { + + // TODO: [REDACTED_JIRA] + override fun convert(value: TokenListSortingError): OrganizeTokensState { + return inProgressStateConverter.convertBack(currentState()) + } +} \ 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 new file mode 100644 index 0000000000..f0e892fc45 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt @@ -0,0 +1,56 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items + +import androidx.annotation.DrawableRes +import com.tangem.core.ui.utils.BigDecimalFormatter +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.feature.wallet.impl.R +import com.tangem.feature.wallet.presentation.common.state.TokenItemState +import com.tangem.feature.wallet.presentation.organizetokens.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.converter.Converter + +internal class CryptoCurrencyToDraggableItemConverter( + private val fiatCurrencyCode: String, + private val fiatCurrencySymbol: String, +) : Converter { + + private val CryptoCurrency.networkIconResId: Int? + @DrawableRes get() { + // TODO: [REDACTED_JIRA] + return if (this is CryptoCurrency.Coin) null else R.drawable.img_eth_22 + } + + private val CryptoCurrency.tokenIconResId: Int + @DrawableRes get() { + // TODO: [REDACTED_JIRA] + return R.drawable.img_eth_22 + } + + override fun convert(value: CryptoCurrencyStatus): DraggableItem.Token { + return DraggableItem.Token( + tokenItemState = createToTokenItemState(value), + groupId = getGroupHeaderId(value.currency.networkId), + ) + } + + private fun createToTokenItemState(currencyStatus: CryptoCurrencyStatus): TokenItemState.Draggable { + val currency = currencyStatus.currency + + return TokenItemState.Draggable( + id = getTokenItemId(currency.id), + tokenIconUrl = currency.iconUrl, + tokenIconResId = currency.tokenIconResId, + networkIconResId = currency.networkIconResId, + name = currency.name, + fiatAmount = getFormattedFiatAmount(currencyStatus), + ) + } + + private fun getFormattedFiatAmount(currency: CryptoCurrencyStatus): String { + val fiatAmount = currency.value.fiatAmount ?: return BigDecimalFormatter.EMPTY_BALANCE_SIGN + + return BigDecimalFormatter.formatFiatAmount(fiatAmount, fiatCurrencyCode, fiatCurrencySymbol) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/NetworkGroupToDraggableItemsConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/NetworkGroupToDraggableItemsConverter.kt new file mode 100644 index 0000000000..47e698cf55 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/NetworkGroupToDraggableItemsConverter.kt @@ -0,0 +1,41 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items + +import com.tangem.domain.tokens.model.NetworkGroup +import com.tangem.feature.wallet.presentation.organizetokens.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> { + + override fun convert(value: NetworkGroup): List { + return buildList { + add(createGroupHeader(value)) + addAll(createTokens(value)) + } + } + + override fun convertList(input: Collection): List> { + 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.id), + networkName = group.network.name, + ) + + private fun createTokens(group: NetworkGroup): List { + return itemConverter.convertList(group.currencies.toList()) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/TokenListToListStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/TokenListToListStateConverter.kt new file mode 100644 index 0000000000..f62bd3abb9 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/TokenListToListStateConverter.kt @@ -0,0 +1,42 @@ +package com.tangem.feature.wallet.presentation.organizetokens.utils.converter.items + +import com.tangem.domain.tokens.model.TokenList +import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensListState +import com.tangem.feature.wallet.presentation.organizetokens.utils.common.uniteItems +import com.tangem.utils.converter.Converter +import kotlinx.collections.immutable.toPersistentList + +internal class TokenListToListStateConverter( + private val groupsConverter: NetworkGroupToDraggableItemsConverter, + private val tokensConverter: CryptoCurrencyToDraggableItemConverter, +) : Converter { + + override fun convert(value: TokenList): OrganizeTokensListState { + return when (value) { + is TokenList.GroupedByNetwork -> createListState(value) + is TokenList.Ungrouped -> createListState(value) + is TokenList.NotInitialized -> createEmptyListState() + } + } + + private fun createListState(tokenList: TokenList.GroupedByNetwork): OrganizeTokensListState.GroupedByNetwork { + return OrganizeTokensListState.GroupedByNetwork( + items = groupsConverter.convertList(tokenList.groups) + .flatten() + .uniteItems() + .toPersistentList(), + ) + } + + private fun createListState(tokenList: TokenList.Ungrouped): OrganizeTokensListState.Ungrouped { + return OrganizeTokensListState.Ungrouped( + items = tokensConverter.convertList(tokenList.currencies) + .uniteItems() + .toPersistentList(), + ) + } + + private fun createEmptyListState(): OrganizeTokensListState.Empty { + return OrganizeTokensListState.Empty + } +} \ No newline at end of file