Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-26 18:26:31 +03:00
parent c215778788
commit d1c77b00cf
14 changed files with 44 additions and 85 deletions

View file

@ -19,20 +19,20 @@ class ToggleTokenListGroupingUseCase(
suspend operator fun invoke(tokenList: TokenList): Either<TokenListSortingError, TokenList> {
return withContext(dispatchers.default) {
either {
ensure(tokenList.totalFiatBalance !is TokenList.FiatBalance.Loading) {
TokenListSortingError.TokenListIsLoading
}
when (tokenList) {
is TokenList.GroupedByNetwork -> ungroupTokens(tokenList)
is TokenList.Ungrouped -> groupTokens(tokenList)
is TokenList.NotInitialized -> raise(TokenListSortingError.TokenListIsEmpty)
is TokenList.Empty -> raise(TokenListSortingError.TokenListIsEmpty)
}
}
}
}
private fun Raise<TokenListSortingError>.groupTokens(tokenList: TokenList.Ungrouped): TokenList.GroupedByNetwork {
ensure(tokenList.totalFiatBalance !is TokenList.FiatBalance.Loading) {
TokenListSortingError.TokenListIsLoading
}
val sortingOperations = TokenListSortingOperations(tokenList)
return TokenList.GroupedByNetwork(
@ -47,6 +47,10 @@ class ToggleTokenListGroupingUseCase(
private fun Raise<TokenListSortingError>.ungroupTokens(
tokenList: TokenList.GroupedByNetwork,
): TokenList.Ungrouped {
ensure(tokenList.totalFiatBalance !is TokenList.FiatBalance.Loading) {
TokenListSortingError.TokenListIsLoading
}
val sortingOperations = TokenListSortingOperations(tokenList)
return TokenList.Ungrouped(

View file

@ -19,14 +19,10 @@ class ToggleTokenListSortingUseCase(
suspend operator fun invoke(tokenList: TokenList): Either<TokenListSortingError, TokenList> {
return withContext(dispatchers.default) {
either {
ensure(tokenList.totalFiatBalance !is TokenList.FiatBalance.Loading) {
TokenListSortingError.TokenListIsLoading
}
when (tokenList) {
is TokenList.GroupedByNetwork -> sortGroupedTokenList(tokenList)
is TokenList.Ungrouped -> sortUngroupedTokenList(tokenList)
is TokenList.NotInitialized -> raise(TokenListSortingError.TokenListIsEmpty)
is TokenList.Empty -> raise(TokenListSortingError.TokenListIsEmpty)
}
}
}
@ -35,6 +31,10 @@ class ToggleTokenListSortingUseCase(
private fun Raise<TokenListSortingError>.sortGroupedTokenList(
tokenList: TokenList.GroupedByNetwork,
): TokenList.GroupedByNetwork {
ensure(tokenList.totalFiatBalance !is TokenList.FiatBalance.Loading) {
TokenListSortingError.TokenListIsLoading
}
val operations = getSortingOperations(tokenList)
return tokenList.copy(
@ -48,6 +48,10 @@ class ToggleTokenListSortingUseCase(
private fun Raise<TokenListSortingError>.sortUngroupedTokenList(
tokenList: TokenList.Ungrouped,
): TokenList.Ungrouped {
ensure(tokenList.totalFiatBalance !is TokenList.FiatBalance.Loading) {
TokenListSortingError.TokenListIsLoading
}
val operations = getSortingOperations(tokenList)
return tokenList.copy(

View file

@ -41,8 +41,14 @@ sealed class TokenList {
override val sortedBy: SortType,
) : TokenList()
/** Represents a state where the token list is not initialized. */
object NotInitialized : TokenList()
/** Represents a state where the token list is empty. */
object Empty : TokenList() {
override val totalFiatBalance: FiatBalance = FiatBalance.Loaded(
amount = BigDecimal.ZERO,
isAllAmountsSummarized = true,
)
}
/** Defines the possible sorting criteria for the tokens. */
enum class SortType {

View file

@ -41,7 +41,7 @@ internal class TokenListOperations(
private fun Raise<Error>.createTokenList(isGrouped: Boolean, isSortedByBalance: Boolean): TokenList {
val nonEmptyCurrencies = tokens.toNonEmptyListOrNull()
?: return TokenList.NotInitialized
?: return TokenList.Empty
val isAnyTokenLoading = nonEmptyCurrencies.any { it.value is CryptoCurrencyStatus.Loading }
val fiatBalanceOperations = TokenListFiatBalanceOperations(nonEmptyCurrencies, isAnyTokenLoading)

View file

@ -27,7 +27,7 @@ internal class TokenListSortingOperations(
currencies = when (tokenList) {
is TokenList.GroupedByNetwork -> tokenList.groups.flatMap { it.currencies }
is TokenList.Ungrouped -> tokenList.currencies
is TokenList.NotInitialized -> emptyList()
is TokenList.Empty -> emptyList()
},
isAnyTokenLoading = isAnyTokenLoading,
sortByBalance = sortByBalance,

View file

@ -205,7 +205,7 @@ internal class GetTokenListUseCaseTest {
@Test
fun `when tokens is empty then not initialized token list should be received`() = runTest {
val expectedResult = MockTokenLists.notInitializedTokenList.right()
val expectedResult = MockTokenLists.emptyTokenList.right()
val useCase = getUseCase(tokens = flowOf(emptyList<CryptoCurrency>().right()))

View file

@ -12,21 +12,7 @@ import org.junit.Test
internal class ToggleTokenListGroupingTest {
@Test
fun `when grouped list is empty then error should be received`() = runTest {
// Given
val expectedResult = TokenListSortingError.TokenListIsEmpty.left()
val useCase = getUseCase()
// When
val result = useCase(MockTokenLists.emptyGroupedTokenList)
// Then
assertEquals(expectedResult, result)
}
@Test
fun `when ungrouped list is empty then error should be received`() = runTest {
fun `when list is empty then error should be received`() = runTest {
// Given
val expectedResult = TokenListSortingError.TokenListIsEmpty.left()
@ -67,20 +53,6 @@ internal class ToggleTokenListGroupingTest {
assertEquals(expectedResult, result)
}
@Test
fun `when list is not initialized then error should be received`() = runTest {
// Given
val expectedResult = TokenListSortingError.TokenListIsLoading.left()
val useCase = getUseCase()
// When
val result = useCase(MockTokenLists.notInitializedTokenList)
// Then
assertEquals(expectedResult, result)
}
@Test
fun `when list is ungrouped and sorted then sorted grouped list should be received`() = runTest {
// Given

View file

@ -12,42 +12,14 @@ import org.junit.Test
internal class ToggleTokenListSortingUseCaseTest {
@Test
fun `when grouped list is not initialized then error should be received`() = runTest {
// Given
val expectedResult = TokenListSortingError.TokenListIsLoading.left()
val useCase = getUseCase()
// When
val result = useCase(MockTokenLists.notInitializedTokenList)
// Then
assertEquals(expectedResult, result)
}
@Test
fun `when grouped list is empty then error should be received`() = runTest {
fun `when list is empty then error should be received`() = runTest {
// Given
val expectedResult = TokenListSortingError.TokenListIsEmpty.left()
val useCase = getUseCase()
// When
val result = useCase(MockTokenLists.emptyGroupedTokenList)
// Then
assertEquals(expectedResult, result)
}
@Test
fun `when ungrouped list is empty then error should be received`() = runTest {
// Given
val expectedResult = TokenListSortingError.TokenListIsEmpty.left()
val useCase = getUseCase()
// When
val result = useCase(MockTokenLists.emptyUngroupedTokenList)
val result = useCase(MockTokenLists.emptyTokenList)
// Then
assertEquals(expectedResult, result)

View file

@ -15,7 +15,7 @@ internal object MockTokenLists {
const val isGrouped = false
const val isSortedByBalance = false
val notInitializedTokenList = TokenList.NotInitialized
val emptyTokenList = TokenList.Empty
val emptyGroupedTokenList = TokenList.GroupedByNetwork(
groups = emptyList(),

View file

@ -16,7 +16,7 @@ internal class CryptoCurrenciesIdsResolver {
val currenciesStatuses = when (tokenList) {
is TokenList.GroupedByNetwork -> tokenList.groups.flatMap { it.currencies }
is TokenList.Ungrouped -> tokenList.currencies
is TokenList.NotInitialized,
is TokenList.Empty,
null,
-> return emptyList()
}

View file

@ -7,6 +7,6 @@ internal fun TokenList.disableSortingByBalance(): TokenList {
return when (this) {
is TokenList.GroupedByNetwork -> this.copy(sortedBy = SortType.NONE)
is TokenList.Ungrouped -> this.copy(sortedBy = SortType.NONE)
is TokenList.NotInitialized -> this
is TokenList.Empty -> this
}
}

View file

@ -17,7 +17,7 @@ internal class TokenListToListStateConverter(
return when (value) {
is TokenList.GroupedByNetwork -> createListState(value)
is TokenList.Ungrouped -> createListState(value)
is TokenList.NotInitialized -> createEmptyListState()
is TokenList.Empty -> createEmptyListState()
}
}

View file

@ -29,7 +29,7 @@ internal class TokenListToContentItemsConverter(
override fun convert(value: TokenList): WalletTokensListState {
return when (value) {
is TokenList.NotInitialized -> WalletTokensListState.Loading()
is TokenList.Empty -> WalletTokensListState.Empty
is TokenList.GroupedByNetwork -> WalletTokensListState.Content(
items = value.mapToMultiCurrencyItems(),
organizeTokensButton = value.mapToOrganizeTokensButtonState(),

View file

@ -241,7 +241,7 @@ internal class WalletViewModel @Inject constructor(
if (cacheState != null) {
uiState = stateFactory.getStateWithoutDeletedWallet(cacheState, action)
if (cacheState.isLoadingState()) {
if (cacheState.isLoadingOrEmptyState()) {
uiState = stateFactory.getStateAndTriggerEvent(
state = uiState,
event = WalletEvent.ChangeWallet(action.selectedWalletIndex),
@ -509,7 +509,7 @@ internal class WalletViewModel @Inject constructor(
pullToRefreshConfig = cacheState.pullToRefreshConfig.copy(isRefreshing = false),
)
if (cacheState.isLoadingState()) {
if (cacheState.isLoadingOrEmptyState()) {
getContentItemsUpdates(index)
}
} else {
@ -904,7 +904,7 @@ internal class WalletViewModel @Inject constructor(
.hasNonZeroWallets()
}
is TokenList.Ungrouped -> tokenList.currencies.hasNonZeroWallets()
TokenList.NotInitialized -> false
is TokenList.Empty -> false
}
if (hasNonZeroWallets) {
@ -984,7 +984,7 @@ internal class WalletViewModel @Inject constructor(
.flatMap(NetworkGroup::currencies)
}
is TokenList.Ungrouped -> tokenList.currencies
is TokenList.NotInitialized -> emptyList()
is TokenList.Empty -> emptyList()
}
} else {
listOfNotNull(singleWalletCryptoCurrencyStatus)
@ -1033,7 +1033,7 @@ internal class WalletViewModel @Inject constructor(
)
}
private fun WalletState.isLoadingState(): Boolean {
private fun WalletState.isLoadingOrEmptyState(): Boolean {
// Check the base components
if (this is WalletState.ContentState &&
walletsListConfig.wallets[walletsListConfig.selectedWalletIndex] is WalletCardState.Loading
@ -1044,12 +1044,13 @@ internal class WalletViewModel @Inject constructor(
// Check the special components
return when (this) {
is WalletMultiCurrencyState -> {
val isTokensEmpty = tokensListState is WalletTokensListState.Empty
val hasLoadingTokens = tokensListState is WalletTokensListState.ContentState &&
(tokensListState as WalletTokensListState.ContentState).items
.filterIsInstance<WalletTokensListState.TokensListItemState.Token>()
.any { it.state is TokenItemState.Loading }
tokensListState is WalletTokensListState.Loading || hasLoadingTokens
isTokensEmpty || tokensListState is WalletTokensListState.Loading || hasLoadingTokens
}
is WalletSingleCurrencyState -> {
this is WalletSingleCurrencyState.Content && marketPriceBlockState is MarketPriceBlockState.Loading