diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
index 42a6ccc24b..b40ebc1342 100644
--- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
+++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
@@ -634,7 +634,7 @@ internal class ChildFactory @Inject constructor(
is AppRoute.TangemPayDetails -> {
createComponentChild(
context = context,
- params = TangemPayDetailsComponent.Params(config = route.config),
+ params = TangemPayDetailsComponent.Params(userWalletId = route.userWalletId, config = route.config),
componentFactory = tangemPayDetailsComponentFactory,
)
}
diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt
index 5764799d45..7e09365956 100644
--- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt
+++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt
@@ -400,8 +400,9 @@ sealed class AppRoute(val path: String) : Route {
@Serializable
data class TangemPayDetails(
+ val userWalletId: UserWalletId,
val config: TangemPayDetailsConfig,
- ) : AppRoute(path = "/tangem_pay_details")
+ ) : AppRoute(path = "/tangem_pay_details/${userWalletId.stringValue}")
@Serializable
data class TangemPayOnboarding(
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 5351f7b076..d581e12134 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -1302,6 +1302,17 @@
You receive
Choose token
not available
+ Deposit
+ Dispute
+ Explore transaction
+ Service fees
+ Fee
+ Completed
+ Declined
+ Pending
+ The bank rejected this transaction request.
+ This fee goes to cover the cost of handling your transfer.
+ Withdrawal
Failed to load data. Try again later.
Hide
Technical issues detected. Please try again later or contact support.
diff --git a/core/ui/src/main/java/com/tangem/core/ui/extensions/ColorReference.kt b/core/ui/src/main/java/com/tangem/core/ui/extensions/ColorReference.kt
new file mode 100644
index 0000000000..8add413e59
--- /dev/null
+++ b/core/ui/src/main/java/com/tangem/core/ui/extensions/ColorReference.kt
@@ -0,0 +1,33 @@
+package com.tangem.core.ui.extensions
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.ui.graphics.Color
+
+/**
+ * Utility class for keeping themed color reference from app theme.
+ *
+ * It necessary to use [Immutable] annotation for runtime stability.
+ *
+ * @property value color provider from theme
+ */
+@Immutable
+data class ColorReference(val value: @Composable () -> Color)
+
+/**
+ * Creates a [ColorReference] using a themed color from the app theme with a lambda.
+ *
+ * @param value The color provider from theme.
+ * @return A [ColorReference] representing the themed color.
+ */
+fun themedColor(value: @Composable () -> Color): ColorReference {
+ return ColorReference(value)
+}
+
+/**
+ * Resolves [ColorReference] to [Color]
+ */
+@Composable
+fun ColorReference.resolveReference(): Color {
+ return value()
+}
\ No newline at end of file
diff --git a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayTxHistoryRepository.kt b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayTxHistoryRepository.kt
index 7e197fea52..b7c1bac9d4 100644
--- a/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayTxHistoryRepository.kt
+++ b/data/visa/src/main/kotlin/com/tangem/data/pay/repository/DefaultTangemPayTxHistoryRepository.kt
@@ -1,8 +1,10 @@
package com.tangem.data.pay.repository
+import com.squareup.moshi.Moshi
import com.tangem.data.common.cache.CacheRegistry
import com.tangem.data.visa.utils.TangemPayTxHistoryItemConverter
import com.tangem.datasource.api.pay.TangemPayApi
+import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.local.visa.TangemPayTxHistoryItemsStore
import com.tangem.domain.tangempay.model.TangemPayTxHistoryListBatchFlow
import com.tangem.domain.tangempay.model.TangemPayTxHistoryListBatchingContext
@@ -26,8 +28,11 @@ internal class DefaultTangemPayTxHistoryRepository @Inject constructor(
private val cacheRegistry: CacheRegistry,
private val txHistoryItemsStore: TangemPayTxHistoryItemsStore,
private val dispatchers: CoroutineDispatcherProvider,
+ @NetworkMoshi private val moshi: Moshi,
) : TangemPayTxHistoryRepository {
+ private val txHistoryItemConverter by lazy { TangemPayTxHistoryItemConverter(moshi) }
+
override fun getTxHistoryBatchFlow(
batchSize: Int,
context: TangemPayTxHistoryListBatchingContext,
@@ -84,7 +89,7 @@ internal class DefaultTangemPayTxHistoryRepository @Inject constructor(
val result = requestPerformer.request { authHeader ->
visaApi.getTangemPayTxHistory(authHeader = authHeader, limit = pageSize, cursor = cursor)
}.result
- val items = TangemPayTxHistoryItemConverter.convertList(result.transactions).filterNotNull()
+ val items = txHistoryItemConverter.convertList(result.transactions).filterNotNull()
txHistoryItemsStore.store(key = customerWalletAddress, cursor = cursor ?: INITIAL_CURSOR, value = items)
}.onLeft { error(it.toString()) }
}
diff --git a/data/visa/src/main/kotlin/com/tangem/data/visa/utils/TangemPayTxHistoryItemConverter.kt b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/TangemPayTxHistoryItemConverter.kt
index e8bead6d27..8c916070f1 100644
--- a/data/visa/src/main/kotlin/com/tangem/data/visa/utils/TangemPayTxHistoryItemConverter.kt
+++ b/data/visa/src/main/kotlin/com/tangem/data/visa/utils/TangemPayTxHistoryItemConverter.kt
@@ -1,14 +1,19 @@
package com.tangem.data.visa.utils
+import com.squareup.moshi.Moshi
import com.tangem.datasource.api.pay.models.response.TangemPayTxHistoryResponse
import com.tangem.domain.visa.model.TangemPayTxHistoryItem
import com.tangem.utils.converter.Converter
import timber.log.Timber
import java.util.Currency
-internal object TangemPayTxHistoryItemConverter :
+internal class TangemPayTxHistoryItemConverter(moshi: Moshi) :
Converter {
+ private val spendAdapter = moshi.adapter(TangemPayTxHistoryResponse.Spend::class.java)
+ private val paymentAdapter = moshi.adapter(TangemPayTxHistoryResponse.Payment::class.java)
+ private val feeAdapter = moshi.adapter(TangemPayTxHistoryResponse.Fee::class.java)
+
override fun convert(value: TangemPayTxHistoryResponse.Transaction): TangemPayTxHistoryItem? {
return value.spend?.let { convertSpend(id = value.id, spend = it) }
?: value.payment?.let { convertPayment(id = value.id, payment = it) }
@@ -22,6 +27,7 @@ internal object TangemPayTxHistoryItemConverter :
private fun convertSpend(id: String, spend: TangemPayTxHistoryResponse.Spend): TangemPayTxHistoryItem.Spend {
return TangemPayTxHistoryItem.Spend(
id = id,
+ jsonRepresentation = spendAdapter.toJson(spend),
// If postedAt is null, it means transaction wasn't posted and was likely declined. Use authorizedAt
date = spend.postedAt ?: spend.authorizedAt,
amount = spend.amount,
@@ -41,15 +47,18 @@ internal object TangemPayTxHistoryItemConverter :
): TangemPayTxHistoryItem.Payment {
return TangemPayTxHistoryItem.Payment(
id = id,
+ jsonRepresentation = paymentAdapter.toJson(payment),
date = payment.postedAt,
currency = Currency.getInstance(payment.currency),
amount = payment.amount,
+ transactionHash = payment.transactionHash,
)
}
private fun convertFee(id: String, fee: TangemPayTxHistoryResponse.Fee): TangemPayTxHistoryItem.Fee {
return TangemPayTxHistoryItem.Fee(
id = id,
+ jsonRepresentation = feeAdapter.toJson(fee),
date = fee.postedAt,
currency = Currency.getInstance(fee.currency),
amount = fee.amount,
diff --git a/domain/feedback/models/src/main/kotlin/com/tangem/domain/feedback/models/FeedbackEmailType.kt b/domain/feedback/models/src/main/kotlin/com/tangem/domain/feedback/models/FeedbackEmailType.kt
index 5649d73a23..df2d3bd01e 100644
--- a/domain/feedback/models/src/main/kotlin/com/tangem/domain/feedback/models/FeedbackEmailType.kt
+++ b/domain/feedback/models/src/main/kotlin/com/tangem/domain/feedback/models/FeedbackEmailType.kt
@@ -1,5 +1,6 @@
package com.tangem.domain.feedback.models
+import com.tangem.domain.visa.model.TangemPayTxHistoryItem
import com.tangem.domain.visa.model.VisaTxDetails
/**
@@ -64,5 +65,10 @@ sealed interface FeedbackEmailType {
val visaTxDetails: VisaTxDetails,
override val walletMetaInfo: WalletMetaInfo,
) : Visa()
+
+ data class DisputeV2(
+ val item: TangemPayTxHistoryItem,
+ override val walletMetaInfo: WalletMetaInfo,
+ ) : Visa()
}
}
\ No newline at end of file
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt
index e5f65f4c77..6431a2da48 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/FeedbackDataBuilder.kt
@@ -2,6 +2,7 @@ package com.tangem.domain.feedback
import com.tangem.domain.feedback.models.*
import com.tangem.domain.feedback.utils.breakLine
+import com.tangem.domain.visa.model.TangemPayTxHistoryItem
import com.tangem.domain.visa.model.VisaTxDetails
import com.tangem.domain.feedback.models.BlockchainInfo.Addresses as BlockchainAddresses
@@ -9,6 +10,10 @@ internal class FeedbackDataBuilder {
private val builder = StringBuilder()
+ fun addTangemPayTxInfo(item: TangemPayTxHistoryItem) {
+ builder.append(item.jsonRepresentation)
+ }
+
fun addVisaTxInfo(txDetails: VisaTxDetails) {
builder.appendKeyValue("Type", txDetails.type)
builder.appendKeyValue("Status", txDetails.status)
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt
index a8d5177b41..0aff9662cf 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/SendFeedbackEmailUseCase.kt
@@ -64,6 +64,7 @@ class SendFeedbackEmailUseCase(
is FeedbackEmailType.PreActivatedWallet,
is FeedbackEmailType.CardAttestationFailed,
is FeedbackEmailType.Visa.Dispute,
+ is FeedbackEmailType.Visa.DisputeV2,
-> this
is FeedbackEmailType.DirectUserRequest,
is FeedbackEmailType.RateCanBeBetter,
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt
index 5a94a88857..cf9a7a8208 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageBodyResolver.kt
@@ -1,9 +1,10 @@
package com.tangem.domain.feedback.utils
import com.tangem.domain.feedback.FeedbackDataBuilder
-import com.tangem.domain.feedback.models.WalletMetaInfo
import com.tangem.domain.feedback.models.FeedbackEmailType
+import com.tangem.domain.feedback.models.WalletMetaInfo
import com.tangem.domain.feedback.repository.FeedbackRepository
+import com.tangem.domain.visa.model.TangemPayTxHistoryItem
import com.tangem.domain.visa.model.VisaTxDetails
/**
@@ -33,11 +34,21 @@ internal class EmailMessageBodyResolver(
is FeedbackEmailType.Visa.Activation -> addUserRequestBody(type.walletMetaInfo)
is FeedbackEmailType.Visa.DirectUserRequest -> addUserRequestBody(type.walletMetaInfo)
is FeedbackEmailType.Visa.Dispute -> addVisaRequestBody(type.walletMetaInfo, type.visaTxDetails)
+ is FeedbackEmailType.Visa.DisputeV2 -> addTangemPayRequestBody(type.walletMetaInfo, type.item)
}
return build()
}
+ private suspend fun FeedbackDataBuilder.addTangemPayRequestBody(
+ walletMetaInfo: WalletMetaInfo,
+ item: TangemPayTxHistoryItem,
+ ) {
+ addUserRequestBody(walletMetaInfo)
+ addDelimiter()
+ addTangemPayTxInfo(item)
+ }
+
private suspend fun FeedbackDataBuilder.addVisaRequestBody(
walletMetaInfo: WalletMetaInfo,
visaTxDetails: VisaTxDetails,
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt
index 583f43cb02..7a76916fd1 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailMessageTitleResolver.kt
@@ -23,6 +23,7 @@ internal class EmailMessageTitleResolver(private val resources: Resources) {
is FeedbackEmailType.Visa.Activation,
is FeedbackEmailType.Visa.DirectUserRequest,
is FeedbackEmailType.Visa.Dispute,
+ is FeedbackEmailType.Visa.DisputeV2,
-> R.string.feedback_preface_support
is FeedbackEmailType.RateCanBeBetter -> R.string.feedback_preface_rate_negative
is FeedbackEmailType.ScanningProblem -> R.string.feedback_preface_scan_failed
diff --git a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt
index 490c6611dd..e930678eae 100644
--- a/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt
+++ b/domain/feedback/src/main/java/com/tangem/domain/feedback/utils/EmailSubjectResolver.kt
@@ -39,7 +39,9 @@ internal class EmailSubjectResolver(private val resources: Resources) {
FeedbackEmailType.CardAttestationFailed -> "Card attestation failed"
is FeedbackEmailType.Visa.Activation -> "[Visa] [Activation] {auto-filled subject}"
is FeedbackEmailType.Visa.DirectUserRequest -> "[Visa] {auto-filled subject}"
- is FeedbackEmailType.Visa.Dispute -> "[Visa] [DISPUTE] {auto-filled subject}"
+ is FeedbackEmailType.Visa.Dispute,
+ is FeedbackEmailType.Visa.DisputeV2,
+ -> "[Visa] [DISPUTE] {auto-filled subject}"
}
}
}
\ No newline at end of file
diff --git a/domain/models/build.gradle.kts b/domain/models/build.gradle.kts
index f2d3d5a0cf..5cb3097c77 100644
--- a/domain/models/build.gradle.kts
+++ b/domain/models/build.gradle.kts
@@ -18,6 +18,7 @@ dependencies {
implementation(deps.moshi.kotlin)
implementation(deps.moshi.adapters)
implementation(deps.kotlin.datetime)
+ implementation(deps.jodatime)
implementation(deps.kotlin.serialization)
ksp(deps.moshi.kotlin.codegen)
implementation(deps.arrow.core)
diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/serialization/CurrencySerializer.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/serialization/CurrencySerializer.kt
new file mode 100644
index 0000000000..b17a17658f
--- /dev/null
+++ b/domain/models/src/main/kotlin/com/tangem/domain/models/serialization/CurrencySerializer.kt
@@ -0,0 +1,24 @@
+package com.tangem.domain.models.serialization
+
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+import java.util.Currency
+
+typealias SerializedCurrency = @Serializable(with = CurrencySerializer::class) Currency
+
+object CurrencySerializer : KSerializer {
+ override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("java.util.Currency", PrimitiveKind.STRING)
+
+ override fun serialize(encoder: Encoder, value: Currency) {
+ encoder.encodeString(value.currencyCode)
+ }
+
+ override fun deserialize(decoder: Decoder): Currency {
+ return Currency.getInstance(decoder.decodeString())
+ }
+}
\ No newline at end of file
diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/serialization/JodaDateTimeSerializer.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/serialization/JodaDateTimeSerializer.kt
new file mode 100644
index 0000000000..d72729ef78
--- /dev/null
+++ b/domain/models/src/main/kotlin/com/tangem/domain/models/serialization/JodaDateTimeSerializer.kt
@@ -0,0 +1,24 @@
+package com.tangem.domain.models.serialization
+
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+import org.joda.time.DateTime
+
+typealias SerializedDateTime = @Serializable(with = JodaDateTimeSerializer::class) DateTime
+
+object JodaDateTimeSerializer : KSerializer {
+ override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("DateTime", PrimitiveKind.LONG)
+
+ override fun serialize(encoder: Encoder, value: DateTime) {
+ encoder.encodeLong(value.millis)
+ }
+
+ override fun deserialize(decoder: Decoder): DateTime {
+ return DateTime(decoder.decodeLong())
+ }
+}
\ No newline at end of file
diff --git a/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/TangemPayTxHistoryItem.kt b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/TangemPayTxHistoryItem.kt
index 6793255df3..d5a102ee64 100644
--- a/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/TangemPayTxHistoryItem.kt
+++ b/domain/visa/models/src/main/kotlin/com/tangem/domain/visa/model/TangemPayTxHistoryItem.kt
@@ -1,20 +1,25 @@
package com.tangem.domain.visa.model
-import org.joda.time.DateTime
-import java.math.BigDecimal
-import java.util.Currency
+import com.tangem.domain.models.serialization.SerializedBigDecimal
+import com.tangem.domain.models.serialization.SerializedCurrency
+import com.tangem.domain.models.serialization.SerializedDateTime
+import kotlinx.serialization.Serializable
+@Serializable
sealed class TangemPayTxHistoryItem {
abstract val id: String
- abstract val date: DateTime
- abstract val amount: BigDecimal
- abstract val currency: Currency
+ abstract val date: SerializedDateTime
+ abstract val amount: SerializedBigDecimal
+ abstract val currency: SerializedCurrency
+ abstract val jsonRepresentation: String
+ @Serializable
data class Spend(
override val id: String,
- override val date: DateTime,
- override val amount: BigDecimal,
- override val currency: Currency,
+ override val jsonRepresentation: String,
+ override val date: SerializedDateTime,
+ override val amount: SerializedBigDecimal,
+ override val currency: SerializedCurrency,
val enrichedMerchantName: String?,
val merchantName: String,
val enrichedMerchantCategory: String?,
@@ -23,18 +28,23 @@ sealed class TangemPayTxHistoryItem {
val enrichedMerchantIconUrl: String?,
) : TangemPayTxHistoryItem()
+ @Serializable
data class Payment(
override val id: String,
- override val date: DateTime,
- override val amount: BigDecimal,
- override val currency: Currency,
+ override val jsonRepresentation: String,
+ override val date: SerializedDateTime,
+ override val amount: SerializedBigDecimal,
+ override val currency: SerializedCurrency,
+ val transactionHash: String?,
) : TangemPayTxHistoryItem()
+ @Serializable
data class Fee(
override val id: String,
- override val date: DateTime,
- override val amount: BigDecimal,
- override val currency: Currency,
+ override val jsonRepresentation: String,
+ override val date: SerializedDateTime,
+ override val amount: SerializedBigDecimal,
+ override val currency: SerializedCurrency,
) : TangemPayTxHistoryItem()
enum class Status {
diff --git a/features/tangempay/details/api/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayDetailsComponent.kt b/features/tangempay/details/api/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayDetailsComponent.kt
index 428f063730..c78a18aa6f 100644
--- a/features/tangempay/details/api/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayDetailsComponent.kt
+++ b/features/tangempay/details/api/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayDetailsComponent.kt
@@ -2,9 +2,10 @@ package com.tangem.features.tangempay.components
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableContentComponent
+import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.pay.TangemPayDetailsConfig
interface TangemPayDetailsComponent : ComposableContentComponent {
- data class Params(val config: TangemPayDetailsConfig)
+ data class Params(val userWalletId: UserWalletId, val config: TangemPayDetailsConfig)
interface Factory : ComponentFactory
}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/build.gradle.kts b/features/tangempay/details/impl/build.gradle.kts
index cc2ac540ec..4789f8413a 100644
--- a/features/tangempay/details/impl/build.gradle.kts
+++ b/features/tangempay/details/impl/build.gradle.kts
@@ -15,8 +15,9 @@ dependencies {
/** Core */
implementation(projects.core.configToggles)
implementation(projects.core.decompose)
- implementation(projects.core.ui)
implementation(projects.core.error)
+ implementation(projects.core.navigation)
+ implementation(projects.core.ui)
/** Features api */
implementation(projects.features.tangempay.details.api)
@@ -26,9 +27,12 @@ dependencies {
/** Domain */
implementation(projects.domain.balanceHiding)
implementation(projects.domain.balanceHiding.models)
+ implementation(projects.domain.feedback)
+ implementation(projects.domain.feedback.models)
implementation(projects.domain.models)
implementation(projects.domain.visa)
implementation(projects.domain.visa.models)
+ implementation(projects.domain.wallets)
/** Compose */
implementation(deps.compose.coil)
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayDetailsComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayDetailsComponent.kt
index adad4cfd19..53e057a5c8 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayDetailsComponent.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/DefaultTangemPayDetailsComponent.kt
@@ -15,8 +15,9 @@ import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.core.ui.components.NavigationBar3ButtonsScrim
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.features.tangempay.components.txHistory.DefaultTangemPayTxHistoryComponent
+import com.tangem.features.tangempay.components.txHistory.TangemPayTxHistoryDetailsComponent
import com.tangem.features.tangempay.model.TangemPayDetailsModel
-import com.tangem.features.tangempay.model.TangemPayDetailsNavigation
+import com.tangem.features.tangempay.entity.TangemPayDetailsNavigation
import com.tangem.features.tangempay.ui.TangemPayDetailsScreen
import com.tangem.features.tokenreceive.TokenReceiveComponent
import dagger.assisted.Assisted
@@ -39,7 +40,10 @@ internal class DefaultTangemPayDetailsComponent @AssistedInject constructor(
)
private val txHistoryComponent = DefaultTangemPayTxHistoryComponent(
appComponentContext = child("txHistoryComponent"),
- params = DefaultTangemPayTxHistoryComponent.Params(customerWalletAddress = params.config.customerWalletAddress),
+ params = DefaultTangemPayTxHistoryComponent.Params(
+ customerWalletAddress = params.config.customerWalletAddress,
+ uiActions = model,
+ ),
)
@Composable
@@ -59,19 +63,25 @@ internal class DefaultTangemPayDetailsComponent @AssistedInject constructor(
private fun bottomSheetChild(
navigation: TangemPayDetailsNavigation,
componentContext: ComponentContext,
- ): ComposableBottomSheetComponent = when (navigation) {
- is TangemPayDetailsNavigation.Error -> TangemPayErrorBottomSheetComponent(
- appComponentContext = appComponentContext,
- messageUM = navigation.messageUM,
- onDismiss = model.bottomSheetNavigation::dismiss,
- )
- is TangemPayDetailsNavigation.Receive -> tokenReceiveComponentFactory.create(
- context = childByContext(componentContext),
- params = TokenReceiveComponent.Params(
- config = navigation.config,
- onDismiss = model.bottomSheetNavigation::dismiss,
- ),
- )
+ ): ComposableBottomSheetComponent {
+ val context = childByContext(componentContext)
+ return when (navigation) {
+ is TangemPayDetailsNavigation.Receive -> tokenReceiveComponentFactory.create(
+ context = context,
+ params = TokenReceiveComponent.Params(
+ config = navigation.config,
+ onDismiss = model.bottomSheetNavigation::dismiss,
+ ),
+ )
+ is TangemPayDetailsNavigation.TransactionDetails -> TangemPayTxHistoryDetailsComponent(
+ appComponentContext = context,
+ params = TangemPayTxHistoryDetailsComponent.Params(
+ transaction = navigation.transaction,
+ userWalletId = params.userWalletId,
+ onDismiss = model.bottomSheetNavigation::dismiss,
+ ),
+ )
+ }
}
@AssistedFactory
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayErrorBottomSheetComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayErrorBottomSheetComponent.kt
deleted file mode 100644
index 62e7a375f5..0000000000
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/TangemPayErrorBottomSheetComponent.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.tangem.features.tangempay.components
-
-import androidx.compose.runtime.Composable
-import com.tangem.core.decompose.context.AppComponentContext
-import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2
-import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetV2
-import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
-
-internal class TangemPayErrorBottomSheetComponent(
- appComponentContext: AppComponentContext,
- private val messageUM: MessageBottomSheetUMV2,
- private val onDismiss: () -> Unit,
-) : AppComponentContext by appComponentContext, ComposableBottomSheetComponent {
-
- override fun dismiss() {
- onDismiss()
- }
-
- @Composable
- override fun BottomSheet() {
- MessageBottomSheetV2(state = messageUM, onDismissRequest = ::dismiss)
- }
-}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/txHistory/DefaultTangemPayTxHistoryComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/txHistory/DefaultTangemPayTxHistoryComponent.kt
index 4338d0ecbc..42a85d03c4 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/txHistory/DefaultTangemPayTxHistoryComponent.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/txHistory/DefaultTangemPayTxHistoryComponent.kt
@@ -7,6 +7,7 @@ import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.features.tangempay.entity.TangemPayTxHistoryUM
import com.tangem.features.tangempay.model.TangemPayTxHistoryModel
import com.tangem.features.tangempay.ui.tangemPayTxHistoryItems
+import com.tangem.features.tangempay.utils.TangemPayTxHistoryUiActions
import kotlinx.coroutines.flow.StateFlow
internal class DefaultTangemPayTxHistoryComponent(
@@ -21,5 +22,5 @@ internal class DefaultTangemPayTxHistoryComponent(
tangemPayTxHistoryItems(listState, state)
}
- data class Params(val customerWalletAddress: String)
+ data class Params(val customerWalletAddress: String, val uiActions: TangemPayTxHistoryUiActions)
}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/txHistory/TangemPayTxHistoryDetailsComponent.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/txHistory/TangemPayTxHistoryDetailsComponent.kt
new file mode 100644
index 0000000000..345ca4a497
--- /dev/null
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/components/txHistory/TangemPayTxHistoryDetailsComponent.kt
@@ -0,0 +1,34 @@
+package com.tangem.features.tangempay.components.txHistory
+
+import androidx.compose.runtime.Composable
+import com.tangem.core.decompose.context.AppComponentContext
+import com.tangem.core.decompose.model.getOrCreateModel
+import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
+import com.tangem.core.ui.extensions.*
+import com.tangem.domain.models.wallet.UserWalletId
+import com.tangem.domain.visa.model.TangemPayTxHistoryItem
+import com.tangem.features.tangempay.model.TangemPayTxHistoryDetailsModel
+import com.tangem.features.tangempay.ui.TangemPayTxHistoryDetailsContent
+
+internal class TangemPayTxHistoryDetailsComponent(
+ appComponentContext: AppComponentContext,
+ params: Params,
+) : ComposableBottomSheetComponent, AppComponentContext by appComponentContext {
+
+ private val model: TangemPayTxHistoryDetailsModel = getOrCreateModel(params = params)
+
+ override fun dismiss() {
+ model.dismiss()
+ }
+
+ @Composable
+ override fun BottomSheet() {
+ TangemPayTxHistoryDetailsContent(state = model.uiState)
+ }
+
+ data class Params(
+ val transaction: TangemPayTxHistoryItem,
+ val userWalletId: UserWalletId,
+ val onDismiss: () -> Unit,
+ )
+}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt
index ef72f17c45..cc9f121abb 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/di/TangemPayModelModule.kt
@@ -3,6 +3,7 @@ package com.tangem.features.tangempay.di
import com.tangem.core.decompose.di.ModelComponent
import com.tangem.core.decompose.model.Model
import com.tangem.features.tangempay.model.TangemPayDetailsModel
+import com.tangem.features.tangempay.model.TangemPayTxHistoryDetailsModel
import com.tangem.features.tangempay.model.TangemPayTxHistoryModel
import dagger.Binds
import dagger.Module
@@ -23,4 +24,9 @@ internal interface TangemPayModelModule {
@IntoMap
@ClassKey(TangemPayTxHistoryModel::class)
fun bindTangemPayTxHistoryModel(model: TangemPayTxHistoryModel): Model
+
+ @Binds
+ @IntoMap
+ @ClassKey(TangemPayTxHistoryDetailsModel::class)
+ fun bindTangemPayTxHistoryDetailsModel(model: TangemPayTxHistoryDetailsModel): Model
}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsNavigation.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsNavigation.kt
new file mode 100644
index 0000000000..4bf153edca
--- /dev/null
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayDetailsNavigation.kt
@@ -0,0 +1,15 @@
+package com.tangem.features.tangempay.entity
+
+import com.tangem.domain.models.TokenReceiveConfig
+import com.tangem.domain.visa.model.TangemPayTxHistoryItem
+import kotlinx.serialization.Serializable
+
+@Serializable
+internal sealed class TangemPayDetailsNavigation {
+
+ @Serializable
+ data class Receive(val config: TokenReceiveConfig) : TangemPayDetailsNavigation()
+
+ @Serializable
+ data class TransactionDetails(val transaction: TangemPayTxHistoryItem) : TangemPayDetailsNavigation()
+}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayTxHistoryDetailsUM.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayTxHistoryDetailsUM.kt
new file mode 100644
index 0000000000..2ca794500d
--- /dev/null
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/entity/TangemPayTxHistoryDetailsUM.kt
@@ -0,0 +1,23 @@
+package com.tangem.features.tangempay.entity
+
+import com.tangem.core.ui.components.label.entity.LabelUM
+import com.tangem.core.ui.components.notifications.NotificationConfig
+import com.tangem.core.ui.extensions.ColorReference
+import com.tangem.core.ui.extensions.ImageReference
+import com.tangem.core.ui.extensions.TextReference
+
+internal data class TangemPayTxHistoryDetailsUM(
+ val title: TextReference,
+ val iconState: ImageReference,
+ val transactionTitle: TextReference,
+ val transactionSubtitle: TextReference,
+ val transactionAmount: String,
+ val transactionAmountColor: ColorReference,
+ val labelState: LabelUM?,
+ val notification: NotificationConfig?,
+ val buttonState: ButtonState,
+ val dismiss: () -> Unit,
+) {
+
+ data class ButtonState(val text: TextReference, val onClick: () -> Unit)
+}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt
index da92a7606c..0a8a5676fe 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsModel.kt
@@ -4,7 +4,6 @@ import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.toArgb
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
-import com.arkivanov.decompose.router.slot.dismiss
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@@ -19,13 +18,16 @@ import com.tangem.domain.models.TokenReceiveConfig
import com.tangem.domain.models.TokenReceiveType
import com.tangem.domain.pay.DataForReceiveFactory
import com.tangem.domain.pay.repository.CardDetailsRepository
+import com.tangem.domain.visa.model.TangemPayTxHistoryItem
import com.tangem.features.tangempay.components.TangemPayDetailsComponent
import com.tangem.features.tangempay.details.impl.R
import com.tangem.features.tangempay.entity.TangemPayDetailsErrorType
+import com.tangem.features.tangempay.entity.TangemPayDetailsNavigation
import com.tangem.features.tangempay.entity.TangemPayDetailsStateFactory
import com.tangem.features.tangempay.entity.TangemPayDetailsUM
import com.tangem.features.tangempay.model.transformers.*
import com.tangem.features.tangempay.utils.TangemPayErrorMessageFactory
+import com.tangem.features.tangempay.utils.TangemPayTxHistoryUiActions
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.coroutines.JobHolder
import com.tangem.utils.coroutines.saveIn
@@ -53,7 +55,7 @@ internal class TangemPayDetailsModel @Inject constructor(
private val dataForReceiveFactory: DataForReceiveFactory,
private val clipboardManager: ClipboardManager,
private val uiMessageSender: UiMessageSender,
-) : Model() {
+) : Model(), TangemPayTxHistoryUiActions {
private val params: TangemPayDetailsComponent.Params = paramsContainer.require()
@@ -102,11 +104,8 @@ internal class TangemPayDetailsModel @Inject constructor(
bottomSheetNavigation.activate(TangemPayDetailsNavigation.Receive(config))
}
.onLeft {
- val messageUM = TangemPayErrorMessageFactory.createError(
- type = TangemPayDetailsErrorType.Receive,
- onDismiss = bottomSheetNavigation::dismiss,
- )
- bottomSheetNavigation.activate(TangemPayDetailsNavigation.Error(messageUM))
+ val messageUM = TangemPayErrorMessageFactory.createErrorMessage(TangemPayDetailsErrorType.Receive)
+ uiMessageSender.send(message = messageUM)
}
}
}
@@ -163,4 +162,8 @@ internal class TangemPayDetailsModel @Inject constructor(
SnackbarMessage(TextReference.Res(R.string.tangempay_card_details_error_text)),
)
}
+
+ override fun onTransactionClick(item: TangemPayTxHistoryItem) {
+ bottomSheetNavigation.activate(TangemPayDetailsNavigation.TransactionDetails(item))
+ }
}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsNavigation.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsNavigation.kt
deleted file mode 100644
index bcf24b8829..0000000000
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayDetailsNavigation.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.tangem.features.tangempay.model
-
-import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2
-import com.tangem.domain.models.TokenReceiveConfig
-import kotlinx.serialization.Serializable
-
-@Serializable
-internal sealed class TangemPayDetailsNavigation {
-
- data class Receive(
- val config: TokenReceiveConfig,
- ) : TangemPayDetailsNavigation()
-
- data class Error(
- val messageUM: MessageBottomSheetUMV2,
- ) : TangemPayDetailsNavigation()
-}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModel.kt
new file mode 100644
index 0000000000..48d190991e
--- /dev/null
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryDetailsModel.kt
@@ -0,0 +1,66 @@
+package com.tangem.features.tangempay.model
+
+import androidx.compose.runtime.Stable
+import com.tangem.core.decompose.di.ModelScoped
+import com.tangem.core.decompose.model.Model
+import com.tangem.core.decompose.model.ParamsContainer
+import com.tangem.core.navigation.url.UrlOpener
+import com.tangem.domain.feedback.GetWalletMetaInfoUseCase
+import com.tangem.domain.feedback.SendFeedbackEmailUseCase
+import com.tangem.domain.feedback.models.FeedbackEmailType
+import com.tangem.domain.models.wallet.requireColdWallet
+import com.tangem.domain.wallets.usecase.GetWalletsUseCase
+import com.tangem.features.tangempay.components.txHistory.TangemPayTxHistoryDetailsComponent
+import com.tangem.features.tangempay.entity.TangemPayTxHistoryDetailsUM
+import com.tangem.features.tangempay.model.transformers.TangemPayTxHistoryDetailsConverter
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@Stable
+@ModelScoped
+internal class TangemPayTxHistoryDetailsModel @Inject constructor(
+ override val dispatchers: CoroutineDispatcherProvider,
+ private val getUserWalletsUseCase: GetWalletsUseCase,
+ private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase,
+ private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
+ private val urlOpener: UrlOpener,
+ paramsContainer: ParamsContainer,
+) : Model() {
+
+ private val params = paramsContainer.require()
+ val uiState: TangemPayTxHistoryDetailsUM = TangemPayTxHistoryDetailsConverter.convert(
+ TangemPayTxHistoryDetailsConverter.Input(
+ item = params.transaction,
+ onExplorerClick = ::openExplorer,
+ onDisputeClick = ::dispute,
+ onDismiss = ::dismiss,
+ ),
+ )
+
+ fun dismiss() {
+ params.onDismiss()
+ }
+
+ fun openExplorer(txHash: String?) {
+ txHash?.let(urlOpener::openUrlExternalBrowser)
+ }
+
+ fun dispute() {
+ modelScope.launch {
+ val userWalletId = params.userWalletId
+ val userWallet = getUserWalletsUseCase.invokeSync()
+ .firstOrNull { it.walletId == userWalletId } ?: return@launch
+ val walletMetaInfo = getWalletMetaInfoUseCase.invoke(
+ userWallet.requireColdWallet().scanResponse,
+ ).getOrNull() ?: return@launch
+
+ sendFeedbackEmailUseCase.invoke(
+ FeedbackEmailType.Visa.DisputeV2(
+ item = params.transaction,
+ walletMetaInfo = walletMetaInfo,
+ ),
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryModel.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryModel.kt
index ac67e1d5b4..85a8c31571 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryModel.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/TangemPayTxHistoryModel.kt
@@ -6,17 +6,14 @@ import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.tangempay.repository.TangemPayTxHistoryRepository
-import com.tangem.domain.visa.model.TangemPayTxHistoryItem
import com.tangem.features.tangempay.components.txHistory.DefaultTangemPayTxHistoryComponent
import com.tangem.features.tangempay.entity.TangemPayTxHistoryUM
import com.tangem.features.tangempay.utils.TangemPayTxHistoryListManager
-import com.tangem.features.tangempay.utils.TangemPayTxHistoryUiActions
import com.tangem.pagination.PaginationStatus
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
-import timber.log.Timber
import javax.inject.Inject
@Stable
@@ -26,14 +23,14 @@ internal class TangemPayTxHistoryModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
tangemPayTxHistoryRepository: TangemPayTxHistoryRepository,
paramsContainer: ParamsContainer,
-) : Model(), TangemPayTxHistoryUiActions {
+) : Model() {
private val params: DefaultTangemPayTxHistoryComponent.Params = paramsContainer.require()
private val listManager = TangemPayTxHistoryListManager(
repository = tangemPayTxHistoryRepository,
dispatchers = dispatchers,
customerWalletAddress = params.customerWalletAddress,
- txHistoryUiActions = this,
+ txHistoryUiActions = params.uiActions,
)
val uiState: StateFlow
@@ -115,10 +112,6 @@ internal class TangemPayTxHistoryModel @Inject constructor(
.launchIn(modelScope)
}
- override fun onTransactionClick(item: TangemPayTxHistoryItem) {
- Timber.d("onTransactionClick: $item")
- }
-
private fun getEmptyState(isBalanceHidden: Boolean): TangemPayTxHistoryUM.Empty {
return TangemPayTxHistoryUM.Empty(isBalanceHidden = isBalanceHidden)
}
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverter.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverter.kt
new file mode 100644
index 0000000000..edf1708a96
--- /dev/null
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/model/transformers/TangemPayTxHistoryDetailsConverter.kt
@@ -0,0 +1,202 @@
+package com.tangem.features.tangempay.model.transformers
+
+import com.tangem.core.ui.components.label.entity.LabelStyle
+import com.tangem.core.ui.components.label.entity.LabelUM
+import com.tangem.core.ui.components.notifications.NotificationConfig
+import com.tangem.core.ui.extensions.*
+import com.tangem.core.ui.format.bigdecimal.fiat
+import com.tangem.core.ui.format.bigdecimal.format
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.core.ui.utils.DateTimeFormatters
+import com.tangem.domain.visa.model.TangemPayTxHistoryItem
+import com.tangem.features.tangempay.details.impl.R
+import com.tangem.features.tangempay.entity.TangemPayTxHistoryDetailsUM
+import com.tangem.utils.StringsSigns
+import com.tangem.utils.converter.Converter
+import com.tangem.utils.extensions.isPositive
+
+internal object TangemPayTxHistoryDetailsConverter :
+ Converter {
+ private val dateFormatter = DateTimeFormatters.getBestFormatterBySkeleton("dd MMMM")
+
+ override fun convert(value: Input): TangemPayTxHistoryDetailsUM {
+ val transaction = value.item
+ return TangemPayTxHistoryDetailsUM(
+ title = transaction.extractDate(),
+ iconState = transaction.extractIcon(),
+ transactionTitle = transaction.extractTransactionTitle(),
+ transactionSubtitle = transaction.extractTransactionSubtitle(),
+ transactionAmount = transaction.extractAmount(),
+ transactionAmountColor = value.item.extractAmountColor(),
+ labelState = value.item.extractLabel(),
+ notification = value.item.extractNotification(),
+ buttonState = value.extractButtonState(),
+ dismiss = value.onDismiss,
+ )
+ }
+
+ private fun TangemPayTxHistoryItem.extractDate(): TextReference {
+ val date = DateTimeFormatters.formatDate(this.date, dateFormatter)
+ val time = DateTimeFormatters.formatDate(this.date, DateTimeFormatters.timeFormatter)
+
+ return stringReference("$date ${StringsSigns.DOT} $time")
+ }
+
+ private fun TangemPayTxHistoryItem.extractIcon(): ImageReference {
+ return when (this) {
+ is TangemPayTxHistoryItem.Fee -> ImageReference.Res(R.drawable.ic_percent_24)
+ is TangemPayTxHistoryItem.Payment -> {
+ if (this.amount.isPositive()) {
+ ImageReference.Res(R.drawable.ic_arrow_down_24)
+ } else {
+ ImageReference.Res(R.drawable.ic_arrow_up_24)
+ }
+ }
+ is TangemPayTxHistoryItem.Spend -> {
+ val merchantIcon = this.enrichedMerchantIconUrl
+ if (merchantIcon != null) {
+ ImageReference.Url(merchantIcon)
+ } else {
+ ImageReference.Res(R.drawable.ic_category_24)
+ }
+ }
+ }
+ }
+
+ private fun TangemPayTxHistoryItem.extractTransactionTitle(): TextReference {
+ return when (this) {
+ is TangemPayTxHistoryItem.Fee -> resourceReference(R.string.tangem_pay_fee_title)
+ is TangemPayTxHistoryItem.Spend -> stringReference(this.enrichedMerchantName ?: this.merchantName)
+ is TangemPayTxHistoryItem.Payment -> if (this.amount.isPositive()) {
+ resourceReference(R.string.tangem_pay_deposit)
+ } else {
+ resourceReference(R.string.tangem_pay_withdrawal)
+ }
+ }
+ }
+
+ private fun TangemPayTxHistoryItem.extractTransactionSubtitle(): TextReference {
+ return when (this) {
+ is TangemPayTxHistoryItem.Fee -> resourceReference(R.string.tangem_pay_fee_subtitle)
+ is TangemPayTxHistoryItem.Payment -> resourceReference(R.string.common_transfer)
+ is TangemPayTxHistoryItem.Spend -> stringReference(this.enrichedMerchantCategory ?: this.merchantCategory)
+ }
+ }
+
+ private fun TangemPayTxHistoryItem.extractAmount(): String {
+ return when (this) {
+ is TangemPayTxHistoryItem.Fee,
+ is TangemPayTxHistoryItem.Spend,
+ -> {
+ val amount = this.amount.format {
+ fiat(
+ fiatCurrencyCode = this@extractAmount.currency.currencyCode,
+ fiatCurrencySymbol = this@extractAmount.currency.symbol,
+ )
+ }
+ StringsSigns.MINUS + amount
+ }
+ is TangemPayTxHistoryItem.Payment -> {
+ val amount = this.amount.format {
+ fiat(
+ fiatCurrencyCode = this@extractAmount.currency.currencyCode,
+ fiatCurrencySymbol = this@extractAmount.currency.symbol,
+ )
+ }
+ if (this.amount.isPositive()) {
+ StringsSigns.PLUS + amount
+ } else {
+ StringsSigns.MINUS + amount
+ }
+ }
+ }
+ }
+
+ private fun TangemPayTxHistoryItem.extractAmountColor(): ColorReference {
+ return when (this) {
+ is TangemPayTxHistoryItem.Fee,
+ is TangemPayTxHistoryItem.Spend,
+ -> themedColor { TangemTheme.colors.text.primary1 }
+ is TangemPayTxHistoryItem.Payment -> themedColor {
+ if (this.amount.isPositive()) {
+ TangemTheme.colors.text.accent
+ } else {
+ TangemTheme.colors.text.primary1
+ }
+ }
+ }
+ }
+
+ private fun TangemPayTxHistoryItem.extractLabel(): LabelUM? {
+ return when (this) {
+ is TangemPayTxHistoryItem.Fee,
+ is TangemPayTxHistoryItem.Payment,
+ -> null
+ is TangemPayTxHistoryItem.Spend -> when (this.status) {
+ TangemPayTxHistoryItem.Status.COMPLETED -> LabelUM(
+ text = resourceReference(R.string.tangem_pay_status_completed),
+ style = LabelStyle.ACCENT,
+ )
+ TangemPayTxHistoryItem.Status.PENDING -> LabelUM(
+ text = resourceReference(R.string.tangem_pay_status_pending),
+ style = LabelStyle.REGULAR,
+ icon = com.tangem.core.ui.R.drawable.ic_clock_24,
+ )
+ TangemPayTxHistoryItem.Status.DECLINED -> LabelUM(
+ text = resourceReference(R.string.tangem_pay_status_declined),
+ style = LabelStyle.WARNING,
+ )
+ TangemPayTxHistoryItem.Status.RESERVED,
+ TangemPayTxHistoryItem.Status.UNKNOWN,
+ -> null
+ }
+ }
+ }
+
+ private fun TangemPayTxHistoryItem.extractNotification(): NotificationConfig? {
+ return when (this) {
+ is TangemPayTxHistoryItem.Payment -> null
+ is TangemPayTxHistoryItem.Fee -> NotificationConfig(
+ title = resourceReference(R.string.tangem_pay_transaction_fee_notification_text),
+ subtitle = TextReference.EMPTY,
+ iconResId = R.drawable.ic_token_info_24,
+ )
+ is TangemPayTxHistoryItem.Spend -> when (this.status) {
+ TangemPayTxHistoryItem.Status.DECLINED -> NotificationConfig(
+ title = resourceReference(R.string.tangem_pay_transaction_declined_notification_text),
+ subtitle = TextReference.EMPTY,
+ iconResId = R.drawable.ic_token_info_24,
+ )
+ TangemPayTxHistoryItem.Status.PENDING,
+ TangemPayTxHistoryItem.Status.COMPLETED,
+ TangemPayTxHistoryItem.Status.RESERVED,
+ TangemPayTxHistoryItem.Status.UNKNOWN,
+ -> null
+ }
+ }
+ }
+
+ private fun Input.extractButtonState(): TangemPayTxHistoryDetailsUM.ButtonState {
+ return when (this.item) {
+ is TangemPayTxHistoryItem.Fee -> TangemPayTxHistoryDetailsUM.ButtonState(
+ text = resourceReference(R.string.tangem_pay_dispute),
+ onClick = this.onDisputeClick,
+ )
+ is TangemPayTxHistoryItem.Spend -> TangemPayTxHistoryDetailsUM.ButtonState(
+ text = resourceReference(R.string.tangem_pay_dispute),
+ onClick = this.onDisputeClick,
+ )
+ is TangemPayTxHistoryItem.Payment -> TangemPayTxHistoryDetailsUM.ButtonState(
+ text = resourceReference(R.string.tangem_pay_explore_transaction),
+ onClick = { this.onExplorerClick(this.item.transactionHash) },
+ )
+ }
+ }
+
+ data class Input(
+ val item: TangemPayTxHistoryItem,
+ val onExplorerClick: (String?) -> Unit,
+ val onDisputeClick: () -> Unit,
+ val onDismiss: () -> Unit,
+ )
+}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/InternalComponents.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/InternalComponents.kt
new file mode 100644
index 0000000000..874fab6548
--- /dev/null
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/InternalComponents.kt
@@ -0,0 +1,46 @@
+package com.tangem.features.tangempay.ui
+
+import androidx.annotation.DrawableRes
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.Icon
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.unit.Dp
+import coil.compose.rememberAsyncImagePainter
+import com.tangem.core.ui.res.TangemTheme
+
+@Composable
+internal fun RemoteIcon(url: String, modifier: Modifier = Modifier) {
+ Icon(
+ modifier = modifier.clip(CircleShape),
+ painter = rememberAsyncImagePainter(url),
+ contentDescription = null,
+ tint = Color.Unspecified,
+ )
+}
+
+@Composable
+internal fun LocalStaticIcon(@DrawableRes id: Int, iconSize: Dp, modifier: Modifier = Modifier) {
+ Box(
+ modifier = modifier.background(
+ color = TangemTheme.colors.icon.secondary.copy(alpha = 0.1F),
+ shape = CircleShape,
+ ),
+ ) {
+ Icon(
+ painter = painterResource(id),
+ contentDescription = null,
+ modifier = Modifier
+ .size(iconSize)
+ .align(Alignment.Center),
+ tint = TangemTheme.colors.icon.informative,
+ )
+ }
+}
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayTxHistoryUi.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayTxHistoryUi.kt
index bcaec6f86e..deddf2a265 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayTxHistoryUi.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangemPayTxHistoryUi.kt
@@ -1,13 +1,11 @@
package com.tangem.features.tangempay.ui
-import androidx.annotation.DrawableRes
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.itemsIndexed
-import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
@@ -15,7 +13,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
-import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
@@ -24,7 +21,6 @@ import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ChainStyle
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
-import coil.compose.rememberAsyncImagePainter
import com.tangem.core.ui.R
import com.tangem.core.ui.components.CircleShimmer
import com.tangem.core.ui.components.RectangleShimmer
@@ -264,47 +260,24 @@ private fun Icon(state: TangemPayTransactionState, modifier: Modifier = Modifier
if (state.iconUrl != null) {
RemoteIcon(modifier = modifier, url = state.iconUrl)
} else {
- LocalStaticIcon(modifier = modifier, id = R.drawable.ic_category_24)
+ LocalStaticIcon(
+ modifier = modifier,
+ id = R.drawable.ic_category_24,
+ iconSize = TangemTheme.dimens.size20,
+ )
}
}
- is TangemPayTransactionState.Content.Fee -> LocalStaticIcon(modifier = modifier, id = R.drawable.ic_percent_24)
+ is TangemPayTransactionState.Content.Fee -> LocalStaticIcon(
+ modifier = modifier,
+ id = R.drawable.ic_percent_24,
+ iconSize = TangemTheme.dimens.size20,
+ )
is TangemPayTransactionState.Content.Payment -> LocalStaticIcon(
modifier = modifier,
id = if (state.isIncome) R.drawable.ic_arrow_down_24 else R.drawable.ic_arrow_up_24,
+ iconSize = TangemTheme.dimens.size20,
)
- is TangemPayTransactionState.Loading -> {
- CircleShimmer(modifier = modifier.size(TangemTheme.dimens.size40))
- }
- }
-}
-
-@Composable
-private fun RemoteIcon(url: String, modifier: Modifier = Modifier) {
- Icon(
- modifier = modifier
- .size(TangemTheme.dimens.size40)
- .clip(CircleShape),
- painter = rememberAsyncImagePainter(url),
- contentDescription = null,
- tint = Color.Unspecified,
- )
-}
-
-@Composable
-private fun LocalStaticIcon(@DrawableRes id: Int, modifier: Modifier = Modifier) {
- Box(
- modifier = modifier
- .size(TangemTheme.dimens.size40)
- .background(color = TangemTheme.colors.icon.secondary.copy(alpha = 0.1F), shape = CircleShape),
- ) {
- Icon(
- painter = painterResource(id),
- contentDescription = null,
- modifier = Modifier
- .size(TangemTheme.dimens.size20)
- .align(Alignment.Center),
- tint = TangemTheme.colors.icon.informative,
- )
+ is TangemPayTransactionState.Loading -> CircleShimmer(modifier = modifier)
}
}
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUi.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUi.kt
new file mode 100644
index 0000000000..7d79f24a4e
--- /dev/null
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/ui/TangempayTxDetailsUi.kt
@@ -0,0 +1,241 @@
+package com.tangem.features.tangempay.ui
+
+import android.content.res.Configuration
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Devices
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.tooling.preview.PreviewParameter
+import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
+import androidx.compose.ui.unit.dp
+import com.tangem.core.ui.components.SecondaryButton
+import com.tangem.core.ui.components.SpacerH32
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
+import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
+import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
+import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
+import com.tangem.core.ui.components.label.Label
+import com.tangem.core.ui.components.label.entity.LabelStyle
+import com.tangem.core.ui.components.label.entity.LabelUM
+import com.tangem.core.ui.components.notifications.Notification
+import com.tangem.core.ui.components.notifications.NotificationConfig
+import com.tangem.core.ui.extensions.ImageReference
+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.extensions.themedColor
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.core.ui.res.TangemThemePreview
+import com.tangem.features.tangempay.details.impl.R
+import com.tangem.features.tangempay.entity.TangemPayTxHistoryDetailsUM
+
+@Composable
+internal fun TangemPayTxHistoryDetailsContent(state: TangemPayTxHistoryDetailsUM) {
+ TangemModalBottomSheet(
+ config = TangemBottomSheetConfig(
+ isShown = true,
+ onDismissRequest = state.dismiss,
+ content = TangemBottomSheetConfigContent.Empty,
+ ),
+ onBack = state.dismiss,
+ containerColor = TangemTheme.colors.background.tertiary,
+ title = {
+ TangemModalBottomSheetTitle(
+ title = state.title,
+ endIconRes = R.drawable.ic_close_24,
+ onEndClick = state.dismiss,
+ )
+ },
+ ) {
+ Column(
+ modifier = Modifier
+ .padding(horizontal = 16.dp)
+ .fillMaxWidth(),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Icon(
+ modifier = Modifier
+ .padding(top = 24.dp)
+ .size(88.dp),
+ iconState = state.iconState,
+ )
+ Text(
+ modifier = Modifier.padding(top = 32.dp),
+ text = state.transactionTitle.resolveReference(),
+ style = TangemTheme.typography.subtitle1,
+ color = TangemTheme.colors.text.primary1,
+ )
+ Text(
+ modifier = Modifier.padding(top = 2.dp),
+ text = state.transactionSubtitle.resolveReference(),
+ style = TangemTheme.typography.body2,
+ color = TangemTheme.colors.text.tertiary,
+ )
+ Text(
+ modifier = Modifier.padding(top = 8.dp),
+ text = state.transactionAmount,
+ style = TangemTheme.typography.head,
+ color = state.transactionAmountColor.resolveReference(),
+ )
+ state.labelState?.let { Label(state = state.labelState, modifier = Modifier.padding(top = 12.dp)) }
+ SpacerH32()
+ state.notification?.let {
+ Notification(
+ config = state.notification,
+ titleColor = TangemTheme.colors.text.tertiary,
+ iconTint = TangemTheme.colors.icon.secondary,
+ )
+ }
+ ButtonContainer(
+ modifier = Modifier
+ .padding(vertical = 16.dp)
+ .fillMaxWidth(),
+ buttonState = state.buttonState,
+ )
+ }
+ }
+}
+
+@Composable
+private fun ButtonContainer(buttonState: TangemPayTxHistoryDetailsUM.ButtonState, modifier: Modifier = Modifier) {
+ SecondaryButton(modifier = modifier, text = buttonState.text.resolveReference(), onClick = buttonState.onClick)
+}
+
+@Composable
+private fun Icon(iconState: ImageReference, modifier: Modifier = Modifier) {
+ when (iconState) {
+ is ImageReference.Res -> LocalStaticIcon(modifier = modifier, id = iconState.resId, iconSize = 40.dp)
+ is ImageReference.Url -> RemoteIcon(modifier = modifier, url = iconState.url)
+ }
+}
+
+@Preview(device = Devices.PIXEL_7_PRO)
+@Preview(device = Devices.PIXEL_7_PRO, uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+private fun TangemPayTxHistoryDetailsContentPreview(
+ @PreviewParameter(TangemPayTxHistoryDetailsUMProvider::class) state: TangemPayTxHistoryDetailsUM,
+) {
+ TangemThemePreview {
+ TangemPayTxHistoryDetailsContent(state = state)
+ }
+}
+
+private class TangemPayTxHistoryDetailsUMProvider : CollectionPreviewParameterProvider(
+ listOf(
+ TangemPayTxHistoryDetailsUM(
+ title = stringReference("12 June • 12:40"),
+ iconState = ImageReference.Res(R.drawable.ic_category_24),
+ transactionTitle = stringReference("Starbucks"),
+ transactionSubtitle = stringReference("Food and drinks"),
+ transactionAmount = "-$5.86",
+ transactionAmountColor = themedColor { TangemTheme.colors.text.primary1 },
+ labelState = LabelUM(
+ text = resourceReference(R.string.tangem_pay_status_pending),
+ style = LabelStyle.REGULAR,
+ icon = R.drawable.ic_clock_24,
+ ),
+ notification = null,
+ buttonState = TangemPayTxHistoryDetailsUM.ButtonState(
+ text = stringReference("Dispute"),
+ onClick = {},
+ ),
+ dismiss = {},
+ ),
+ TangemPayTxHistoryDetailsUM(
+ title = stringReference("12 June • 12:40"),
+ iconState = ImageReference.Res(R.drawable.ic_category_24),
+ transactionTitle = stringReference("Starbucks"),
+ transactionSubtitle = stringReference("Food and drinks"),
+ transactionAmount = "-$5.86",
+ transactionAmountColor = themedColor { TangemTheme.colors.text.warning },
+ labelState = LabelUM(
+ text = resourceReference(R.string.tangem_pay_status_declined),
+ style = LabelStyle.WARNING,
+ ),
+ notification = NotificationConfig(
+ title = stringReference("The bank rejected this transaction request."),
+ subtitle = TextReference.EMPTY,
+ iconResId = R.drawable.ic_token_info_24,
+ ),
+ buttonState = TangemPayTxHistoryDetailsUM.ButtonState(
+ text = stringReference("Dispute"),
+ onClick = {},
+ ),
+ dismiss = {},
+ ),
+ TangemPayTxHistoryDetailsUM(
+ title = stringReference("12 June • 12:40"),
+ iconState = ImageReference.Res(R.drawable.ic_category_24),
+ transactionTitle = stringReference("Starbucks"),
+ transactionSubtitle = stringReference("Food and drinks"),
+ transactionAmount = "-$5.86",
+ transactionAmountColor = themedColor { TangemTheme.colors.text.primary1 },
+ labelState = LabelUM(
+ text = resourceReference(R.string.tangem_pay_status_completed),
+ style = LabelStyle.ACCENT,
+ ),
+ notification = null,
+ buttonState = TangemPayTxHistoryDetailsUM.ButtonState(
+ text = stringReference("Dispute"),
+ onClick = {},
+ ),
+ dismiss = {},
+ ),
+ TangemPayTxHistoryDetailsUM(
+ title = stringReference("12 June • 12:40"),
+ iconState = ImageReference.Res(R.drawable.ic_percent_24),
+ transactionTitle = stringReference("Fee"),
+ transactionSubtitle = stringReference("Service fee"),
+ transactionAmount = "-$5.86",
+ transactionAmountColor = themedColor { TangemTheme.colors.text.primary1 },
+ labelState = null,
+ notification = NotificationConfig(
+ title = stringReference("This fee goes to cover the cost of handling your transfer."),
+ subtitle = TextReference.EMPTY,
+ iconResId = R.drawable.ic_token_info_24,
+ ),
+ buttonState = TangemPayTxHistoryDetailsUM.ButtonState(
+ text = stringReference("Dispute"),
+ onClick = {},
+ ),
+ dismiss = {},
+ ),
+ TangemPayTxHistoryDetailsUM(
+ title = stringReference("12 June • 12:40"),
+ iconState = ImageReference.Res(R.drawable.ic_arrow_down_24),
+ transactionTitle = stringReference("Deposit"),
+ transactionSubtitle = stringReference("Transfers"),
+ transactionAmount = "+$20",
+ transactionAmountColor = themedColor { TangemTheme.colors.text.accent },
+ labelState = null,
+ notification = null,
+ buttonState = TangemPayTxHistoryDetailsUM.ButtonState(
+ text = stringReference("Explore transaction"),
+ onClick = {},
+ ),
+ dismiss = {},
+ ),
+ TangemPayTxHistoryDetailsUM(
+ title = stringReference("12 June • 12:40"),
+ iconState = ImageReference.Res(R.drawable.ic_arrow_up_24),
+ transactionTitle = stringReference("Withdrawal"),
+ transactionSubtitle = stringReference("Transfers"),
+ transactionAmount = "-$5.86",
+ transactionAmountColor = themedColor { TangemTheme.colors.text.primary1 },
+ labelState = null,
+ notification = null,
+ buttonState = TangemPayTxHistoryDetailsUM.ButtonState(
+ text = stringReference("Explore transaction"),
+ onClick = {},
+ ),
+ dismiss = {},
+ ),
+ ),
+)
\ No newline at end of file
diff --git a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/utils/TangemPayErrorMessageFactory.kt b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/utils/TangemPayErrorMessageFactory.kt
index 2f5ce481ea..6aa000667c 100644
--- a/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/utils/TangemPayErrorMessageFactory.kt
+++ b/features/tangempay/details/impl/src/main/kotlin/com/tangem/features/tangempay/utils/TangemPayErrorMessageFactory.kt
@@ -4,13 +4,15 @@ import com.tangem.core.ui.R
import com.tangem.core.ui.components.bottomsheets.message.*
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.message.BottomSheetMessageV2
+import com.tangem.core.ui.message.bottomSheetMessage
import com.tangem.features.tangempay.entity.TangemPayDetailsErrorType
internal object TangemPayErrorMessageFactory {
- fun createError(type: TangemPayDetailsErrorType, onDismiss: () -> Unit): MessageBottomSheetUMV2 {
+ fun createErrorMessage(type: TangemPayDetailsErrorType): BottomSheetMessageV2 {
return when (type) {
- TangemPayDetailsErrorType.Receive -> messageBottomSheetUM {
+ TangemPayDetailsErrorType.Receive -> bottomSheetMessage {
infoBlock {
icon(R.drawable.img_attention_20) {
backgroundType = MessageBottomSheetUMV2.Icon.BackgroundType.Attention
@@ -20,7 +22,7 @@ internal object TangemPayErrorMessageFactory {
}
primaryButton {
text = resourceReference(R.string.common_got_it)
- onClick { onDismiss() }
+ onClick { closeBs() }
}
}
}
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt
index ebf62b0e39..292e3b3ad9 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt
@@ -365,7 +365,12 @@ internal class WalletModel @Inject constructor(
value = info,
onClickIssue = ::issueOrder,
onClickKyc = innerWalletRouter::openTangemPayOnboarding,
- openDetails = innerWalletRouter::openTangemPayDetails,
+ openDetails = { config ->
+ innerWalletRouter.openTangemPayDetails(
+ userWalletId = stateHolder.getSelectedWalletId(),
+ config = config,
+ )
+ },
),
)
}
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt
index 8213172d17..4fed890be6 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/DefaultWalletRouter.kt
@@ -109,8 +109,8 @@ internal class DefaultWalletRouter @Inject constructor(
router.push(AppRoute.TangemPayOnboarding(AppRoute.TangemPayOnboarding.Mode.ContinueOnboarding))
}
- override fun openTangemPayDetails(config: TangemPayDetailsConfig) {
- router.push(AppRoute.TangemPayDetails(config))
+ override fun openTangemPayDetails(userWalletId: UserWalletId, config: TangemPayDetailsConfig) {
+ router.push(AppRoute.TangemPayDetails(userWalletId = userWalletId, config = config))
}
override fun openYieldSupplyBottomSheet(
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt
index d869ca8b84..120a13a248 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/router/InnerWalletRouter.kt
@@ -60,7 +60,7 @@ internal interface InnerWalletRouter {
fun openTangemPayOnboarding()
- fun openTangemPayDetails(config: TangemPayDetailsConfig)
+ fun openTangemPayDetails(userWalletId: UserWalletId, config: TangemPayDetailsConfig)
/** Open BS abput yield supply active and all money deposited in AAVE */
fun openYieldSupplyBottomSheet(