From ff918c04b49cdd017fa3e8f1f9b1431ed5edd615 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 24 Feb 2026 13:08:09 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/di/domain/TokensDomainModule.kt | 14 -- .../status/di/AccountStatusUseCaseModule.kt | 12 +- .../status/model/AccountCryptoCurrency.kt | 2 +- ...eV2.kt => ApplyTokenListSortingUseCase.kt} | 6 +- ...2.kt => ToggleTokenListGroupingUseCase.kt} | 2 +- ...V2.kt => ToggleTokenListSortingUseCase.kt} | 2 +- .../ApplyTokenListSortingUseCaseTest.kt | 2 +- ... => ToggleTokenListGroupingUseCaseTest.kt} | 4 +- ...t => ToggleTokenListSortingUseCaseTest.kt} | 4 +- .../tokens/ToggleTokenListGroupingUseCase.kt | 51 ---- .../tokens/ToggleTokenListSortingUseCase.kt | 38 --- .../tokens/ToggleTokenListGroupingTest.kt | 103 -------- .../ToggleTokenListSortingUseCaseTest.kt | 103 -------- .../organizetokens/OrganizeTokensComponent.kt | 2 +- .../PortfolioOrganizeTokensAnalyticsEvent.kt | 2 +- .../organizetokens/entity}/DraggableItem.kt | 2 +- .../entity/OrganizeTokensListUM.kt} | 20 +- .../entity}/OrganizeTokensState.kt | 3 +- .../model/CryptoCurrenciesIdsResolver.kt | 35 +++ .../organizetokens/model}/Intents.kt | 4 +- .../model/OrganizeTokensModel.kt | 233 +++++------------- .../model/OrganizeTokensStateHolder.kt | 111 +++++++++ .../model}/common/DraggableItemOperations.kt | 4 +- .../model}/common/DraggableItemsOperations.kt | 55 +---- .../model}/common/IdsOperations.kt | 2 +- .../OrganiseTokensListStateOperations.kt | 18 ++ .../model}/common/TokenListOperations.kt | 2 +- .../converter/InProgressStateConverter.kt | 4 +- .../converter/TokenListToStateConverter.kt} | 20 +- .../error/TokenListErrorConverter.kt | 6 +- .../error/TokenListSortingErrorConverter.kt | 6 +- ...CryptoCurrencyToDraggableItemConverter.kt} | 10 +- .../NetworkGroupToDraggableItemsConverter.kt} | 16 +- .../items/OrganizedTokenListConverter.kt | 8 +- .../model/dnd/DragAndDropAdapter.kt} | 24 +- .../model}/dnd/DraggableGroupsOperations.kt | 47 +--- .../ui}/OrganizeTokensScreen.kt | 23 +- .../ui/preview/OrganizeTokensPreview.kt | 127 ++++++++++ .../presentation/common/WalletPreviewData.kt | 130 ---------- .../OrganizeTokensStateHolder.kt | 166 ------------- .../utils/CryptoCurrenciesIdsResolver.kt | 60 ----- .../OrganiseTokensListStateOperations.kt | 31 --- .../converter/TokenListToStateConverter.kt | 32 --- .../CryptoCurrencyToDraggableItemConverter.kt | 74 ------ .../NetworkGroupToDraggableItemsConverter.kt | 41 --- .../items/TokenListToListStateConverter.kt | 45 ---- .../utils/dnd/DragAndDropAdapter.kt | 185 -------------- 47 files changed, 440 insertions(+), 1451 deletions(-) rename domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/{ApplyTokenListSortingUseCaseV2.kt => ApplyTokenListSortingUseCase.kt} (98%) rename domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/{ToggleTokenListGroupingUseCaseV2.kt => ToggleTokenListGroupingUseCase.kt} (98%) rename domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/{ToggleTokenListSortingUseCaseV2.kt => ToggleTokenListSortingUseCase.kt} (98%) rename domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/{ToggleTokenListGroupingUseCaseV2Test.kt => ToggleTokenListGroupingUseCaseTest.kt} (98%) rename domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/{ToggleTokenListSortingUseCaseV2Test.kt => ToggleTokenListSortingUseCaseTest.kt} (97%) delete mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ToggleTokenListGroupingUseCase.kt delete mode 100644 domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ToggleTokenListSortingUseCase.kt delete mode 100644 domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ToggleTokenListGroupingTest.kt delete mode 100644 domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ToggleTokenListSortingUseCaseTest.kt rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation => child}/organizetokens/analytics/PortfolioOrganizeTokensAnalyticsEvent.kt (92%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/model => child/organizetokens/entity}/DraggableItem.kt (98%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/model/OrganizeTokensListState.kt => child/organizetokens/entity/OrganizeTokensListUM.kt} (54%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/model => child/organizetokens/entity}/OrganizeTokensState.kt (91%) create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/CryptoCurrenciesIdsResolver.kt rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens => child/organizetokens/model}/Intents.kt (76%) create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/OrganizeTokensStateHolder.kt rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils => child/organizetokens/model}/common/DraggableItemOperations.kt (59%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils => child/organizetokens/model}/common/DraggableItemsOperations.kt (63%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils => child/organizetokens/model}/common/IdsOperations.kt (78%) create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/common/OrganiseTokensListStateOperations.kt rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils => child/organizetokens/model}/common/TokenListOperations.kt (83%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils => child/organizetokens/model}/converter/InProgressStateConverter.kt (82%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils/converter/TokenListToStateConverterV2.kt => child/organizetokens/model/converter/TokenListToStateConverter.kt} (83%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils => child/organizetokens/model}/converter/error/TokenListErrorConverter.kt (64%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils => child/organizetokens/model}/converter/error/TokenListSortingErrorConverter.kt (65%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverterV2.kt => child/organizetokens/model/converter/items/CryptoCurrencyToDraggableItemConverter.kt} (87%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils/converter/items/NetworkGroupToDraggableItemsConverterV2.kt => child/organizetokens/model/converter/items/NetworkGroupToDraggableItemsConverter.kt} (78%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils => child/organizetokens/model}/converter/items/OrganizedTokenListConverter.kt (85%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils/dnd/DragAndDropAdapterV2.kt => child/organizetokens/model/dnd/DragAndDropAdapter.kt} (87%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens/utils => child/organizetokens/model}/dnd/DraggableGroupsOperations.kt (59%) rename features/wallet/impl/src/main/java/com/tangem/feature/wallet/{presentation/organizetokens => child/organizetokens/ui}/OrganizeTokensScreen.kt (95%) create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/preview/OrganizeTokensPreview.kt delete mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensStateHolder.kt delete mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/CryptoCurrenciesIdsResolver.kt delete mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/OrganiseTokensListStateOperations.kt delete mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenListToStateConverter.kt delete mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt delete mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/NetworkGroupToDraggableItemsConverter.kt delete mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/TokenListToListStateConverter.kt delete mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/dnd/DragAndDropAdapter.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt index ef95af2a32..ecba7042ef 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/TokensDomainModule.kt @@ -177,20 +177,6 @@ internal object TokensDomainModule { return GetCryptoCurrencyUseCase(currenciesRepository, multiWalletCryptoCurrenciesSupplier) } - @Provides - @Singleton - fun provideToggleTokenListGroupingUseCase( - dispatchers: CoroutineDispatcherProvider, - ): ToggleTokenListGroupingUseCase { - return ToggleTokenListGroupingUseCase(dispatchers) - } - - @Provides - @Singleton - fun provideToggleTokenListSortingUseCase(dispatchers: CoroutineDispatcherProvider): ToggleTokenListSortingUseCase { - return ToggleTokenListSortingUseCase(dispatchers) - } - @Provides @Singleton fun provideApplyTokenListSortingUseCase( diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusUseCaseModule.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusUseCaseModule.kt index a228aceb2e..1f7bea813c 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusUseCaseModule.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/di/AccountStatusUseCaseModule.kt @@ -67,8 +67,8 @@ internal object AccountStatusUseCaseModule { fun provideApplyTokenListSortingUseCaseV2( accountsCRUDRepository: AccountsCRUDRepository, dispatchers: CoroutineDispatcherProvider, - ): ApplyTokenListSortingUseCaseV2 { - return ApplyTokenListSortingUseCaseV2( + ): ApplyTokenListSortingUseCase { + return ApplyTokenListSortingUseCase( accountsCRUDRepository = accountsCRUDRepository, dispatchers = dispatchers, ) @@ -141,8 +141,8 @@ internal object AccountStatusUseCaseModule { @Singleton fun provideToggleTokenListSortingUseCaseV2( dispatchers: CoroutineDispatcherProvider, - ): ToggleTokenListSortingUseCaseV2 { - return ToggleTokenListSortingUseCaseV2( + ): ToggleTokenListSortingUseCase { + return ToggleTokenListSortingUseCase( dispatchers = dispatchers, ) } @@ -151,8 +151,8 @@ internal object AccountStatusUseCaseModule { @Singleton fun provideToggleTokenListGroupingUseCaseV2( dispatchers: CoroutineDispatcherProvider, - ): ToggleTokenListGroupingUseCaseV2 { - return ToggleTokenListGroupingUseCaseV2( + ): ToggleTokenListGroupingUseCase { + return ToggleTokenListGroupingUseCase( dispatchers = dispatchers, ) } diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/model/AccountCryptoCurrency.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/model/AccountCryptoCurrency.kt index 5acaea2b98..152ab3ca77 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/model/AccountCryptoCurrency.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/model/AccountCryptoCurrency.kt @@ -4,7 +4,7 @@ import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrency import kotlinx.serialization.Serializable -typealias AccountCryptoCurrencies = Map> +typealias AccountCryptoCurrencies = Map> /** * Combines an [Account] with its corresponding [CryptoCurrency]. diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ApplyTokenListSortingUseCaseV2.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ApplyTokenListSortingUseCase.kt similarity index 98% rename from domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ApplyTokenListSortingUseCaseV2.kt rename to domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ApplyTokenListSortingUseCase.kt index 6dc53cca47..55e21d936c 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ApplyTokenListSortingUseCaseV2.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ApplyTokenListSortingUseCase.kt @@ -25,7 +25,7 @@ private typealias SortingErrorByAccountId = MutableMap + errors[account.accountId] = error return@map account } diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCaseV2.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCase.kt similarity index 98% rename from domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCaseV2.kt rename to domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCase.kt index 32e1b28366..648daca038 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCaseV2.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCase.kt @@ -21,7 +21,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider * * @property dispatchers Provides coroutine dispatchers for executing tasks. */ -class ToggleTokenListGroupingUseCaseV2( +class ToggleTokenListGroupingUseCase( private val dispatchers: CoroutineDispatcherProvider, ) { diff --git a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCaseV2.kt b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCase.kt similarity index 98% rename from domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCaseV2.kt rename to domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCase.kt index ccf2416368..18bfbc35a1 100644 --- a/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCaseV2.kt +++ b/domain/account/status/src/main/java/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCase.kt @@ -21,7 +21,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider * * @property dispatchers Provides coroutine dispatchers for executing tasks. */ -class ToggleTokenListSortingUseCaseV2( +class ToggleTokenListSortingUseCase( private val dispatchers: CoroutineDispatcherProvider, ) { diff --git a/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ApplyTokenListSortingUseCaseTest.kt b/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ApplyTokenListSortingUseCaseTest.kt index af71ec2c02..bd340dc150 100644 --- a/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ApplyTokenListSortingUseCaseTest.kt +++ b/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ApplyTokenListSortingUseCaseTest.kt @@ -30,7 +30,7 @@ internal class ApplyTokenListSortingUseCaseTest { private val accountsCRUDRepository = mockk(relaxUnitFun = true) - private val useCase = ApplyTokenListSortingUseCaseV2( + private val useCase = ApplyTokenListSortingUseCase( accountsCRUDRepository = accountsCRUDRepository, dispatchers = TestingCoroutineDispatcherProvider(), ) diff --git a/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCaseV2Test.kt b/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCaseTest.kt similarity index 98% rename from domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCaseV2Test.kt rename to domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCaseTest.kt index 9dadb85e4f..9e3b423a62 100644 --- a/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCaseV2Test.kt +++ b/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListGroupingUseCaseTest.kt @@ -28,9 +28,9 @@ import java.math.BigDecimal [REDACTED_AUTHOR] */ @TestInstance(TestInstance.Lifecycle.PER_CLASS) -class ToggleTokenListGroupingUseCaseV2Test { +class ToggleTokenListGroupingUseCaseTest { - private val useCase = ToggleTokenListGroupingUseCaseV2(dispatchers = TestingCoroutineDispatcherProvider()) + private val useCase = ToggleTokenListGroupingUseCase(dispatchers = TestingCoroutineDispatcherProvider()) private val userWalletId = UserWalletId("011") private val cryptoCurrencyFactory = MockCryptoCurrencyFactory() diff --git a/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCaseV2Test.kt b/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCaseTest.kt similarity index 97% rename from domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCaseV2Test.kt rename to domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCaseTest.kt index 344dc8641e..c7808be2d4 100644 --- a/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCaseV2Test.kt +++ b/domain/account/status/src/test/kotlin/com/tangem/domain/account/status/usecase/ToggleTokenListSortingUseCaseTest.kt @@ -28,9 +28,9 @@ import java.math.BigDecimal [REDACTED_AUTHOR] */ @TestInstance(TestInstance.Lifecycle.PER_CLASS) -class ToggleTokenListSortingUseCaseV2Test { +class ToggleTokenListSortingUseCaseTest { - private val useCase = ToggleTokenListSortingUseCaseV2(dispatchers = TestingCoroutineDispatcherProvider()) + private val useCase = ToggleTokenListSortingUseCase(dispatchers = TestingCoroutineDispatcherProvider()) private val userWalletId = UserWalletId("011") private val cryptoCurrencyFactory = MockCryptoCurrencyFactory() diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ToggleTokenListGroupingUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ToggleTokenListGroupingUseCase.kt deleted file mode 100644 index 11bdea2a34..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ToggleTokenListGroupingUseCase.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import arrow.core.raise.Raise -import arrow.core.raise.either -import arrow.core.raise.ensure -import com.tangem.domain.models.TotalFiatBalance -import com.tangem.domain.models.tokenlist.TokenList -import com.tangem.domain.tokens.error.TokenListSortingError -import com.tangem.domain.tokens.operations.TokenListFactory -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.withContext - -class ToggleTokenListGroupingUseCase( - private val dispatchers: CoroutineDispatcherProvider, -) { - - suspend operator fun invoke(tokenList: TokenList): Either { - return withContext(dispatchers.default) { - either { - when (tokenList) { - is TokenList.GroupedByNetwork -> ungroupTokens(tokenList) - is TokenList.Ungrouped -> groupTokens(tokenList) - is TokenList.Empty -> raise(TokenListSortingError.TokenListIsEmpty) - } - } - } - } - - private fun Raise.groupTokens(tokenList: TokenList.Ungrouped): TokenList.GroupedByNetwork { - validate(tokenList) - - return TokenListFactory.createGroupedByNetwork(tokenList) - } - - private fun Raise.ungroupTokens(tokenList: TokenList.GroupedByNetwork): TokenList.Ungrouped { - validate(tokenList) - - return TokenListFactory.createUngrouped(tokenList) - } - - private fun Raise.validate(tokenList: TokenList) { - ensure(tokenList.totalFiatBalance !is TotalFiatBalance.Loading) { - TokenListSortingError.TokenListIsLoading - } - - ensure(tokenList.flattenCurrencies().isNotEmpty()) { - TokenListSortingError.TokenListIsEmpty - } - } -} \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ToggleTokenListSortingUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ToggleTokenListSortingUseCase.kt deleted file mode 100644 index 2bc37f5bb1..0000000000 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/ToggleTokenListSortingUseCase.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.Either -import arrow.core.raise.either -import arrow.core.raise.ensure -import com.tangem.domain.models.TokensGroupType -import com.tangem.domain.models.TokensSortType -import com.tangem.domain.models.TotalFiatBalance -import com.tangem.domain.models.tokenlist.TokenList -import com.tangem.domain.tokens.error.TokenListSortingError -import com.tangem.domain.tokens.operations.TokenListFactory -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.withContext - -class ToggleTokenListSortingUseCase( - private val dispatchers: CoroutineDispatcherProvider, -) { - - suspend operator fun invoke(tokenList: TokenList): Either { - return withContext(dispatchers.default) { - either { - ensure(tokenList.totalFiatBalance !is TotalFiatBalance.Loading) { - TokenListSortingError.TokenListIsLoading - } - - TokenListFactory.create( - statuses = tokenList.flattenCurrencies(), - groupType = when (tokenList) { - is TokenList.GroupedByNetwork -> TokensGroupType.NETWORK - is TokenList.Ungrouped -> TokensGroupType.NONE - is TokenList.Empty -> raise(TokenListSortingError.TokenListIsEmpty) - }, - sortType = TokensSortType.BALANCE, - ) - } - } - } -} \ No newline at end of file diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ToggleTokenListGroupingTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ToggleTokenListGroupingTest.kt deleted file mode 100644 index 8630063505..0000000000 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ToggleTokenListGroupingTest.kt +++ /dev/null @@ -1,103 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.left -import arrow.core.right -import com.google.common.truth.Truth -import com.tangem.domain.tokens.error.TokenListSortingError -import com.tangem.domain.tokens.mock.MockTokenLists -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider -import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.TestInstance - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -internal class ToggleTokenListGroupingTest { - - private val useCase = ToggleTokenListGroupingUseCase( - dispatchers = TestingCoroutineDispatcherProvider(), - ) - - @Test - fun `when list is empty then error should be received`() = runTest { - // Given - val expected = TokenListSortingError.TokenListIsEmpty.left() - - // When - val actual = useCase(MockTokenLists.emptyUngroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is grouped and loading then error should be received`() = runTest { - // Given - val expected = TokenListSortingError.TokenListIsLoading.left() - - // When - val actual = useCase(MockTokenLists.loadingGroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is ungrouped and loading then error should be received`() = runTest { - // Given - val expected = TokenListSortingError.TokenListIsLoading.left() - - // When - val actual = useCase(MockTokenLists.loadingUngroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is ungrouped and sorted then sorted grouped list should be received`() = runTest { - // Given - val expected = MockTokenLists.sortedGroupedTokenList.right() - - // When - val actual = useCase(MockTokenLists.sortedUngroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is ungrouped and unsorted then unsorted grouped list should be received`() = runTest { - // Given - val expected = MockTokenLists.unsortedGroupedTokenList.right() - - // When - val actual = useCase(MockTokenLists.unsortedUngroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is grouped and sorted then sorted ungrouped list should be received`() = runTest { - // Given - val expected = MockTokenLists.sortedUngroupedTokenList.right() - - // When - val actual = useCase(MockTokenLists.sortedGroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is grouped and unsorted then unsorted ungrouped list should be received`() = runTest { - // Given - val expected = MockTokenLists.unsortedUngroupedTokenList.right() - - // When - val actual = useCase(MockTokenLists.unsortedGroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } -} \ No newline at end of file diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ToggleTokenListSortingUseCaseTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ToggleTokenListSortingUseCaseTest.kt deleted file mode 100644 index 787d55393c..0000000000 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/ToggleTokenListSortingUseCaseTest.kt +++ /dev/null @@ -1,103 +0,0 @@ -package com.tangem.domain.tokens - -import arrow.core.left -import arrow.core.right -import com.google.common.truth.Truth -import com.tangem.domain.tokens.error.TokenListSortingError -import com.tangem.domain.tokens.mock.MockTokenLists -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider -import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.TestInstance - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -internal class ToggleTokenListSortingUseCaseTest { - - private val useCase = ToggleTokenListSortingUseCase( - dispatchers = TestingCoroutineDispatcherProvider(), - ) - - @Test - fun `when list is empty then error should be received`() = runTest { - // Given - val expected = TokenListSortingError.TokenListIsEmpty.left() - - // When - val actual = useCase(MockTokenLists.emptyTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is grouped and loading then error should be received`() = runTest { - // Given - val expected = TokenListSortingError.TokenListIsLoading.left() - - // When - val actual = useCase(MockTokenLists.loadingGroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is ungrouped and loading then error should be received`() = runTest { - // Given - val expected = TokenListSortingError.TokenListIsLoading.left() - - // When - val actual = useCase(MockTokenLists.loadingUngroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is grouped and unsorted then grouped and sorted list should be received`() = runTest { - // Given - val expected = MockTokenLists.sortedGroupedTokenList.right() - - // When - val actual = useCase(MockTokenLists.unsortedGroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is ungrouped and unsorted then ungrouped and sorted list should be received`() = runTest { - // Given - val expected = MockTokenLists.sortedUngroupedTokenList.right() - - // When - val actual = useCase(MockTokenLists.unsortedUngroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is grouped and sorted then grouped and unsorted list should be received`() = runTest { - // Given - val expected = MockTokenLists.sortedGroupedTokenList.right() - - // When - val actual = useCase(MockTokenLists.unsortedGroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } - - @Test - fun `when list is ungrouped and sorted then ungrouped and unsorted list should be received`() = runTest { - // Given - val expected = MockTokenLists.sortedUngroupedTokenList.right() - - // When - val actual = useCase(MockTokenLists.unsortedUngroupedTokenList) - - // Then - Truth.assertThat(actual).isEqualTo(expected) - } -} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/OrganizeTokensComponent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/OrganizeTokensComponent.kt index b54ed3161b..e8a18c88ec 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/OrganizeTokensComponent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/OrganizeTokensComponent.kt @@ -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( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/analytics/PortfolioOrganizeTokensAnalyticsEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/analytics/PortfolioOrganizeTokensAnalyticsEvent.kt similarity index 92% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/analytics/PortfolioOrganizeTokensAnalyticsEvent.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/analytics/PortfolioOrganizeTokensAnalyticsEvent.kt index a0c96c2974..5d4948ab02 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/analytics/PortfolioOrganizeTokensAnalyticsEvent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/analytics/PortfolioOrganizeTokensAnalyticsEvent.kt @@ -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 diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/model/DraggableItem.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/entity/DraggableItem.kt similarity index 98% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/model/DraggableItem.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/entity/DraggableItem.kt index da7e0746a2..4d0560b517 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/model/DraggableItem.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/entity/DraggableItem.kt @@ -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 diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/model/OrganizeTokensListState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/entity/OrganizeTokensListUM.kt similarity index 54% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/model/OrganizeTokensListState.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/entity/OrganizeTokensListUM.kt index 720edbb802..38144081c3 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/model/OrganizeTokensListState.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/entity/OrganizeTokensListUM.kt @@ -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 - - data class GroupedByNetwork( - override val items: PersistentList, - ) : OrganizeTokensListState() - - data class Ungrouped( - override val items: PersistentList, - ) : OrganizeTokensListState() - - data object Empty : OrganizeTokensListState() { - override val items: PersistentList = persistentListOf() - } -} - @Immutable internal sealed interface OrganizeTokensListUM { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/model/OrganizeTokensState.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/entity/OrganizeTokensState.kt similarity index 91% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/model/OrganizeTokensState.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/entity/OrganizeTokensState.kt index 556f2e081d..234ab0e793 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/model/OrganizeTokensState.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/entity/OrganizeTokensState.kt @@ -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, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/CryptoCurrenciesIdsResolver.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/CryptoCurrenciesIdsResolver.kt new file mode 100644 index 0000000000..cb1a1b0db7 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/CryptoCurrenciesIdsResolver.kt @@ -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() + } + + 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() + } + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/Intents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/Intents.kt similarity index 76% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/Intents.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/Intents.kt index e0f4868347..5123361a66 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/Intents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/Intents.kt @@ -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 { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/OrganizeTokensModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/OrganizeTokensModel.kt index fb310ec8be..bd4e6ee9be 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/OrganizeTokensModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/OrganizeTokensModel.kt @@ -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().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::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() diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/OrganizeTokensStateHolder.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/OrganizeTokensStateHolder.kt new file mode 100644 index 0000000000..638cfa480b --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/OrganizeTokensStateHolder.kt @@ -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, +) { + + private val stateFlowInternal: MutableStateFlow = MutableStateFlow(getInitialState()) + + private val inProgressStateConverter by lazy { InProgressStateConverter() } + + private val tokenListSortingErrorConverter by lazy { + TokenListSortingErrorConverter(Provider(stateFlowInternal::value), inProgressStateConverter) + } + + val stateFlow: StateFlow = 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()) } + } +} \ No newline at end of file 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/child/organizetokens/model/common/DraggableItemOperations.kt similarity index 59% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemOperations.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/common/DraggableItemOperations.kt index 80ea9a25b1..1133e2b1b9 100644 --- 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/child/organizetokens/model/common/DraggableItemOperations.kt @@ -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( diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemsOperations.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/common/DraggableItemsOperations.kt similarity index 63% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemsOperations.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/common/DraggableItemsOperations.kt index 2c10ffaf82..f668be3be6 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/DraggableItemsOperations.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/common/DraggableItemsOperations.kt @@ -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.uniteItems(): List { - 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.uniteItemsV2(isAccountsMode: Boolean): List { +internal fun List.uniteItems(isAccountsMode: Boolean): List { val items = this val lastItemIndex = items.lastIndex @@ -92,27 +64,6 @@ internal fun List.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.prepareItems(): List { - val firstPlaceholderId = "initial_placeholder" - val items = this - - return mutableListOf().apply { - add(DraggableItem.Placeholder(firstPlaceholderId)) - - val itemsWithoutFirstPlaceholder = items.filterNot { it.id == firstPlaceholderId } - - addAll(itemsWithoutFirstPlaceholder) - } -} - /** * Applying rounding to tokens * 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/child/organizetokens/model/common/IdsOperations.kt similarity index 78% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/IdsOperations.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/common/IdsOperations.kt index 0225b0d6ca..b4d70c5fb0 100644 --- 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/child/organizetokens/model/common/IdsOperations.kt @@ -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 diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/common/OrganiseTokensListStateOperations.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/common/OrganiseTokensListStateOperations.kt new file mode 100644 index 0000000000..2935a14855 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/common/OrganiseTokensListStateOperations.kt @@ -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) -> List, +): OrganizeTokensListUM { + val updatedItems = update(items).toPersistentList() + + return when (this) { + is OrganizeTokensListUM.AccountList -> copy(items = updatedItems) + is OrganizeTokensListUM.TokensList -> copy(items = updatedItems) + OrganizeTokensListUM.EmptyList -> 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/child/organizetokens/model/common/TokenListOperations.kt similarity index 83% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/TokenListOperations.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/common/TokenListOperations.kt index 8600d8beaf..b298e1121c 100644 --- 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/child/organizetokens/model/common/TokenListOperations.kt @@ -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 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/child/organizetokens/model/converter/InProgressStateConverter.kt similarity index 82% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/InProgressStateConverter.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/InProgressStateConverter.kt index 936385e8ea..7da5b51e59 100644 --- 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/child/organizetokens/model/converter/InProgressStateConverter.kt @@ -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 { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenListToStateConverterV2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/TokenListToStateConverter.kt similarity index 83% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenListToStateConverterV2.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/TokenListToStateConverter.kt index 279d59f8ed..61bb28d854 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenListToStateConverterV2.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/TokenListToStateConverter.kt @@ -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(), ) } 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/child/organizetokens/model/converter/error/TokenListErrorConverter.kt similarity index 64% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/error/TokenListErrorConverter.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/error/TokenListErrorConverter.kt index e2117bfc5f..506816829f 100644 --- 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/child/organizetokens/model/converter/error/TokenListErrorConverter.kt @@ -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 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/child/organizetokens/model/converter/error/TokenListSortingErrorConverter.kt similarity index 65% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/error/TokenListSortingErrorConverter.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/error/TokenListSortingErrorConverter.kt index 7d7bcd16c5..f86c07468e 100644 --- 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/child/organizetokens/model/converter/error/TokenListSortingErrorConverter.kt @@ -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 diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverterV2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/items/CryptoCurrencyToDraggableItemConverter.kt similarity index 87% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverterV2.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/items/CryptoCurrencyToDraggableItemConverter.kt index 478351d5dc..cd6c995427 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverterV2.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/items/CryptoCurrencyToDraggableItemConverter.kt @@ -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 { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/NetworkGroupToDraggableItemsConverterV2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/items/NetworkGroupToDraggableItemsConverter.kt similarity index 78% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/NetworkGroupToDraggableItemsConverterV2.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/items/NetworkGroupToDraggableItemsConverter.kt index 13206c8a13..9a68fca15d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/NetworkGroupToDraggableItemsConverterV2.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/items/NetworkGroupToDraggableItemsConverter.kt @@ -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, List> { override fun convert(value: Pair): List { @@ -42,10 +42,10 @@ internal class NetworkGroupToDraggableItemsConverterV2( private fun createTokens(account: Account.CryptoPortfolio, group: NetworkGroup): List { return itemConverter.convertList( - group.currencies.map { + group.currencies.map { currencyStatus -> AccountCryptoCurrencyStatus( account = account, - status = it, + status = currencyStatus, ) }, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/OrganizedTokenListConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/items/OrganizedTokenListConverter.kt similarity index 85% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/OrganizedTokenListConverter.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/items/OrganizedTokenListConverter.kt index c0938d2748..c1f5ce4fef 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/OrganizedTokenListConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/converter/items/OrganizedTokenListConverter.kt @@ -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> { - 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 { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/dnd/DragAndDropAdapterV2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/dnd/DragAndDropAdapter.kt similarity index 87% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/dnd/DragAndDropAdapterV2.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/dnd/DragAndDropAdapter.kt index 6c0a7531b8..7e4e3b77fd 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/dnd/DragAndDropAdapterV2.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/dnd/DragAndDropAdapter.kt @@ -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, ) : 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, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/dnd/DraggableGroupsOperations.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/dnd/DraggableGroupsOperations.kt similarity index 59% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/dnd/DraggableGroupsOperations.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/dnd/DraggableGroupsOperations.kt index e92d772829..7ce66f0a2e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/dnd/DraggableGroupsOperations.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/model/dnd/DraggableGroupsOperations.kt @@ -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, movingGroup: DraggableItem.GroupHeader): List { - if (!groupIdToTokens.isNullOrEmpty()) return items - - groupIdToTokens = items - .asSequence() - .filterIsInstance() - .groupBy { it.groupId } - - val itemsWithoutGroupTokens = items.filterNot { - it is DraggableItem.Token && it.groupId == movingGroup.id - } - - return itemsWithoutGroupTokens.divideMovingItem(movingGroup) - } - fun expandGroups(items: List): List { if (groupIdToTokens.isNullOrEmpty()) return items - val currentGroups = items.filterIsInstance() - 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): List { - if (groupIdToTokens.isNullOrEmpty()) return items - val accountList = items.filterIsInstance() val currentGroups = items.filterIsInstance() 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/child/organizetokens/ui/OrganizeTokensScreen.kt similarity index 95% rename from features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensScreen.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/OrganizeTokensScreen.kt index 2996d749be..1c23378393 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/child/organizetokens/ui/OrganizeTokensScreen.kt @@ -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( collection = listOf( - WalletPreviewData.organizeTokensState, - WalletPreviewData.groupedOrganizeTokensState, + OrganizeTokensPreview.stateAccounts, + OrganizeTokensPreview.state, ), ) // endregion Preview \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/preview/OrganizeTokensPreview.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/preview/OrganizeTokensPreview.kt new file mode 100644 index 0000000000..47869d9b69 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/organizetokens/ui/preview/OrganizeTokensPreview.kt @@ -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 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 = 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, + ), + ) + } +} \ No newline at end of file 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 be88fcbccd..1c48f40af5 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 @@ -1,23 +1,11 @@ package com.tangem.feature.wallet.presentation.common -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 { @@ -67,124 +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 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 = 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() - .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 actionsBottomSheet = ActionsBottomSheetConfig( actions = listOf( TokenActionButtonConfig( 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 deleted file mode 100644 index f1eb7915cf..0000000000 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/OrganizeTokensStateHolder.kt +++ /dev/null @@ -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, - private val accountsFeatureToggles: AccountsFeatureToggles, -) { - - private val stateFlowInternal: MutableStateFlow = 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 = 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()) } - } -} \ 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 deleted file mode 100644 index 770ada3985..0000000000 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/CryptoCurrenciesIdsResolver.kt +++ /dev/null @@ -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 { - val draggableTokens = when (listState) { - is OrganizeTokensListState.Empty -> return emptyList() - is OrganizeTokensListState.GroupedByNetwork -> listState.items.filterIsInstance() - is OrganizeTokensListState.Ungrouped -> listState.items.filterIsInstance() - } - 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() - } - - 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() - } -} \ 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 deleted file mode 100644 index d67847aa0a..0000000000 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/common/OrganiseTokensListStateOperations.kt +++ /dev/null @@ -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) -> List, -): 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) -> List, -): OrganizeTokensListUM { - val updatedItems = update(items).toPersistentList() - - return when (this) { - is OrganizeTokensListUM.AccountList -> copy(items = updatedItems) - is OrganizeTokensListUM.TokensList -> copy(items = updatedItems) - OrganizeTokensListUM.EmptyList -> this - } -} \ 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 deleted file mode 100644 index d561e3b262..0000000000 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/TokenListToStateConverter.kt +++ /dev/null @@ -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, - 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 == TokensSortType.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/items/CryptoCurrencyToDraggableItemConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt deleted file mode 100644 index 79ea585f1d..0000000000 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/CryptoCurrencyToDraggableItemConverter.kt +++ /dev/null @@ -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, -) : Converter { - - private val iconStateConverter = CryptoCurrencyToIconStateConverter() - - 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 = 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) } - } -} \ 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 deleted file mode 100644 index 73ecfe3f79..0000000000 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/NetworkGroupToDraggableItemsConverter.kt +++ /dev/null @@ -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> { - - 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), - networkName = group.network.name, - ) - - private fun createTokens(group: NetworkGroup): List { - return itemConverter.convertList(group.currencies) - } -} \ 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 deleted file mode 100644 index 770d63c0f4..0000000000 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/converter/items/TokenListToListStateConverter.kt +++ /dev/null @@ -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 { - - 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, - ) - } - - private fun createEmptyListState(): OrganizeTokensListState.Empty { - return OrganizeTokensListState.Empty - } -} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/dnd/DragAndDropAdapter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/dnd/DragAndDropAdapter.kt deleted file mode 100644 index 7158aa1260..0000000000 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/organizetokens/utils/dnd/DragAndDropAdapter.kt +++ /dev/null @@ -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, -) : DragAndDropIntents { - - private val draggableGroupsOperations = DraggableGroupsOperations() - - private val externalListState: OrganizeTokensListState - get() = listStateProvider.invoke() - - private val dragAndDropUpdatesInternal: MutableStateFlow = MutableStateFlow(value = null) - - private var draggingItem: DraggableItem? = null - private var draggingListState: OrganizeTokensListState? = null - - val dragAndDropUpdates: Flow - 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) { - val updatedState = externalListState.updateItems { block(externalListState) } - - dragAndDropUpdatesInternal.value = DragOperation(type, updatedState) - } - - private fun findItemsToMove( - items: List, - moveOverItemKey: Any?, - movedItemKey: Any?, - ): Pair { - 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? = 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() - } - } -} \ No newline at end of file