From f65dcebf65d048c89612ec4798951ed08f443260 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 8 Feb 2024 11:38:02 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../ui/components/transactions/Transaction.kt | 55 +++++++-- .../transactions/state/TransactionState.kt | 3 +- .../TokenDetailsLoadedBalanceConverter.kt | 4 +- ...ilsPendingTxToTransactionStateConverter.kt | 109 ------------------ .../TokenDetailsTxHistoryItemFlowConverter.kt | 24 +--- ...tailsTxHistoryTransactionStateConverter.kt | 14 +-- .../presentation/common/WalletPreviewData.kt | 6 +- .../implementors/VisaWalletContentLoader.kt | 28 ++--- .../VisaWalletContentLoaderFactory.kt | 15 +-- .../WalletLoadingTxHistoryConverter.kt | 2 +- ...letPendingTxToTransactionStateConverter.kt | 109 ------------------ .../WalletTxHistoryItemFlowConverter.kt | 27 +---- ...alletTxHistoryTransactionStateConverter.kt | 14 +-- .../SetBalancesAndLimitsTransformer.kt | 2 + .../SetTxHistoryItemsTransformer.kt | 7 +- .../converter/TxHistoryItemFlowConverter.kt | 51 ++------ .../converter/TxHistoryItemStateConverter.kt | 14 +-- .../VisaTxHistoryItemStateConverter.kt | 46 ++++++++ .../wallet/subscribers/TxHistorySubscriber.kt | 41 +++---- .../VisaWalletBalancesAndLimitsSubscriber.kt | 32 ----- .../subscribers/VisaWalletSubscriber.kt | 105 +++++++++++++++++ .../presentation/wallet/ui/WalletScreenV2.kt | 3 +- .../viewmodels/intents/VisaWalletIntents.kt | 6 + 23 files changed, 267 insertions(+), 450 deletions(-) delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsPendingTxToTransactionStateConverter.kt delete mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletPendingTxToTransactionStateConverter.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/VisaTxHistoryItemStateConverter.kt delete mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/VisaWalletBalancesAndLimitsSubscriber.kt create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/VisaWalletSubscriber.kt diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt index 3e863a35f6..180acd8a31 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/Transaction.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider @@ -30,6 +31,7 @@ import com.tangem.core.ui.components.transactions.state.TransactionState.Content import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.res.TangemTheme import java.util.UUID @@ -46,6 +48,7 @@ import java.util.UUID [REDACTED_AUTHOR] */ @Composable +@Suppress("LongMethod") fun Transaction(state: TransactionState, isBalanceHidden: Boolean, modifier: Modifier = Modifier) { Surface( modifier = modifier @@ -76,10 +79,15 @@ fun Transaction(state: TransactionState, isBalanceHidden: Boolean, modifier: Mod Title( state = state, modifier = Modifier - .padding(horizontal = TangemTheme.dimens.spacing12) + .padding( + start = TangemTheme.dimens.spacing12, + end = TangemTheme.dimens.spacing6, + ) .constrainAs(titleItem) { start.linkTo(iconItem.end) + end.linkTo(amountItem.start) top.linkTo(iconItem.top) + width = Dimension.fillToConstraints }, ) @@ -173,11 +181,16 @@ private fun Icon(state: TransactionState, modifier: Modifier = Modifier) { private fun Title(state: TransactionState, modifier: Modifier = Modifier) { when (state) { is TransactionState.Content -> { - Row(modifier = modifier, horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing6)) { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing6), + ) { Text( text = state.title.resolveReference(), color = TangemTheme.colors.text.primary1, style = TangemTheme.typography.subtitle2, + overflow = TextOverflow.Ellipsis, + maxLines = 1, ) if (state.status is Status.Unconfirmed) { @@ -266,7 +279,7 @@ private fun Timestamp(state: TransactionState, modifier: Modifier = Modifier) { when (state) { is TransactionState.Content -> { Text( - text = state.timestamp, + text = state.time, modifier = modifier, textAlign = TextAlign.End, color = TangemTheme.colors.text.tertiary, @@ -321,89 +334,109 @@ private class TransactionItemStateProvider : CollectionPreviewParameterProvider< TransactionState.Content( txHash = UUID.randomUUID().toString(), amount = "-0.500913 BTC", - timestamp = "8:41", + time = "8:41", status = Status.Confirmed, direction = Direction.OUTGOING, iconRes = R.drawable.ic_arrow_up_24, title = resourceReference(R.string.common_transfer), subtitle = TextReference.Str("33BddS...ga2B"), + timestamp = 0L, onClick = {}, ), TransactionState.Content( txHash = UUID.randomUUID().toString(), amount = "+0.500913 BTC", - timestamp = "8:41", + time = "8:41", status = Status.Unconfirmed, direction = Direction.INCOMING, iconRes = R.drawable.ic_arrow_down_24, title = resourceReference(R.string.common_transfer), subtitle = TextReference.Str("33BddS...ga2B"), + timestamp = 0L, onClick = {}, ), TransactionState.Content( txHash = UUID.randomUUID().toString(), amount = "+0.500913 BTC", - timestamp = "8:41", + time = "8:41", status = Status.Unconfirmed, direction = Direction.OUTGOING, iconRes = R.drawable.ic_doc_24, title = resourceReference(R.string.common_approval), subtitle = TextReference.Str("33BddS...ga2B"), + timestamp = 0L, onClick = {}, ), TransactionState.Content( txHash = UUID.randomUUID().toString(), amount = "+0.500913 BTC", - timestamp = "8:41", + time = "8:41", status = Status.Failed, direction = Direction.OUTGOING, iconRes = R.drawable.ic_doc_24, title = resourceReference(R.string.common_approval), subtitle = TextReference.Str("33BddS...ga2B"), + timestamp = 0L, onClick = {}, ), TransactionState.Content( txHash = UUID.randomUUID().toString(), amount = "+0.500913 BTC", - timestamp = "8:41", + time = "8:41", status = Status.Confirmed, direction = Direction.OUTGOING, iconRes = R.drawable.ic_doc_24, title = resourceReference(R.string.common_approval), subtitle = TextReference.Str("33BddS...ga2B"), + timestamp = 0L, onClick = {}, ), TransactionState.Content( txHash = UUID.randomUUID().toString(), amount = "+0.500913 BTC", - timestamp = "8:41", + time = "8:41", status = Status.Unconfirmed, direction = Direction.INCOMING, iconRes = R.drawable.ic_arrow_down_24, title = resourceReference(R.string.common_swap), subtitle = TextReference.Str("33BddS...ga2B"), + timestamp = 0L, onClick = {}, ), TransactionState.Content( txHash = UUID.randomUUID().toString(), amount = "+0.500913 BTC", - timestamp = "8:41", + time = "8:41", status = Status.Confirmed, direction = Direction.INCOMING, iconRes = R.drawable.ic_doc_24, title = TextReference.Str("Submit"), subtitle = TextReference.Str("33BddS...ga2B"), + timestamp = 0L, onClick = {}, ), TransactionState.Content( txHash = UUID.randomUUID().toString(), amount = "+0.500913 BTC", - timestamp = "8:41", + time = "8:41", status = Status.Confirmed, direction = Direction.OUTGOING, iconRes = R.drawable.ic_arrow_up_24, title = TextReference.Str("Submit"), subtitle = TextReference.Str("33BddS...ga2B"), + timestamp = 0L, + onClick = {}, + ), + TransactionState.Content( + txHash = UUID.randomUUID().toString(), + amount = "0.625 USDT", + time = "€0.50", + status = Status.Confirmed, + direction = Direction.OUTGOING, + iconRes = R.drawable.ic_arrow_up_24, + title = TextReference.Str("Unlimint Banking Cards Sandbox London"), + subtitle = stringReference(value = "8:41 • authorized"), + timestamp = 0L, onClick = {}, ), TransactionState.Loading(txHash = UUID.randomUUID().toString()), diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/transactions/state/TransactionState.kt b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/state/TransactionState.kt index c18e43f28e..7df1982a29 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/transactions/state/TransactionState.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/transactions/state/TransactionState.kt @@ -25,13 +25,14 @@ sealed interface TransactionState { data class Content( override val txHash: String, val amount: String, - val timestamp: String, + val time: String, val status: Status, val direction: Direction, val onClick: () -> Unit, @DrawableRes val iconRes: Int, val title: TextReference, val subtitle: TextReference, + val timestamp: Long, ) : TransactionState { sealed class Status { diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt index 142947657c..e8c09263eb 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt @@ -12,7 +12,7 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsBalanceBlockState import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification -import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsPendingTxToTransactionStateConverter +import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsTxHistoryTransactionStateConverter import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents import com.tangem.utils.Provider import com.tangem.utils.converter.Converter @@ -29,7 +29,7 @@ internal class TokenDetailsLoadedBalanceConverter( ) : Converter, TokenDetailsState> { private val txHistoryItemConverter by lazy { - TokenDetailsPendingTxToTransactionStateConverter(symbol, decimals, clickIntents) + TokenDetailsTxHistoryTransactionStateConverter(symbol, decimals, clickIntents) } override fun convert(value: Either): TokenDetailsState { diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsPendingTxToTransactionStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsPendingTxToTransactionStateConverter.kt deleted file mode 100644 index 6ba156961c..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsPendingTxToTransactionStateConverter.kt +++ /dev/null @@ -1,109 +0,0 @@ -package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory - -import com.tangem.core.ui.components.transactions.state.TransactionState -import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringReference -import com.tangem.core.ui.extensions.wrappedList -import com.tangem.core.ui.utils.DateTimeFormatters -import com.tangem.domain.txhistory.models.TxHistoryItem -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents -import com.tangem.features.tokendetails.impl.R -import com.tangem.utils.converter.Converter -import com.tangem.utils.toBriefAddressFormat -import com.tangem.utils.toFormattedCurrencyString -import org.joda.time.DateTime -import org.joda.time.DateTimeZone - -// FIXME: Refactoring needed -/** Same as [TokenDetailsTxHistoryTransactionStateConverter] but with other timestamp format */ -internal class TokenDetailsPendingTxToTransactionStateConverter( - private val symbol: String, - private val decimals: Int, - private val clickIntents: TokenDetailsClickIntents, -) : Converter { - - override fun convert(value: TxHistoryItem): TransactionState { - return createTransactionStateItem(item = value) - } - - private fun createTransactionStateItem(item: TxHistoryItem): TransactionState { - return TransactionState.Content( - txHash = item.txHash, - amount = item.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.extractDirection(), - iconRes = item.extractIcon(), - title = item.extractTitle(), - subtitle = item.extractSubtitle(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - } - - private fun TxHistoryItem.extractIcon(): Int = if (status == TxHistoryItem.TransactionStatus.Failed) { - R.drawable.ic_close_24 - } else { - when (type) { - is TxHistoryItem.TransactionType.Approve -> R.drawable.ic_doc_24 - is TxHistoryItem.TransactionType.Operation, - is TxHistoryItem.TransactionType.Swap, - is TxHistoryItem.TransactionType.Transfer, - is TxHistoryItem.TransactionType.UnknownOperation, - -> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24 - } - } - - private fun TxHistoryItem.extractTitle(): TextReference = when (val type = type) { - is TxHistoryItem.TransactionType.Approve -> resourceReference(R.string.common_approval) - is TxHistoryItem.TransactionType.Operation -> stringReference(type.name) - is TxHistoryItem.TransactionType.Swap -> resourceReference(R.string.common_swap) - is TxHistoryItem.TransactionType.Transfer -> resourceReference(R.string.common_transfer) - is TxHistoryItem.TransactionType.UnknownOperation -> resourceReference(R.string.transaction_history_operation) - } - - private fun TxHistoryItem.extractSubtitle(): TextReference = - when (val interactionAddress = interactionAddressType) { - is TxHistoryItem.InteractionAddressType.Contract -> resourceReference( - id = R.string.transaction_history_contract_address, - formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), - ) - is TxHistoryItem.InteractionAddressType.Multiple -> resourceReference( - id = if (isOutgoing) { - R.string.transaction_history_transaction_to_address - } else { - R.string.transaction_history_transaction_from_address - }, - formatArgs = wrappedList(resourceReference(R.string.transaction_history_multiple_addresses)), - ) - is TxHistoryItem.InteractionAddressType.User -> resourceReference( - id = if (isOutgoing) { - R.string.transaction_history_transaction_to_address - } else { - R.string.transaction_history_transaction_from_address - }, - formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), - ) - } - - private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) { - TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed - TxHistoryItem.TransactionStatus.Failed -> TransactionState.Content.Status.Failed - TxHistoryItem.TransactionStatus.Unconfirmed -> TransactionState.Content.Status.Unconfirmed - } - - private fun Long.toTimeFormat(): String { - return DateTimeFormatters.formatTime(time = DateTime(this, DateTimeZone.getDefault())) - } - - private fun TxHistoryItem.extractDirection() = - if (isOutgoing) TransactionState.Content.Direction.OUTGOING else TransactionState.Content.Direction.INCOMING - - private fun TxHistoryItem.getAmount(): String { - val prefix = when (status) { - TxHistoryItem.TransactionStatus.Failed -> "" - else -> if (isOutgoing) "-" else "+" - } - return prefix + amount.toFormattedCurrencyString(currency = symbol, decimals = decimals) - } -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt index 56ae213609..9fb6df70b1 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryItemFlowConverter.kt @@ -5,7 +5,6 @@ import com.tangem.core.ui.components.transactions.state.TransactionState import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.core.ui.components.transactions.state.TxHistoryState.TxHistoryItemState import com.tangem.core.ui.utils.toDateFormat -import com.tangem.core.ui.utils.toTimeFormat import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents @@ -52,8 +51,7 @@ internal class TokenDetailsTxHistoryItemFlowConverter( terminalSeparatorType = TerminalSeparatorType.SOURCE_COMPLETE, item = TxHistoryItemState.Title(clickIntents::onExploreClick), ) - .insertGroupTitle() // method uses the raw timestamp - .formatTransactionsTimestamp() // method formats the timestamp + .insertGroupTitle() } } .launchIn(CoroutineScope(Dispatchers.IO)) @@ -94,28 +92,10 @@ internal class TokenDetailsTxHistoryItemFlowConverter( } } - /** - * Map the [PagingData] to format the [TxHistoryItemState] timestamp - */ - private fun PagingData.formatTransactionsTimestamp(): PagingData { - return map { txHistoryItemState -> - if (txHistoryItemState is TxHistoryItemState.Transaction && - txHistoryItemState.state is TransactionState.Content - ) { - val txContent = txHistoryItemState.state as TransactionState.Content - txHistoryItemState.copy( - state = txContent.copy(timestamp = txContent.timestamp.toLong().toTimeFormat()), - ) - } else { - txHistoryItemState - } - } - } - private fun TxHistoryItemState?.getTimestamp(): Long? { return if (this is TxHistoryItemState.Transaction && this.state is TransactionState.Content) { val txContent = this.state as TransactionState.Content - requireNotNull(txContent.timestamp.toLongOrNull()) { "Timestamp must be Long type" } + txContent.timestamp } else { null } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt index 22d68befc8..1e2ab2341d 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/txhistory/TokenDetailsTxHistoryTransactionStateConverter.kt @@ -6,6 +6,7 @@ import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.utils.toTimeFormat import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R @@ -13,8 +14,6 @@ import com.tangem.utils.converter.Converter import com.tangem.utils.toBriefAddressFormat import com.tangem.utils.toFormattedCurrencyString -// FIXME: Refactoring needed -/** Same as [TokenDetailsPendingTxToTransactionStateConverter] but with other timestamp format */ internal class TokenDetailsTxHistoryTransactionStateConverter( private val symbol: String, private val decimals: Int, @@ -30,12 +29,13 @@ internal class TokenDetailsTxHistoryTransactionStateConverter( return TransactionState.Content( txHash = item.txHash, amount = item.getAmount(), - timestamp = item.getRawTimestamp(), + time = item.timestampInMillis.toTimeFormat(), status = item.status.tiUiStatus(), direction = item.extractDirection(), iconRes = item.extractIcon(), title = item.extractTitle(), subtitle = item.extractSubtitle(), + timestamp = item.timestampInMillis, onClick = { clickIntents.onTransactionClick(item.txHash) }, ) } @@ -87,14 +87,6 @@ internal class TokenDetailsTxHistoryTransactionStateConverter( private fun TxHistoryItem.extractDirection() = if (isOutgoing) Direction.OUTGOING else Direction.INCOMING - /** - * Get timestamp without formatting. - * It's life hack that help us to add transaction's group title to flow. - * - * @see [convert] - */ - private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString() - private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) { TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed TxHistoryItem.TransactionStatus.Failed -> TransactionState.Content.Status.Failed 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 9ffd482c85..727545a58c 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 @@ -426,12 +426,13 @@ internal object WalletPreviewData { TransactionState.Content( txHash = UUID.randomUUID().toString(), amount = "-0.500913 BTC", - timestamp = "8:41", + time = "8:41", status = TransactionState.Content.Status.Unconfirmed, direction = TransactionState.Content.Direction.OUTGOING, iconRes = com.tangem.core.ui.R.drawable.ic_arrow_up_24, title = resourceReference(com.tangem.core.ui.R.string.common_transfer), subtitle = TextReference.Str("33BddS...ga2B"), + timestamp = 0L, onClick = {}, ), ), @@ -443,12 +444,13 @@ internal object WalletPreviewData { TransactionState.Content( txHash = UUID.randomUUID().toString(), amount = "-0.500913 BTC", - timestamp = "8:41", + time = "8:41", status = TransactionState.Content.Status.Confirmed, direction = TransactionState.Content.Direction.OUTGOING, iconRes = com.tangem.core.ui.R.drawable.ic_arrow_up_24, title = resourceReference(com.tangem.core.ui.R.string.common_transfer), subtitle = TextReference.Str("33BddS...ga2B"), + timestamp = 0L, onClick = {}, ), ), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/VisaWalletContentLoader.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/VisaWalletContentLoader.kt index 7d41dcb257..990533203a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/VisaWalletContentLoader.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/VisaWalletContentLoader.kt @@ -1,46 +1,32 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase -import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase -import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.visa.GetVisaCurrencyUseCase +import com.tangem.domain.visa.GetVisaTxHistoryUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.state2.WalletStateController -import com.tangem.feature.wallet.presentation.wallet.subscribers.TxHistorySubscriber -import com.tangem.feature.wallet.presentation.wallet.subscribers.VisaWalletBalancesAndLimitsSubscriber +import com.tangem.feature.wallet.presentation.wallet.subscribers.VisaWalletSubscriber import com.tangem.feature.wallet.presentation.wallet.subscribers.WalletSubscriber import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntentsV2 -@Suppress("LongParameterList") internal class VisaWalletContentLoader( private val userWallet: UserWallet, private val clickIntents: WalletClickIntentsV2, private val isRefresh: Boolean, - private val stateHolder: WalletStateController, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, - private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase, - private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase, + private val stateController: WalletStateController, + private val getVisaTxHistoryUseCase: GetVisaTxHistoryUseCase, private val getVisaCurrencyUseCase: GetVisaCurrencyUseCase, ) : WalletContentLoader(id = userWallet.walletId) { override fun create(): List { return listOf( - VisaWalletBalancesAndLimitsSubscriber( + VisaWalletSubscriber( userWallet = userWallet, - stateHolder = stateHolder, + stateController = stateController, isRefresh = isRefresh, getVisaCurrencyUseCase = getVisaCurrencyUseCase, + getVisaTxHistoryUseCase = getVisaTxHistoryUseCase, clickIntents = clickIntents, ), - TxHistorySubscriber( - userWallet = userWallet, - isRefresh = isRefresh, - stateHolder = stateHolder, - clickIntents = clickIntents, - getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase, - txHistoryItemsCountUseCase = txHistoryItemsCountUseCase, - txHistoryItemsUseCase = txHistoryItemsUseCase, - ), ) } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/VisaWalletContentLoaderFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/VisaWalletContentLoaderFactory.kt index e81f30afff..1d00369116 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/VisaWalletContentLoaderFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/loaders/implementors/VisaWalletContentLoaderFactory.kt @@ -1,9 +1,7 @@ package com.tangem.feature.wallet.presentation.wallet.loaders.implementors -import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase -import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase -import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.visa.GetVisaCurrencyUseCase +import com.tangem.domain.visa.GetVisaTxHistoryUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.state2.WalletStateController import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntentsV2 @@ -11,13 +9,10 @@ import dagger.hilt.android.scopes.ViewModelScoped import javax.inject.Inject @ViewModelScoped -@Suppress("LongParameterList") internal class VisaWalletContentLoaderFactory @Inject constructor( private val stateHolder: WalletStateController, - private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase, - private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase, - private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase, private val getVisaCurrencyUseCase: GetVisaCurrencyUseCase, + private val getVisaTxHistoryUseCase: GetVisaTxHistoryUseCase, ) { fun create(userWallet: UserWallet, clickIntents: WalletClickIntentsV2, isRefresh: Boolean): WalletContentLoader { @@ -25,11 +20,9 @@ internal class VisaWalletContentLoaderFactory @Inject constructor( userWallet = userWallet, clickIntents = clickIntents, isRefresh = isRefresh, - stateHolder = stateHolder, - getPrimaryCurrencyStatusUpdatesUseCase = getPrimaryCurrencyStatusUpdatesUseCase, - txHistoryItemsCountUseCase = txHistoryItemsCountUseCase, - txHistoryItemsUseCase = txHistoryItemsUseCase, + stateController = stateHolder, getVisaCurrencyUseCase = getVisaCurrencyUseCase, + getVisaTxHistoryUseCase = getVisaTxHistoryUseCase, ) } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletLoadingTxHistoryConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletLoadingTxHistoryConverter.kt index ff688613a4..3f4b843c86 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletLoadingTxHistoryConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletLoadingTxHistoryConverter.kt @@ -32,7 +32,7 @@ internal class WalletLoadingTxHistoryConverter( private val txHistoryItemConverter by lazy { val blockchain = currentCardTypeResolverProvider().getBlockchain() - WalletPendingTxToTransactionStateConverter( + WalletTxHistoryTransactionStateConverter( symbol = blockchain.currency, decimals = blockchain.decimals(), clickIntents = clickIntents, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletPendingTxToTransactionStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletPendingTxToTransactionStateConverter.kt deleted file mode 100644 index a3d2cfa92e..0000000000 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletPendingTxToTransactionStateConverter.kt +++ /dev/null @@ -1,109 +0,0 @@ -package com.tangem.feature.wallet.presentation.wallet.state.factory.txhistory - -import com.tangem.core.ui.components.transactions.state.TransactionState -import com.tangem.core.ui.extensions.TextReference -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.stringReference -import com.tangem.core.ui.extensions.wrappedList -import com.tangem.core.ui.utils.DateTimeFormatters -import com.tangem.domain.txhistory.models.TxHistoryItem -import com.tangem.feature.wallet.impl.R -import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents -import com.tangem.utils.converter.Converter -import com.tangem.utils.toBriefAddressFormat -import com.tangem.utils.toFormattedCurrencyString -import org.joda.time.DateTime -import org.joda.time.DateTimeZone - -// FIXME: Refactoring needed -/** Same as [WalletTxHistoryTransactionStateConverter] but with other timestamp format */ -internal class WalletPendingTxToTransactionStateConverter( - private val symbol: String, - private val decimals: Int, - private val clickIntents: WalletClickIntents, -) : Converter { - - override fun convert(value: TxHistoryItem): TransactionState { - return createTransactionStateItem(item = value) - } - - private fun createTransactionStateItem(item: TxHistoryItem): TransactionState { - return TransactionState.Content( - txHash = item.txHash, - amount = item.getAmount(), - timestamp = item.timestampInMillis.toTimeFormat(), - status = item.status.tiUiStatus(), - direction = item.extractDirection(), - iconRes = item.extractIcon(), - title = item.extractTitle(), - subtitle = item.extractSubtitle(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, - ) - } - - private fun TxHistoryItem.extractIcon(): Int = if (status == TxHistoryItem.TransactionStatus.Failed) { - R.drawable.ic_close_24 - } else { - when (type) { - is TxHistoryItem.TransactionType.Approve -> R.drawable.ic_doc_24 - is TxHistoryItem.TransactionType.Operation, - is TxHistoryItem.TransactionType.Swap, - is TxHistoryItem.TransactionType.Transfer, - is TxHistoryItem.TransactionType.UnknownOperation, - -> if (isOutgoing) R.drawable.ic_arrow_up_24 else R.drawable.ic_arrow_down_24 - } - } - - private fun TxHistoryItem.extractTitle(): TextReference = when (val type = type) { - is TxHistoryItem.TransactionType.Approve -> resourceReference(R.string.common_approval) - is TxHistoryItem.TransactionType.Operation -> stringReference(type.name) - is TxHistoryItem.TransactionType.Swap -> resourceReference(R.string.common_swap) - is TxHistoryItem.TransactionType.Transfer -> resourceReference(R.string.common_transfer) - is TxHistoryItem.TransactionType.UnknownOperation -> resourceReference(R.string.transaction_history_operation) - } - - private fun TxHistoryItem.extractSubtitle(): TextReference = - when (val interactionAddress = interactionAddressType) { - is TxHistoryItem.InteractionAddressType.Contract -> resourceReference( - id = R.string.transaction_history_contract_address, - formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), - ) - is TxHistoryItem.InteractionAddressType.Multiple -> resourceReference( - id = if (isOutgoing) { - R.string.transaction_history_transaction_to_address - } else { - R.string.transaction_history_transaction_from_address - }, - formatArgs = wrappedList(resourceReference(R.string.transaction_history_multiple_addresses)), - ) - is TxHistoryItem.InteractionAddressType.User -> resourceReference( - id = if (isOutgoing) { - R.string.transaction_history_transaction_to_address - } else { - R.string.transaction_history_transaction_from_address - }, - formatArgs = wrappedList(interactionAddress.address.toBriefAddressFormat()), - ) - } - - private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) { - TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed - TxHistoryItem.TransactionStatus.Failed -> TransactionState.Content.Status.Failed - TxHistoryItem.TransactionStatus.Unconfirmed -> TransactionState.Content.Status.Unconfirmed - } - - private fun Long.toTimeFormat(): String { - return DateTimeFormatters.formatTime(time = DateTime(this, DateTimeZone.getDefault())) - } - - private fun TxHistoryItem.extractDirection() = - if (isOutgoing) TransactionState.Content.Direction.OUTGOING else TransactionState.Content.Direction.INCOMING - - private fun TxHistoryItem.getAmount(): String { - val prefix = when (status) { - TxHistoryItem.TransactionStatus.Failed -> "" - else -> if (isOutgoing) "-" else "+" - } - return prefix + amount.toFormattedCurrencyString(currency = symbol, decimals = decimals) - } -} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryItemFlowConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryItemFlowConverter.kt index 91864cc3ae..f0ab700230 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryItemFlowConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryItemFlowConverter.kt @@ -64,8 +64,7 @@ internal class WalletTxHistoryItemFlowConverter( terminalSeparatorType = TerminalSeparatorType.SOURCE_COMPLETE, item = TxHistoryItemState.Title(clickIntents::onExploreClick), ) - .insertGroupTitle() // method uses the raw timestamp - .formatTransactionsTimestamp() // method formats the timestamp + .insertGroupTitle() } } .launchIn(CoroutineScope(Dispatchers.IO)) @@ -103,28 +102,10 @@ internal class WalletTxHistoryItemFlowConverter( } } - /** - * Map the [PagingData] to format the [TxHistoryItemState] timestamp - */ - private fun PagingData.formatTransactionsTimestamp(): PagingData { - return map { txHistoryItemState -> - if (txHistoryItemState is TxHistoryItemState.Transaction && - txHistoryItemState.state is TransactionState.Content - ) { - val txContent = txHistoryItemState.state as TransactionState.Content - txHistoryItemState.copy( - state = txContent.copy(timestamp = txContent.timestamp.toTimeFormat()), - ) - } else { - txHistoryItemState - } - } - } - private fun TxHistoryItemState?.getTimestamp(): Long? { return if (this is TxHistoryItemState.Transaction && this.state is TransactionState.Content) { val txContent = this.state as TransactionState.Content - requireNotNull(txContent.timestamp.toLongOrNull()) { "Timestamp must be Long type" } + txContent.timestamp } else { null } @@ -147,8 +128,4 @@ internal class WalletTxHistoryItemFlowConverter( DateTimeFormatters.formatDate(date = localDate) } } - - private fun String.toTimeFormat(): String { - return DateTimeFormatters.formatTime(time = DateTime(this.toLong(), DateTimeZone.getDefault())) - } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt index a7b4c8efa5..720addb22a 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/factory/txhistory/WalletTxHistoryTransactionStateConverter.kt @@ -5,6 +5,7 @@ import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.utils.toTimeFormat import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents @@ -12,8 +13,6 @@ import com.tangem.utils.converter.Converter import com.tangem.utils.toBriefAddressFormat import com.tangem.utils.toFormattedCurrencyString -// FIXME: Refactoring needed -/** Same as [WalletPendingTxToTransactionStateConverter] but with other timestamp format */ internal class WalletTxHistoryTransactionStateConverter( private val symbol: String, private val decimals: Int, @@ -29,12 +28,13 @@ internal class WalletTxHistoryTransactionStateConverter( return TransactionState.Content( txHash = item.txHash, amount = item.getAmount(), - timestamp = item.getRawTimestamp(), + time = item.timestampInMillis.toTimeFormat(), status = item.status.tiUiStatus(), direction = item.extractDirection(), iconRes = item.extractIcon(), title = item.extractTitle(), subtitle = item.extractSubtitle(), + timestamp = item.timestampInMillis, onClick = { clickIntents.onTransactionClick(item.txHash) }, ) } @@ -87,14 +87,6 @@ internal class WalletTxHistoryTransactionStateConverter( private fun TxHistoryItem.extractDirection() = if (isOutgoing) TransactionState.Content.Direction.OUTGOING else TransactionState.Content.Direction.INCOMING - /** - * Get timestamp without formatting. - * It's life hack that help us to add transaction's group title to flow. - * - * @see [convert] - */ - private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString() - private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) { TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed TxHistoryItem.TransactionStatus.Failed -> TransactionState.Content.Status.Failed diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/SetBalancesAndLimitsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/SetBalancesAndLimitsTransformer.kt index 9af5df2c08..959a6527ac 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/SetBalancesAndLimitsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/SetBalancesAndLimitsTransformer.kt @@ -26,12 +26,14 @@ internal class SetBalancesAndLimitsTransformer( val visaCurrency = maybeVisaCurrency.getOrElse { return state.copy( walletCardState = getErrorWalletCardState(state.walletCardState), + depositButtonState = state.depositButtonState.copy(isEnabled = false), balancesAndLimitBlockState = BalancesAndLimitsBlockState.Error, ) } state.copy( walletCardState = getContentWalletCardState(state.walletCardState, visaCurrency), + depositButtonState = state.depositButtonState.copy(isEnabled = true), balancesAndLimitBlockState = getContentBlockState(visaCurrency), ) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/SetTxHistoryItemsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/SetTxHistoryItemsTransformer.kt index 9a47b46770..f1001f3495 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/SetTxHistoryItemsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/SetTxHistoryItemsTransformer.kt @@ -1,8 +1,8 @@ package com.tangem.feature.wallet.presentation.wallet.state2.transformers import androidx.paging.PagingData +import com.tangem.core.ui.components.transactions.state.TransactionState import com.tangem.core.ui.components.transactions.state.TxHistoryState -import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.state2.model.WalletState import com.tangem.feature.wallet.presentation.wallet.state2.transformers.converter.TxHistoryItemFlowConverter @@ -11,8 +11,8 @@ import kotlinx.coroutines.flow.Flow import timber.log.Timber internal class SetTxHistoryItemsTransformer( - private val userWallet: UserWallet, - private val flow: Flow>, + userWallet: UserWallet, + private val flow: Flow>, private val clickIntents: WalletClickIntentsV2, ) : WalletStateTransformer(userWallet.walletId) { @@ -39,7 +39,6 @@ internal class SetTxHistoryItemsTransformer( private fun TxHistoryState.toContentState(): TxHistoryState { val converter = TxHistoryItemFlowConverter( - userWallet = userWallet, currentState = this, clickIntents = clickIntents, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/TxHistoryItemFlowConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/TxHistoryItemFlowConverter.kt index 6c642647c3..6372e43581 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/TxHistoryItemFlowConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/TxHistoryItemFlowConverter.kt @@ -5,10 +5,6 @@ import com.tangem.core.ui.components.transactions.state.TransactionState import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.core.ui.components.transactions.state.TxHistoryState.TxHistoryItemState import com.tangem.core.ui.utils.toDateFormat -import com.tangem.core.ui.utils.toTimeFormat -import com.tangem.domain.common.util.cardTypesResolver -import com.tangem.domain.txhistory.models.TxHistoryItem -import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntentsV2 import com.tangem.utils.converter.Converter import kotlinx.coroutines.CoroutineScope @@ -19,21 +15,11 @@ import java.util.UUID private val scope = CoroutineScope(Dispatchers.IO) internal class TxHistoryItemFlowConverter( - private val userWallet: UserWallet, private val currentState: TxHistoryState, private val clickIntents: WalletClickIntentsV2, -) : Converter>, TxHistoryState?> { +) : Converter>, TxHistoryState?> { - private val txHistoryItemConverter by lazy { - val blockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain() - TxHistoryItemStateConverter( - symbol = blockchain.currency, - decimals = blockchain.decimals(), - clickIntents = clickIntents, - ) - } - - override fun convert(value: Flow>): TxHistoryState { + override fun convert(value: Flow>): TxHistoryState { val txHistoryContent = currentState as? TxHistoryState.Content ?: TxHistoryState.Content(contentItems = MutableStateFlow(PagingData.empty())) @@ -43,16 +29,14 @@ internal class TxHistoryItemFlowConverter( .onEach { txHistoryStatePagingData -> txHistoryContent.contentItems.update { txHistoryStatePagingData - .map { item -> - // [createTransactionState] returns timestamp without formatting - TxHistoryItemState.Transaction(state = createTransactionState(item)) + .map { item -> + TxHistoryItemState.Transaction(item) } .insertHeaderItem( terminalSeparatorType = TerminalSeparatorType.SOURCE_COMPLETE, item = TxHistoryItemState.Title(clickIntents::onExploreClick), ) - .insertGroupTitle() // method uses the raw timestamp - .formatTransactionsTimestamp() // method formats the timestamp + .insertGroupTitle() } } .cachedIn(scope) @@ -61,10 +45,6 @@ internal class TxHistoryItemFlowConverter( return txHistoryContent } - private fun createTransactionState(item: TxHistoryItem): TransactionState { - return txHistoryItemConverter.convert(value = item) - } - private fun PagingData.insertGroupTitle(): PagingData { return insertSeparators(terminalSeparatorType = TerminalSeparatorType.SOURCE_COMPLETE) { before, after -> // Use raw timestamp to get date @@ -88,28 +68,11 @@ internal class TxHistoryItemFlowConverter( } } - /** - * Map the [PagingData] to format the [TxHistoryItemState] timestamp - */ - private fun PagingData.formatTransactionsTimestamp(): PagingData { - return map { txHistoryItemState -> - if (txHistoryItemState is TxHistoryItemState.Transaction && - txHistoryItemState.state is TransactionState.Content - ) { - val txContent = txHistoryItemState.state as TransactionState.Content - txHistoryItemState.copy( - state = txContent.copy(timestamp = txContent.timestamp.toLong().toTimeFormat()), - ) - } else { - txHistoryItemState - } - } - } - private fun TxHistoryItemState?.getTimestamp(): Long? { return if (this is TxHistoryItemState.Transaction && this.state is TransactionState.Content) { val txContent = this.state as TransactionState.Content - requireNotNull(txContent.timestamp.toLongOrNull()) { "Timestamp must be Long type" } + + txContent.timestamp } else { null } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/TxHistoryItemStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/TxHistoryItemStateConverter.kt index e9c78803f3..888144c3eb 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/TxHistoryItemStateConverter.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/TxHistoryItemStateConverter.kt @@ -5,6 +5,7 @@ import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList +import com.tangem.core.ui.utils.toTimeFormat import com.tangem.domain.txhistory.models.TxHistoryItem import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntentsV2 @@ -27,13 +28,14 @@ internal class TxHistoryItemStateConverter( return TransactionState.Content( txHash = item.txHash, amount = item.getAmount(), - timestamp = item.getRawTimestamp(), + time = item.timestampInMillis.toTimeFormat(), status = item.status.tiUiStatus(), direction = item.extractDirection(), iconRes = item.extractIcon(), title = item.extractTitle(), subtitle = item.extractSubtitle(), - onClick = { clickIntents.onTransactionClick(item.txHash) }, + timestamp = item.timestampInMillis, + onClick = { clickIntents.onVisaTransactionClick(item.txHash) }, ) } @@ -85,14 +87,6 @@ internal class TxHistoryItemStateConverter( private fun TxHistoryItem.extractDirection() = if (isOutgoing) TransactionState.Content.Direction.OUTGOING else TransactionState.Content.Direction.INCOMING - /** - * Get timestamp without formatting. - * It's life hack that help us to add transaction's group title to flow. - * - * @see [convert] - */ - private fun TxHistoryItem.getRawTimestamp() = this.timestampInMillis.toString() - private fun TxHistoryItem.TransactionStatus.tiUiStatus() = when (this) { TxHistoryItem.TransactionStatus.Confirmed -> TransactionState.Content.Status.Confirmed TxHistoryItem.TransactionStatus.Failed -> TransactionState.Content.Status.Failed diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/VisaTxHistoryItemStateConverter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/VisaTxHistoryItemStateConverter.kt new file mode 100644 index 0000000000..c1f801a339 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state2/transformers/converter/VisaTxHistoryItemStateConverter.kt @@ -0,0 +1,46 @@ +package com.tangem.feature.wallet.presentation.wallet.state2.transformers.converter + +import com.tangem.core.ui.components.transactions.state.TransactionState +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.utils.BigDecimalFormatter +import com.tangem.core.ui.utils.DateTimeFormatters +import com.tangem.domain.visa.model.VisaCurrency +import com.tangem.domain.visa.model.VisaTxHistoryItem +import com.tangem.feature.wallet.impl.R +import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.VisaWalletIntents +import com.tangem.utils.converter.Converter +import org.joda.time.DateTimeZone + +internal class VisaTxHistoryItemStateConverter( + private val visaCurrency: VisaCurrency, + private val clickIntents: VisaWalletIntents, +) : Converter { + + override fun convert(value: VisaTxHistoryItem): TransactionState { + val localDate = value.date.withZone(DateTimeZone.getDefault()) + val time = DateTimeFormatters.formatTime(time = localDate) + val subtitle = "$time • ${value.status}" + + return TransactionState.Content( + txHash = value.id, + amount = BigDecimalFormatter.formatCryptoAmount( + cryptoAmount = value.amount, + cryptoCurrency = visaCurrency.symbol, + decimals = visaCurrency.decimals, + ), + // Show tx fiat amount instead of tx time + time = BigDecimalFormatter.formatFiatAmount( + fiatAmount = value.fiatAmount, + fiatCurrencyCode = value.fiatCurrency.currencyCode, + fiatCurrencySymbol = value.fiatCurrency.symbol, + ), + status = TransactionState.Content.Status.Confirmed, + direction = TransactionState.Content.Direction.INCOMING, + iconRes = R.drawable.ic_arrow_up_24, + title = stringReference(value = value.merchantName ?: "Unknown merchant"), + subtitle = stringReference(subtitle), + timestamp = localDate.millis, + onClick = { clickIntents.onVisaTransactionClick(value.id) }, + ) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt index d9d435e6f0..c30daff4df 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/TxHistorySubscriber.kt @@ -2,8 +2,8 @@ package com.tangem.feature.wallet.presentation.wallet.subscribers import androidx.paging.PagingData import androidx.paging.cachedIn +import androidx.paging.map import arrow.core.Either -import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.tokens.GetPrimaryCurrencyStatusUpdatesUseCase import com.tangem.domain.tokens.model.CryptoCurrencyStatus @@ -15,12 +15,16 @@ import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.wallet.presentation.wallet.domain.collectLatest import com.tangem.feature.wallet.presentation.wallet.state2.WalletStateController -import com.tangem.feature.wallet.presentation.wallet.state2.model.WalletState -import com.tangem.feature.wallet.presentation.wallet.state2.transformers.* +import com.tangem.feature.wallet.presentation.wallet.state2.transformers.SetTxHistoryCountErrorTransformer +import com.tangem.feature.wallet.presentation.wallet.state2.transformers.SetTxHistoryCountTransformer +import com.tangem.feature.wallet.presentation.wallet.state2.transformers.SetTxHistoryItemsErrorTransformer +import com.tangem.feature.wallet.presentation.wallet.state2.transformers.SetTxHistoryItemsTransformer +import com.tangem.feature.wallet.presentation.wallet.state2.transformers.converter.TxHistoryItemStateConverter import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntentsV2 import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.map typealias MaybeTxHistoryCount = Either typealias MaybeTxHistoryItems = Either>> @@ -37,24 +41,6 @@ internal class TxHistorySubscriber( ) : WalletSubscriber() { override fun create(coroutineScope: CoroutineScope): Flow> { - // TODO: [REDACTED_JIRA] - if (userWallet.scanResponse.cardTypesResolver.isVisaWallet()) { - return flow { - stateHolder.update( - object : WalletStateTransformer(userWallet.walletId) { - override fun transform(prevState: WalletState): WalletState { - return when (prevState) { - is WalletState.Visa.Content -> prevState.copy( - txHistoryState = TxHistoryState.Empty(onExploreClick = {}), - ) - else -> prevState - } - } - }, - ) - } - } - return flow { getPrimaryCurrencyStatusUpdatesUseCase.collectLatest(userWalletId = userWallet.walletId) { status -> val maybeTxHistoryItemCount = txHistoryItemsCountUseCase( @@ -109,10 +95,19 @@ internal class TxHistorySubscriber( clickIntents = clickIntents, ) }, - ifRight = { + ifRight = { itemsFlow -> + val blockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain() + val itemConverter = TxHistoryItemStateConverter( + symbol = blockchain.currency, + decimals = blockchain.decimals(), + clickIntents = clickIntents, + ) + SetTxHistoryItemsTransformer( userWallet = userWallet, - flow = it, + flow = itemsFlow.map { items -> + items.map(itemConverter::convert) + }, clickIntents = clickIntents, ) }, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/VisaWalletBalancesAndLimitsSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/VisaWalletBalancesAndLimitsSubscriber.kt deleted file mode 100644 index a25af15cdc..0000000000 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/VisaWalletBalancesAndLimitsSubscriber.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.tangem.feature.wallet.presentation.wallet.subscribers - -import com.tangem.domain.visa.GetVisaCurrencyUseCase -import com.tangem.domain.wallets.models.UserWallet -import com.tangem.feature.wallet.presentation.wallet.state2.WalletStateController -import com.tangem.feature.wallet.presentation.wallet.state2.transformers.SetBalancesAndLimitsTransformer -import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntentsV2 -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow - -@Suppress("LongParameterList") -internal class VisaWalletBalancesAndLimitsSubscriber( - private val userWallet: UserWallet, - private val stateHolder: WalletStateController, - private val isRefresh: Boolean, - private val getVisaCurrencyUseCase: GetVisaCurrencyUseCase, - private val clickIntents: WalletClickIntentsV2, -) : WalletSubscriber() { - - override fun create(coroutineScope: CoroutineScope): Flow<*> { - return flow { - stateHolder.update( - SetBalancesAndLimitsTransformer( - userWallet = userWallet, - maybeVisaCurrency = getVisaCurrencyUseCase(userWallet.walletId, isRefresh), - clickIntents = clickIntents, - ), - ) - } - } -} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/VisaWalletSubscriber.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/VisaWalletSubscriber.kt new file mode 100644 index 0000000000..ea540ec981 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/subscribers/VisaWalletSubscriber.kt @@ -0,0 +1,105 @@ +package com.tangem.feature.wallet.presentation.wallet.subscribers + +import androidx.paging.PagingData +import androidx.paging.cachedIn +import androidx.paging.map +import arrow.core.Either +import arrow.core.getOrElse +import com.tangem.domain.txhistory.models.TxHistoryListError +import com.tangem.domain.visa.GetVisaCurrencyUseCase +import com.tangem.domain.visa.GetVisaTxHistoryUseCase +import com.tangem.domain.visa.model.VisaCurrency +import com.tangem.domain.visa.model.VisaTxHistoryItem +import com.tangem.domain.wallets.models.UserWallet +import com.tangem.feature.wallet.presentation.wallet.state2.WalletStateController +import com.tangem.feature.wallet.presentation.wallet.state2.transformers.SetBalancesAndLimitsTransformer +import com.tangem.feature.wallet.presentation.wallet.state2.transformers.SetTxHistoryCountTransformer +import com.tangem.feature.wallet.presentation.wallet.state2.transformers.SetTxHistoryItemsErrorTransformer +import com.tangem.feature.wallet.presentation.wallet.state2.transformers.SetTxHistoryItemsTransformer +import com.tangem.feature.wallet.presentation.wallet.state2.transformers.converter.VisaTxHistoryItemStateConverter +import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntentsV2 +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.map +import timber.log.Timber + +internal class VisaWalletSubscriber( + private val userWallet: UserWallet, + private val stateController: WalletStateController, + private val isRefresh: Boolean, + private val getVisaCurrencyUseCase: GetVisaCurrencyUseCase, + private val getVisaTxHistoryUseCase: GetVisaTxHistoryUseCase, + private val clickIntents: WalletClickIntentsV2, +) : WalletSubscriber() { + + override fun create(coroutineScope: CoroutineScope): Flow<*> { + return flow { + setLoadingTxHistoryState() + + val maybeCurrency = getVisaCurrencyUseCase(userWallet.walletId, isRefresh) + setLoadedCurrencyState(maybeCurrency) + + val currency = maybeCurrency.getOrElse { + setFailedTxHistoryState(it) + return@flow + } + val txHistoryItemsFlow = getVisaTxHistoryUseCase(userWallet.walletId, isRefresh = isRefresh) + .map { maybeTxHistoryItems -> + maybeTxHistoryItems.getOrElse { + Timber.e(it, "Failed to load tx history for wallet ${userWallet.walletId}") + throw it + } + } + .catch { setFailedTxHistoryState(it) } + .cachedIn(coroutineScope) + + setLoadedTxHistoryState(txHistoryItemsFlow, currency) + } + } + + private fun setLoadedCurrencyState(maybeCurrency: Either) { + stateController.update( + SetBalancesAndLimitsTransformer( + userWallet = userWallet, + maybeVisaCurrency = maybeCurrency, + clickIntents = clickIntents, + ), + ) + } + + private fun setLoadingTxHistoryState() { + stateController.update( + SetTxHistoryCountTransformer( + userWalletId = userWallet.walletId, + transactionsCount = 10, + clickIntents = clickIntents, + ), + ) + } + + private fun setFailedTxHistoryState(it: Throwable) { + stateController.update( + SetTxHistoryItemsErrorTransformer( + userWalletId = userWallet.walletId, + error = TxHistoryListError.DataError(it), + clickIntents = clickIntents, + ), + ) + } + + private fun setLoadedTxHistoryState(itemsFlow: Flow>, currency: VisaCurrency) { + val itemConverter = VisaTxHistoryItemStateConverter(currency, clickIntents) + + stateController.update( + SetTxHistoryItemsTransformer( + userWallet = userWallet, + flow = itemsFlow.map { items -> + items.map(itemConverter::convert) + }, + clickIntents = clickIntents, + ), + ) + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreenV2.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreenV2.kt index 46380e8b44..15e0698e0d 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreenV2.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreenV2.kt @@ -30,6 +30,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.ActionsBottomSheetCon import com.tangem.feature.wallet.presentation.wallet.state.WalletAlertState import com.tangem.feature.wallet.presentation.wallet.state.components.WalletBottomSheetConfig import com.tangem.feature.wallet.presentation.wallet.state2.model.* +import com.tangem.feature.wallet.presentation.wallet.state2.model.holder.TxHistoryStateHolder import com.tangem.feature.wallet.presentation.wallet.ui.components.TokenActionsBottomSheet import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletsList import com.tangem.feature.wallet.presentation.wallet.ui.components.common.* @@ -92,7 +93,7 @@ private fun WalletContent( BaseScaffold(state = state, selectedWallet = selectedWallet, snackbarHostState = snackbarHostState) { val movableItemModifier = Modifier.changeWalletAnimator(walletsListState) - val lazyTxHistoryItems = (selectedWallet as? WalletState.SingleCurrency)?.let { walletState -> + val lazyTxHistoryItems = (selectedWallet as? TxHistoryStateHolder)?.let { walletState -> (walletState.txHistoryState as? TxHistoryState.Content)?.contentItems?.collectAsLazyPagingItems() } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/VisaWalletIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/VisaWalletIntents.kt index 5dad048ccd..00c4927cde 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/VisaWalletIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/VisaWalletIntents.kt @@ -23,6 +23,8 @@ internal interface VisaWalletIntents { fun onDepositClick() fun onBalancesAndLimitsClick() + + fun onVisaTransactionClick(id: String) } @ViewModelScoped @@ -93,4 +95,8 @@ internal class VisaWalletIntentsImplementor @Inject constructor( null } } + + override fun onVisaTransactionClick(id: String) { + // TODO: Implement [REDACTED_JIRA] + } } \ No newline at end of file