From 67095aaa51725b72319ba47f8351c65311ca6cb5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 3 Aug 2022 10:20:11 +0300 Subject: [PATCH 01/10] Updated on 2026-08-14 --- app/build.gradle | 6 +++--- dependencies.gradle | 4 ++-- domain/build.gradle | 6 +++--- network/build.gradle | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index ce5b525f66..c37a4da509 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -92,9 +92,9 @@ dependencies { implementation 'com.google.android.play:core-ktx:1.8.1' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' - implementation "com.tangem:blockchain:${versions.tamgem_blockchain_sdk}" - implementation "com.tangem.tangem-sdk-kotlin:core:${versions.tamgem_card_sdk}" - implementation "com.tangem.tangem-sdk-kotlin:android:${versions.tamgem_card_sdk}" + implementation "com.tangem:blockchain:${versions.tangem_blockchain_sdk}" + implementation "com.tangem.tangem-sdk-kotlin:core:${versions.tangem_card_sdk}" + implementation "com.tangem.tangem-sdk-kotlin:android:${versions.tangem_card_sdk}" // WebView implementation "androidx.browser:browser:1.3.0" diff --git a/dependencies.gradle b/dependencies.gradle index cbd16111f5..adc97e0523 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,8 +1,8 @@ ext.versions = [ kotlin : '1.6.10', build_gradle : '7.1.3', - tamgem_card_sdk : 'develop-157', - tamgem_blockchain_sdk: 'develop-99', + tangem_card_sdk : 'develop-157', + tangem_blockchain_sdk: 'develop-99', ] ext.environmentConfig = [ diff --git a/domain/build.gradle b/domain/build.gradle index f4b0183cc8..0ea2f21fdf 100644 --- a/domain/build.gradle +++ b/domain/build.gradle @@ -59,9 +59,9 @@ dependencies { implementation implementation(project(path: ':network')) implementation implementation(project(path: ':common')) - implementation "com.tangem:blockchain:${versions.tamgem_blockchain_sdk}" - implementation "com.tangem.tangem-sdk-kotlin:core:${versions.tamgem_card_sdk}" - implementation "com.tangem.tangem-sdk-kotlin:android:${versions.tamgem_card_sdk}" + implementation "com.tangem:blockchain:${versions.tangem_blockchain_sdk}" + implementation "com.tangem.tangem-sdk-kotlin:core:${versions.tangem_card_sdk}" + implementation "com.tangem.tangem-sdk-kotlin:android:${versions.tangem_card_sdk}" // Kotlin coroutines implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2' diff --git a/network/build.gradle b/network/build.gradle index dce3040c09..e7fccceda6 100644 --- a/network/build.gradle +++ b/network/build.gradle @@ -12,7 +12,7 @@ dependencies { implementation implementation(project(path: ':common')) // Tangem sdk's - implementation "com.tangem.tangem-sdk-kotlin:core:${versions.tamgem_card_sdk}" + implementation "com.tangem.tangem-sdk-kotlin:core:${versions.tangem_card_sdk}" // Kotlin coroutines implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2' From 90589b7de1d0479b05608bded70bf4abeb07f070 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 3 Aug 2022 10:21:05 +0300 Subject: [PATCH 02/10] Updated on 2026-08-14 --- .../tap/common/extensions/AnalyticsHandler.kt | 51 ++++++ .../java/com/tangem/tap/domain/TapErrors.kt | 4 - .../walletconnect/WalletConnectSdkHelper.kt | 18 +- .../tangem/tap/features/demo/DemoHelper.kt | 10 +- .../features/send/redux/SendScreenAction.kt | 6 +- .../send/redux/middlewares/SendMiddleware.kt | 157 +++++++++--------- .../ui/dialogs/SendTransactionFailsDialog.kt | 17 +- .../stateSubscribers/SendStateSubscriber.kt | 27 ++- app/src/main/res/values-ru/strings.xml | 2 +- .../main/res/values/strings_untranslated.xml | 2 +- dependencies.gradle | 5 +- 11 files changed, 192 insertions(+), 107 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/extensions/AnalyticsHandler.kt diff --git a/app/src/main/java/com/tangem/tap/common/extensions/AnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/extensions/AnalyticsHandler.kt new file mode 100644 index 0000000000..f2897e2b63 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/extensions/AnalyticsHandler.kt @@ -0,0 +1,51 @@ +package com.tangem.tap.common.extensions + +import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.tangem.blockchain.common.BlockchainError +import com.tangem.blockchain.common.BlockchainSdkError +import com.tangem.common.card.Card +import com.tangem.common.core.TangemSdkError +import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.analytics.AnalyticsHandler +import com.tangem.tap.common.analytics.AnalyticsParam +import com.tangem.tap.features.demo.DemoTransactionSender + +/** +[REDACTED_AUTHOR] + */ +fun AnalyticsHandler.logSendTransactionError( + error: BlockchainError, + action: Analytics.ActionToLog, + parameters: Map? = mapOf(), + card: Card? = null, +) { + when (val blockchainSdkError = (error as BlockchainSdkError)) { + is BlockchainSdkError.WrappedTangemError -> { + val tangemSdkError = (blockchainSdkError.tangemError as? TangemSdkError) ?: return + + logCardSdkError( + error = tangemSdkError, + actionToLog = action, + parameters = parameters, + card = card, + ) + } + else -> { + when { + blockchainSdkError.customMessage.contains(DemoTransactionSender.ID) -> return + else -> { + val params = parameters?.toMutableMap() ?: mutableMapOf() + params[AnalyticsParam.ACTION] = action.key + params[AnalyticsParam.ERROR_CODE] = error.code.toString() + params[AnalyticsParam.ERROR_DESCRIPTION] = "${error.javaClass.simpleName}: ${error.customMessage}" + params[AnalyticsParam.ERROR_KEY] = "BlockchainSdkError" + + FirebaseCrashlytics.getInstance().apply { + params.forEach { setCustomKey(it.key.param, it.value) } + recordException(error) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt index ff19d10171..9d3cc79eee 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapErrors.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapErrors.kt @@ -44,10 +44,6 @@ sealed class TapError( val customMessage: String = "Unsupported state:" ) : TapError(R.string.common_custom_string, listOf("$customMessage $stateError")) - sealed class XmlError { - object AssetAccountNotCreated : TapError(R.string.send_error_no_account_xlm) - } - sealed class WalletManager { object CreationError : CustomError("Can't create wallet manager") class NoAccountError(amountToCreateAccount: String) : CustomError(amountToCreateAccount) diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt index a3b0d31a89..04f1ec8141 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt @@ -7,6 +7,7 @@ import com.tangem.blockchain.blockchains.ethereum.EthereumUtils import com.tangem.blockchain.blockchains.ethereum.EthereumUtils.Companion.toKeccak import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.AmountType +import com.tangem.blockchain.common.BlockchainSdkError import com.tangem.blockchain.common.CommonSigner import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.TransactionSender @@ -24,6 +25,7 @@ import com.tangem.common.extensions.toHexString import com.tangem.crypto.CryptoUtils import com.tangem.operations.sign.SignHashCommand import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.extensions.logSendTransactionError import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.common.extensions.toFormattedString import com.tangem.tap.features.details.redux.walletconnect.WalletConnectSession @@ -38,8 +40,8 @@ import com.tangem.tap.tangemSdk import com.tangem.tap.tangemSdkManager import com.trustwallet.walletconnect.models.ethereum.WCEthereumSignMessage import com.trustwallet.walletconnect.models.ethereum.WCEthereumTransaction -import java.math.BigDecimal import timber.log.Timber +import java.math.BigDecimal class WalletConnectSdkHelper { @@ -69,7 +71,7 @@ class WalletConnectSdkHelper { (walletManager as? EthereumGasLoader)?.getGasPrice()) { is Result.Success -> result.data.toBigDecimal() is Result.Failure -> { - Timber.e(result.error) + (result.error as? Throwable)?.let { Timber.e(it) } return null } null -> return null @@ -143,13 +145,11 @@ class WalletConnectSdkHelper { HEX_PREFIX + data.walletManager.wallet.recentTransactions.last().hash } is SimpleResult.Failure -> { - (result.error as? TangemSdkError)?.let { error -> - store.state.globalState.analyticsHandlers?.logCardSdkError( - error, - Analytics.ActionToLog.WalletConnectTransaction, - ) - } - Timber.e(result.error) + store.state.globalState.analyticsHandlers?.logSendTransactionError( + result.error, + Analytics.ActionToLog.WalletConnectTransaction, + ) + Timber.e(result.error as BlockchainSdkError) null } } diff --git a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt index f7ccf6156a..5248797a0f 100644 --- a/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/demo/DemoHelper.kt @@ -1,7 +1,13 @@ package com.tangem.tap.features.demo import com.tangem.blockchain.blockchains.bitcoin.BitcoinWalletManager -import com.tangem.blockchain.common.* +import com.tangem.blockchain.common.Amount +import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.TransactionData +import com.tangem.blockchain.common.TransactionSender +import com.tangem.blockchain.common.TransactionSigner +import com.tangem.blockchain.common.WalletManager +import com.tangem.blockchain.common.toBlockchainCustomError import com.tangem.blockchain.extensions.Result import com.tangem.blockchain.extensions.SimpleResult import com.tangem.common.CompletionResult @@ -289,7 +295,7 @@ class DemoTransactionSender( publicKey = walletManager.wallet.publicKey ) return when (signerResponse) { - is CompletionResult.Success -> SimpleResult.Failure(Exception(ID)) + is CompletionResult.Success -> SimpleResult.Failure(Exception(ID).toBlockchainCustomError()) is CompletionResult.Failure -> SimpleResult.fromTangemSdkError(signerResponse.error) } } diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt index 2ed9fe33e0..8c76739e6b 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/SendScreenAction.kt @@ -4,6 +4,7 @@ import com.tangem.Message import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.WalletManager +import com.tangem.common.core.TangemSdkError import com.tangem.tap.common.redux.ErrorAction import com.tangem.tap.common.redux.StateDialog import com.tangem.tap.common.redux.ToastNotificationAction @@ -155,7 +156,10 @@ sealed class SendAction : SendScreenAction { val reduceAmount: BigDecimal, ) : Dialog() - data class SendTransactionFails(val errorMessage: String) : Dialog() + sealed class SendTransactionFails : Dialog() { + data class CardSdkError(val error: TangemSdkError): Dialog() + data class BlockchainSdkError(val error: com.tangem.blockchain.common.BlockchainSdkError): Dialog() + } object Hide : Dialog() } diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt index 4a1f2df785..5eaa250690 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/middlewares/SendMiddleware.kt @@ -22,6 +22,7 @@ import com.tangem.tap.common.analytics.AnalyticsParam import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchErrorNotification import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.common.extensions.logSendTransactionError import com.tangem.tap.common.extensions.safeUpdate import com.tangem.tap.common.extensions.stripZeroPlainString import com.tangem.tap.common.redux.AppDialog @@ -52,14 +53,13 @@ import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdk import com.tangem.wallet.R -import java.util.EnumSet import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.rekotlin.Action import org.rekotlin.Middleware -import timber.log.Timber +import java.util.* /** [REDACTED_AUTHOR] @@ -79,13 +79,19 @@ class SendMiddleware { is SendActionUi.CheckIfTransactionDataWasProvided -> { val transactionData = appState()?.sendState?.externalTransactionData if (transactionData != null) { - store.dispatchOnMain(AddressPayIdVerifyAction.AddressVerification.SetWalletAddress( - transactionData.destinationAddress, false - )) + store.dispatchOnMain( + AddressPayIdVerifyAction.AddressVerification.SetWalletAddress( + transactionData.destinationAddress, false, + ), + ) store.dispatchOnMain(AmountActionUi.SetMainCurrency(MainCurrencyType.CRYPTO)) store.dispatchOnMain(AmountActionUi.HandleUserInput(transactionData.amount)) - store.dispatchOnMain(AmountAction.SetAmount(transactionData.amount.toBigDecimal(), - false)) + store.dispatchOnMain( + AmountAction.SetAmount( + transactionData.amount.toBigDecimal(), + false, + ), + ) } } } @@ -93,7 +99,6 @@ class SendMiddleware { } } } - } private fun verifyAndSendTransaction( @@ -113,23 +118,31 @@ private fun verifyAndSendTransaction( when { hadTezosError -> { val reduceAmount = walletManager.wallet.blockchain.minimalAmount() - dispatch(SendAction.Dialog.TezosWarningDialog(reduceCallback = { - dispatch(AmountAction.SetAmount(typedAmount.value!!.minus(reduceAmount), false)) - dispatch(AmountActionUi.CheckAmountToSend) - }, sendAllCallback = { - sendTransaction( - action, walletManager, amountToSend, feeAmount, destinationAddress, - sendState.transactionExtrasState, card, sendState.externalTransactionData, - dispatch - ) - }, reduceAmount)) + dispatch( + SendAction.Dialog.TezosWarningDialog( + reduceCallback = { + dispatch(AmountAction.SetAmount(typedAmount.value!!.minus(reduceAmount), false)) + dispatch(AmountActionUi.CheckAmountToSend) + }, + sendAllCallback = { + sendTransaction( + action, walletManager, amountToSend, feeAmount, destinationAddress, + sendState.transactionExtrasState, card, sendState.externalTransactionData, + dispatch, + ) + }, + reduceAmount, + ), + ) } transactionErrors.isNotEmpty() -> { dispatch(SendAction.SendError(createValidateTransactionError(transactionErrors, walletManager))) } else -> { - sendTransaction(action, walletManager, amountToSend, feeAmount, destinationAddress, - sendState.transactionExtrasState, card, sendState.externalTransactionData, dispatch) + sendTransaction( + action, walletManager, amountToSend, feeAmount, destinationAddress, + sendState.transactionExtrasState, card, sendState.externalTransactionData, dispatch, + ) } } } @@ -150,7 +163,9 @@ private fun sendTransaction( transactionExtras.xlmMemo?.memo?.let { txData = txData.copy(extras = StellarTransactionExtras(it)) } transactionExtras.binanceMemo?.memo?.let { txData = txData.copy(extras = BinanceTransactionExtras(it.toString())) } - transactionExtras.xrpDestinationTag?.tag?.let { txData = txData.copy(extras = XrpTransactionBuilder.XrpTransactionExtras(it)) } + transactionExtras.xrpDestinationTag?.tag?.let { + txData = txData.copy(extras = XrpTransactionBuilder.XrpTransactionExtras(it)) + } scope.launch { val updateWalletResult = walletManager.safeUpdate() @@ -178,14 +193,14 @@ private fun sendTransaction( val signer = TangemSigner( card = card, tangemSdk = tangemSdk, - initialMessage = action.messageForSigner + initialMessage = action.messageForSigner, ) { signResponse -> store.dispatch( GlobalAction.UpdateWalletSignedHashes( walletSignedHashes = signResponse.totalSignedHashes, walletPublicKey = walletManager.wallet.publicKey.seedKey, - remainingSignatures = signResponse.remainingSignatures - ) + remainingSignatures = signResponse.remainingSignatures, + ), ) } val sendResult = try { @@ -211,7 +226,7 @@ private fun sendTransaction( store.state.globalState.analyticsHandlers?.triggerEvent( event = AnalyticsEvent.TRANSACTION_IS_SENT, card = card, - blockchain = walletManager.wallet.blockchain.currency + blockchain = walletManager.wallet.blockchain.currency, ) dispatch(SendAction.SendSuccess) @@ -231,69 +246,48 @@ private fun sendTransaction( } } is SimpleResult.Failure -> { - when (sendResult.error) { + store.state.globalState.feedbackManager?.infoHolder?.updateOnSendError( + wallet = walletManager.wallet, + host = walletManager.currentHost, + amountToSend = amountToSend, + feeAmount = feeAmount, + destinationAddress = destinationAddress, + ) + store.state.globalState.analyticsHandlers?.logSendTransactionError( + error = sendResult.error, + action = Analytics.ActionToLog.SendTransaction, + parameters = mapOf(AnalyticsParam.BLOCKCHAIN to walletManager.wallet.blockchain.currency), + card = card, + ) + + val error = (sendResult.error as? BlockchainSdkError) ?: return@withContext + + when (error) { + is BlockchainSdkError.WrappedTangemError -> { + val tangemSdkError = (error.tangemError as? TangemSdkError) ?: return@withContext + if (tangemSdkError is TangemSdkError.UserCancelled) return@withContext + + dispatch(SendAction.Dialog.SendTransactionFails.CardSdkError(tangemSdkError)) + } is BlockchainSdkError.CreateAccountUnderfunded -> { - val error = sendResult.error as BlockchainSdkError.CreateAccountUnderfunded + // from XLM, XRP val reserve = error.minReserve.value?.stripZeroPlainString() ?: "0" val symbol = error.minReserve.currencySymbol dispatch(SendAction.SendError(TapError.CreateAccountUnderfunded(listOf(reserve, symbol)))) } - is BlockchainSdkError.SendException -> { - sendResult.error?.let { FirebaseCrashlytics.getInstance().recordException(it) } - } - is Throwable -> { - val throwable = sendResult.error as Throwable - val message = throwable.message - val infoHolder = store.state.globalState.feedbackManager?.infoHolder + else -> { when { - message == null -> { - dispatch(SendAction.SendError(TapError.UnknownError)) - infoHolder?.updateOnSendError( - wallet = walletManager.wallet, - host = walletManager.currentHost, - amountToSend = amountToSend, - feeAmount = feeAmount, - destinationAddress = destinationAddress + error.customMessage.contains(DemoTransactionSender.ID) -> { + store.dispatchDialogShow( + AppDialog.SimpleOkDialogRes( + headerId = R.string.common_done, + messageId = R.string.alert_demo_feature_disabled, + onOk = { dispatch(NavigationAction.PopBackTo()) }, + ), ) - dispatch(SendAction.Dialog.SendTransactionFails("unknown error")) - } - message.contains("50002") -> { - // user was cancelled the operation by closing the Sdk bottom sheet - } - // make it easier latter by handling an appropriate enumError or, like on iOS, - // accept a string identifier of the error message - message.contains("Target account is not created. To create account send 1+ XLM.") -> { - dispatch(SendAction.SendError(TapError.XmlError.AssetAccountNotCreated)) - } - message.contains(DemoTransactionSender.ID) -> { - delay(DELAY_SDK_DIALOG_CLOSE) - store.dispatchDialogShow(AppDialog.SimpleOkDialogRes( - R.string.common_done, - R.string.alert_demo_feature_disabled - ) { dispatch(NavigationAction.PopBackTo()) }) } else -> { - (sendResult.error as? TangemSdkError)?.let { error -> - store.state.globalState.analyticsHandlers?.logCardSdkError( - error, - Analytics.ActionToLog.SendTransaction, - mapOf( - AnalyticsParam.BLOCKCHAIN - to walletManager.wallet.blockchain.currency), - card = card, - ) - } - Timber.e(throwable) - FirebaseCrashlytics.getInstance().recordException(throwable) - dispatch(SendAction.SendError(TapError.CustomError(message))) - infoHolder?.updateOnSendError( - wallet = walletManager.wallet, - host = walletManager.currentHost, - amountToSend = amountToSend, - feeAmount = feeAmount, - destinationAddress = destinationAddress - ) - dispatch(SendAction.Dialog.SendTransactionFails(message)) + dispatch(SendAction.Dialog.SendTransactionFails.BlockchainSdkError(error)) } } } @@ -328,7 +322,10 @@ fun extractErrorsForAmountField(errors: EnumSet): EnumSet, walletManager: WalletManager): TapError.ValidateTransactionErrors { +fun createValidateTransactionError( + errorList: EnumSet, + walletManager: WalletManager, +): TapError.ValidateTransactionErrors { val tapErrors = errorList.map { when (it) { TransactionError.AmountExceedsBalance -> TapError.AmountExceedsBalance diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/SendTransactionFailsDialog.kt b/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/SendTransactionFailsDialog.kt index 6eccfef665..a01c048058 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/SendTransactionFailsDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/SendTransactionFailsDialog.kt @@ -2,6 +2,7 @@ package com.tangem.tap.features.send.ui.dialogs import android.content.Context import androidx.appcompat.app.AlertDialog +import com.tangem.tangem_sdk_new.extensions.localizedDescription import com.tangem.tap.common.feedback.SendTransactionFailedEmail import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.send.redux.SendAction @@ -14,14 +15,22 @@ import com.tangem.wallet.R class SendTransactionFailsDialog { companion object { - fun create(context: Context, dialog: SendAction.Dialog.SendTransactionFails): AlertDialog { + fun create(context: Context, dialog: SendAction.Dialog.SendTransactionFails.CardSdkError): AlertDialog { + return create(context, dialog.error.localizedDescription(context)) + } + + fun create(context: Context, dialog: SendAction.Dialog.SendTransactionFails.BlockchainSdkError): AlertDialog { + return create(context, dialog.error.customMessage) + } + + private fun create(context: Context, errorMessage: String): AlertDialog { return AlertDialog.Builder(context).apply { setTitle(R.string.alert_failed_to_send_transaction_title) - setMessage(context.getString(R.string.alert_failed_to_send_transaction_message, dialog.errorMessage)) + setMessage(context.getString(R.string.alert_failed_to_send_transaction_message, errorMessage)) setNeutralButton(R.string.alert_button_send_feedback) { _, _ -> - store.dispatch(GlobalAction.SendEmail(SendTransactionFailedEmail(dialog.errorMessage))) + store.dispatch(GlobalAction.SendEmail(SendTransactionFailedEmail(errorMessage))) } - setPositiveButton(R.string.common_no) { _, _ -> } + setPositiveButton(R.string.common_cancel) { _, _ -> } setOnDismissListener { store.dispatch(SendAction.Dialog.Hide) } }.create() } diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt index 2b71c1ba31..4496bd570b 100644 --- a/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt +++ b/app/src/main/java/com/tangem/tap/features/send/ui/stateSubscribers/SendStateSubscriber.kt @@ -8,7 +8,12 @@ import android.view.View import android.view.ViewGroup import androidx.core.text.bold import com.tangem.common.extensions.remove -import com.tangem.tap.common.extensions.* +import com.tangem.tap.common.extensions.beginDelayedTransition +import com.tangem.tap.common.extensions.enableError +import com.tangem.tap.common.extensions.getColor +import com.tangem.tap.common.extensions.getString +import com.tangem.tap.common.extensions.show +import com.tangem.tap.common.extensions.update import com.tangem.tap.common.redux.getMessageString import com.tangem.tap.common.text.DecimalDigitsInputFilter import com.tangem.tap.domain.MultiMessageError @@ -17,7 +22,17 @@ import com.tangem.tap.features.BaseStoreFragment import com.tangem.tap.features.send.redux.AddressPayIdVerifyAction.Error import com.tangem.tap.features.send.redux.FeeAction import com.tangem.tap.features.send.redux.SendAction -import com.tangem.tap.features.send.redux.states.* +import com.tangem.tap.features.send.redux.states.AddressPayIdState +import com.tangem.tap.features.send.redux.states.AmountState +import com.tangem.tap.features.send.redux.states.FeeState +import com.tangem.tap.features.send.redux.states.MainCurrencyType +import com.tangem.tap.features.send.redux.states.ReceiptLayoutType +import com.tangem.tap.features.send.redux.states.ReceiptState +import com.tangem.tap.features.send.redux.states.SendState +import com.tangem.tap.features.send.redux.states.StateId +import com.tangem.tap.features.send.redux.states.TransactionExtraError +import com.tangem.tap.features.send.redux.states.TransactionExtrasState +import com.tangem.tap.features.send.redux.states.XlmMemoType import com.tangem.tap.features.send.ui.FeeUiHelper import com.tangem.tap.features.send.ui.SendFragment import com.tangem.tap.features.send.ui.dialogs.SendTransactionFailsDialog @@ -117,7 +132,13 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : dialog?.show() } } - is SendAction.Dialog.SendTransactionFails -> { + is SendAction.Dialog.SendTransactionFails.CardSdkError -> { + if (dialog == null) { + dialog = SendTransactionFailsDialog.create(fg.requireContext(), state.dialog) + dialog?.show() + } + } + is SendAction.Dialog.SendTransactionFails.BlockchainSdkError -> { if (dialog == null) { dialog = SendTransactionFailsDialog.create(fg.requireContext(), state.dialog) dialog?.show() diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 1fbdfd7a66..c130eaae63 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -159,7 +159,7 @@ Не удалось отправить электронное письмо Причина: %s Не могу отправить транзакцию - Причина: %s. Хотите отправить отзыв? + Причина: %s У Вас возникли трудности со сканированием вашей карты? Пожалуйста, попробуйте приложить карту точно так, как показано на анимации, или обратитесь в поддержку Отмена diff --git a/app/src/main/res/values/strings_untranslated.xml b/app/src/main/res/values/strings_untranslated.xml index 84f36c07bf..215e7351fa 100644 --- a/app/src/main/res/values/strings_untranslated.xml +++ b/app/src/main/res/values/strings_untranslated.xml @@ -55,7 +55,7 @@ Failed to send email Reason: %s Can\'t send a transaction - Reason: %s. Do you want to send feedback? + Reason: %s Are you having difficulty scanning your card? Please try to tap the card exactly as shown in the animation or request support. I\'m okay diff --git a/dependencies.gradle b/dependencies.gradle index adc97e0523..44bf47e268 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,8 +1,9 @@ ext.versions = [ kotlin : '1.6.10', build_gradle : '7.1.3', - tangem_card_sdk : 'develop-157', - tangem_blockchain_sdk: 'develop-99', + tangem_card_sdk : 'develop-159', + // tangem_blockchain_sdk: 'develop-99', + tangem_blockchain_sdk: '0.0.1', ] ext.environmentConfig = [ From 4646e3b5c63233e6ee41af1499c251e159189c59 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 3 Aug 2022 14:12:22 +0300 Subject: [PATCH 03/10] Updated on 2026-08-14 --- .../wallet/ui/images/CurrencyIconRequest.kt | 17 +---- .../wallet/ui/images/CurrencyIconView.kt | 58 +++++++++++++-- .../main/res/layout/view_currency_icon.xml | 73 +++++++++++++++---- 3 files changed, 110 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconRequest.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconRequest.kt index 41076760dc..cd7959319e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconRequest.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconRequest.kt @@ -19,22 +19,7 @@ import com.tangem.wallet.R private const val QCX = "QCX" private const val VOYR = "VOYRME" -fun loadCurrencyIcon( - currencyImageView: CurrencyIconView, - currencyTextView: TextView, - token: Token?, - blockchain: Blockchain, -) { - CurrencyIconLoader( - currencyImageView = currencyImageView.imageView, - currencyTextView = currencyTextView, - token = token, - blockchain = blockchain - ) - .load() -} - -private class CurrencyIconLoader( +class CurrencyIconRequest( private val currencyImageView: ImageFilterView, private val currencyTextView: TextView, private val token: Token?, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt index b973c9cc52..ec9ff38519 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/images/CurrencyIconView.kt @@ -3,27 +3,69 @@ package com.tangem.tap.features.wallet.ui.images import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater +import android.widget.TextView +import androidx.annotation.DrawableRes import androidx.constraintlayout.utils.widget.ImageFilterView -import com.google.android.material.card.MaterialCardView +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.isVisible +import com.tangem.blockchain.common.DerivationStyle import com.tangem.tangem_sdk_new.extensions.dpToPx +import com.tangem.tap.common.extensions.getRoundIconRes +import com.tangem.tap.features.wallet.models.Currency import com.tangem.wallet.databinding.ViewCurrencyIconBinding +import kotlin.math.roundToInt class CurrencyIconView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, -) : MaterialCardView(context, attrs, defStyleAttr) { +) : ConstraintLayout(context, attrs, defStyleAttr) { private val binding = ViewCurrencyIconBinding.inflate( LayoutInflater.from(context), - this + this, ) - val imageView: ImageFilterView - get() = binding.iv + private val currencyImageView: ImageFilterView + get() = binding.ivCurrency + + private val currencyTextView: TextView + get() = binding.tvTokenLetter + + private var isBlockchainIconVisible: Boolean + get() = binding.ivBlockchain.isVisible + set(value) = binding.ivBlockchain::isVisible.set(value) + + private var isBadgeVisible: Boolean + get() = binding.badge.isVisible + set(value) = binding.badge::isVisible.set(value) + + @DrawableRes + private var blockchainIconRes: Int? = null + set(value) { + if (value != null && value != field && isBlockchainIconVisible) { + binding.ivBlockchain.setImageResource(value) + field = value + } + } init { - elevation = 0f - cardElevation = 0f - radius = dpToPx(6f) + minWidth = dpToPx(48f).roundToInt() + minHeight = dpToPx(48f).roundToInt() + } + + fun load( + currency: Currency, + derivationStyle: DerivationStyle?, + ) { + isBlockchainIconVisible = currency.isToken() + isBadgeVisible = currency.isCustomCurrency(derivationStyle) + blockchainIconRes = currency.blockchain.getRoundIconRes() + + CurrencyIconRequest( + currencyImageView = currencyImageView, + currencyTextView = currencyTextView, + token = (currency as? Currency.Token)?.token, + blockchain = currency.blockchain, + ).load() } } \ No newline at end of file diff --git a/app/src/main/res/layout/view_currency_icon.xml b/app/src/main/res/layout/view_currency_icon.xml index 6859d75600..801ac76c97 100644 --- a/app/src/main/res/layout/view_currency_icon.xml +++ b/app/src/main/res/layout/view_currency_icon.xml @@ -2,20 +2,65 @@ + android:layout_width="48dp" + android:layout_height="48dp" + tools:layout_gravity="center" + tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> - + + + + + + + + + + + From 9b7eecff02bf49cca1fe0bf39685a25657ceccb0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 3 Aug 2022 14:13:27 +0300 Subject: [PATCH 04/10] Updated on 2026-08-14 --- .../wallet/ui/WalletDetailsFragment.kt | 34 ++++++++++---- .../wallet/ui/adapters/WalletAdapter.kt | 27 ++++-------- .../main/res/layout/item_currency_wallet.xml | 44 +------------------ .../layout/layout_balance_wallet_details.xml | 18 +------- 4 files changed, 37 insertions(+), 86 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt index 73eb9ea393..0f54d5b13a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletDetailsFragment.kt @@ -1,7 +1,11 @@ package com.tangem.tap.features.wallet.ui import android.os.Bundle -import android.view.* +import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup import android.widget.TextView import androidx.activity.OnBackPressedCallback import androidx.annotation.ColorRes @@ -11,21 +15,32 @@ import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.transition.TransitionInflater import by.kirich1409.viewbindingdelegate.viewBinding +import com.tangem.domain.common.TapWorkarounds.derivationStyle import com.tangem.tangem_sdk_new.extensions.dpToPx import com.tangem.tap.common.SnackbarHandler import com.tangem.tap.common.TestActions -import com.tangem.tap.common.extensions.* +import com.tangem.tap.common.extensions.appendIfNotNull +import com.tangem.tap.common.extensions.beginDelayedTransition +import com.tangem.tap.common.extensions.fitChipsByGroupWidth +import com.tangem.tap.common.extensions.getColor +import com.tangem.tap.common.extensions.getString +import com.tangem.tap.common.extensions.hide +import com.tangem.tap.common.extensions.show +import com.tangem.tap.common.extensions.toQrCode import com.tangem.tap.common.recyclerView.SpaceItemDecoration import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.onboarding.getQRReceiveMessage import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.models.PendingTransaction -import com.tangem.tap.features.wallet.redux.* +import com.tangem.tap.features.wallet.redux.ErrorType +import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.WalletData +import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.WalletState.Companion.UNKNOWN_AMOUNT_SIGN import com.tangem.tap.features.wallet.ui.adapters.PendingTransactionsAdapter import com.tangem.tap.features.wallet.ui.adapters.WalletDetailWarningMessagesAdapter -import com.tangem.tap.features.wallet.ui.images.loadCurrencyIcon import com.tangem.tap.features.wallet.ui.test.TestWalletDetails import com.tangem.tap.store import com.tangem.wallet.R @@ -199,11 +214,12 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), } private fun handleCurrencyIcon(wallet: WalletData) = with(binding.lWalletDetails.lBalance) { - loadCurrencyIcon( - currencyImageView = ivCurrency, - currencyTextView = tvTokenLetter, - blockchain = wallet.currency.blockchain, - token = (wallet.currency as? Currency.Token)?.token + ivCurrency.load( + currency = wallet.currency, + derivationStyle = store.state.globalState + .scanResponse + ?.card + ?.derivationStyle, ) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt index 78bbb4c3ed..4be9104bb1 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/adapters/WalletAdapter.kt @@ -9,15 +9,12 @@ import androidx.recyclerview.widget.RecyclerView import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token import com.tangem.domain.common.TapWorkarounds.derivationStyle -import com.tangem.tap.common.extensions.getRoundIconRes import com.tangem.tap.common.extensions.getString import com.tangem.tap.common.extensions.hide import com.tangem.tap.common.extensions.show -import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletData import com.tangem.tap.features.wallet.ui.BalanceStatus -import com.tangem.tap.features.wallet.ui.images.loadCurrencyIcon import com.tangem.tap.store import com.tangem.wallet.R import com.tangem.wallet.databinding.ItemCurrencyWalletBinding @@ -67,12 +64,6 @@ class WalletAdapter // Skip changes when on refreshing status if (status == BalanceStatus.Refreshing) return@with - val isCustomCurrency = wallet.currency.isCustomCurrency( - derivationStyle = store.state.globalState - .scanResponse - ?.card - ?.derivationStyle - ) val statusMessage = when (status) { BalanceStatus.TransactionInProgress -> { root.getString(R.string.wallet_balance_tx_in_progress) @@ -87,7 +78,8 @@ class WalletAdapter BalanceStatus.UnknownBlockchain, BalanceStatus.Loading, BalanceStatus.Refreshing, - null -> null + null, + -> null } if (status == null || status == BalanceStatus.Loading) { @@ -98,11 +90,12 @@ class WalletAdapter lContent.root.show() } - loadCurrencyIcon( - currencyImageView = ivCurrency, - currencyTextView = tvTokenLetter, - token = (wallet.currency as? Currency.Token)?.token, - blockchain = wallet.currency.blockchain, + ivCurrency.load( + currency = wallet.currency, + derivationStyle = store.state.globalState + .scanResponse + ?.card + ?.derivationStyle, ) lContent.tvCurrency.text = wallet.currencyData.currency @@ -116,10 +109,6 @@ class WalletAdapter lContent.tvExchangeRate.text = wallet.fiatRateString ?: root.getString(id = R.string.token_item_no_rate) - badgeCustomBalance.isVisible = isCustomCurrency - ivBlockchain.isVisible = wallet.currency.isToken() - ivBlockchain.setImageResource(wallet.currency.blockchain.getRoundIconRes()) - cardWallet.setOnClickListener { store.dispatch(WalletAction.MultiWallet.SelectWallet(wallet)) } diff --git a/app/src/main/res/layout/item_currency_wallet.xml b/app/src/main/res/layout/item_currency_wallet.xml index 01860acfb1..0c6ef1fa3f 100644 --- a/app/src/main/res/layout/item_currency_wallet.xml +++ b/app/src/main/res/layout/item_currency_wallet.xml @@ -27,52 +27,12 @@ - - - - - - - - Date: Thu, 4 Aug 2022 20:23:49 +0300 Subject: [PATCH 05/10] Updated on 2026-08-14 --- .../tangem/tap/features/send/redux/reducers/FeeReducer.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt index edb435953f..fd653557c7 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/FeeReducer.kt @@ -106,8 +106,12 @@ class FeeReducer : SendInternalReducer { private fun getFeePrecision(sendState: SendState): FeePrecision { val blockchain = sendState.walletManager?.wallet?.blockchain - return if ((blockchain?.fullNameWithoutTestnet == Blockchain.Arbitrum.fullName || blockchain?.fullNameWithoutTestnet == Blockchain.Tron.fullName) && - sendState.amountState.typeOfAmount is AmountType.Token) { + return if ( + (blockchain?.fullNameWithoutTestnet == Blockchain.Arbitrum.fullName || + blockchain?.fullNameWithoutTestnet == Blockchain.Tron.fullName || + blockchain?.fullNameWithoutTestnet == Blockchain.Gnosis.fullName) && + sendState.amountState.typeOfAmount is AmountType.Token + ) { FeePrecision.CAN_BE_LOWER } else { FeePrecision.PRECISE From 3f2926b77eeeff36f4e5e168532747832ac16997 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sat, 6 Aug 2022 15:51:09 +0300 Subject: [PATCH 06/10] Updated on 2026-08-14 --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 44bf47e268..ab3dab0c54 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,8 +2,8 @@ ext.versions = [ kotlin : '1.6.10', build_gradle : '7.1.3', tangem_card_sdk : 'develop-159', - // tangem_blockchain_sdk: 'develop-99', - tangem_blockchain_sdk: '0.0.1', + tangem_blockchain_sdk: 'develop-100', + // tangem_blockchain_sdk: '0.0.1', ] ext.environmentConfig = [ From cb38a5783a6d62caaee3f8cb856e23457e77d7f8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 7 Aug 2022 21:35:34 +0400 Subject: [PATCH 07/10] Updated on 2026-08-14 --- .../features/details/redux/DetailsReducer.kt | 8 +- .../tap/features/wallet/ui/WalletFragment.kt | 29 +++-- .../wallet/ui/wallet/MultiWalletView.kt | 18 +-- .../wallet/ui/wallet/SaltPayBalanceWidget.kt | 51 ++++++++ .../ui/wallet/SaltPaySingleWalletView.kt | 51 ++++++++ .../wallet/ui/wallet/SingleWalletView.kt | 38 ++---- .../features/wallet/ui/wallet/WalletView.kt | 24 ++-- app/src/main/res/layout/fragment_wallet.xml | 10 ++ .../layout/layout_single_wallet_balance.xml | 116 ++++++++++++++++++ .../tangem/domain/common/TapWorkarounds.kt | 16 +-- 10 files changed, 280 insertions(+), 81 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SaltPayBalanceWidget.kt create mode 100644 app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/SaltPaySingleWalletView.kt create mode 100644 app/src/main/res/layout/layout_single_wallet_balance.xml diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index 99024b0c20..8db64e1cee 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.details.redux import com.tangem.common.card.Card +import com.tangem.domain.common.TapWorkarounds.isSaltPay import com.tangem.domain.common.TapWorkarounds.isStart2Coin import com.tangem.domain.common.TapWorkarounds.isTangemNote import com.tangem.domain.common.isTangemTwin @@ -19,7 +20,6 @@ class DetailsReducer { private fun internalReduce(action: Action, state: AppState): DetailsState { if (action !is DetailsAction) return state.detailsState - val detailsState = state.detailsState return when (action) { is DetailsAction.PrepareScreen -> { @@ -40,7 +40,6 @@ private fun internalReduce(action: Action, state: AppState): DetailsState { } is DetailsAction.ChangeAppCurrency -> detailsState.copy(appCurrency = action.fiatCurrency) - else -> detailsState } } @@ -48,7 +47,6 @@ private fun internalReduce(action: Action, state: AppState): DetailsState { private fun handlePrepareScreen( action: DetailsAction.PrepareScreen, ): DetailsState { - return DetailsState( scanResponse = action.scanResponse, wallets = action.wallets, @@ -99,7 +97,8 @@ private fun prepareSecurityOptions(card: Card): ManageSecurityState { private fun isResetToFactoryAllowedByCard(card: Card): Boolean { val notAllowedByAnyWallet = card.wallets.any { it.settings.isPermanent } val notAllowedByCard = notAllowedByAnyWallet || - (card.isWalletDataSupported && (!card.isTangemNote() && !card.settings.isBackupAllowed)) + (card.isWalletDataSupported && (!card.isTangemNote() && !card.settings.isBackupAllowed)) || + card.isSaltPay return !notAllowedByCard } @@ -140,7 +139,6 @@ private fun handleSecurityAction( ), ) } - else -> state } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index 73f315e29b..fe3c9131e4 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -14,6 +14,7 @@ import androidx.transition.TransitionInflater import by.kirich1409.viewbindingdelegate.viewBinding import coil.load import coil.size.Scale +import com.tangem.domain.common.TapWorkarounds.isSaltPay import com.tangem.tap.MainActivity import com.tangem.tap.common.extensions.show import com.tangem.tap.common.recyclerView.SpaceItemDecoration @@ -32,6 +33,7 @@ import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter import com.tangem.tap.features.wallet.ui.wallet.MultiWalletView +import com.tangem.tap.features.wallet.ui.wallet.SaltPaySingleWalletView import com.tangem.tap.features.wallet.ui.wallet.SingleWalletView import com.tangem.tap.features.wallet.ui.wallet.WalletView import com.tangem.tap.store @@ -112,17 +114,22 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber { + walletView = SaltPaySingleWalletView() + } + state.isMultiwalletAllowed && + state.primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard && + walletView is SingleWalletView -> { + walletView = MultiWalletView() + } + !state.isMultiwalletAllowed && walletView is MultiWalletView -> { + walletView = SingleWalletView() + } } + + walletView.changeWalletView(this, binding) walletView.onNewState(state) if (!state.shouldShowDetails) { @@ -134,7 +141,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber tvTwinCardNumber.show() @@ -113,11 +97,9 @@ class SingleWalletView : WalletView { } private fun setupButtons( - state: WalletData, isTwinsWallet: Boolean, binding: FragmentWalletBinding + state: WalletData, isTwinsWallet: Boolean, binding: FragmentWalletBinding, ) = with(binding) { - setupButtonsType(state, binding) - val tradeState = state.tradeCryptoState val btnConfirm = if (tradeState.isAvailableToSell() || tradeState.isAvailableToBuy()) { lButtonsShort.btnConfirm @@ -137,8 +119,8 @@ class SingleWalletView : WalletView { store.dispatch( WalletAction.DialogAction.QrCode( currency = state.currency, - selectedAddress = selectedAddress - ) + selectedAddress = selectedAddress, + ), ) } } @@ -207,7 +189,6 @@ class SingleWalletView : WalletView { } } - private fun setupAddressCard(state: WalletData, binding: FragmentWalletBinding) = with(binding.lAddress) { if (state.walletAddresses != null && state.currency is Currency.Blockchain) { binding.lAddress.root.show() @@ -215,7 +196,6 @@ class SingleWalletView : WalletView { (binding.lAddress.root as? ViewGroup)?.beginDelayedTransition() chipGroupAddressType.show() chipGroupAddressType.fitChipsByGroupWidth() - val checkedId = MultipleAddressUiHelper.typeToId(state.walletAddresses.selectedAddress.type) if (checkedId != View.NO_ID) chipGroupAddressType.check(checkedId) @@ -234,8 +214,8 @@ class SingleWalletView : WalletView { store.dispatch( WalletAction.ExploreAddress( state.walletAddresses.selectedAddress.exploreUrl, - fragment!!.requireContext() - ) + fragment!!.requireContext(), + ), ) } } else { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/WalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/WalletView.kt index 1d9ea0eac0..a3b09aab12 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/WalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/WalletView.kt @@ -4,16 +4,20 @@ import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.ui.WalletFragment import com.tangem.wallet.databinding.FragmentWalletBinding -interface WalletView { +abstract class WalletView { + protected var fragment: WalletFragment? = null + protected var binding: FragmentWalletBinding? = null + fun setFragment(fragment: WalletFragment, binding: FragmentWalletBinding) { + this.fragment = fragment + this.binding = binding + } - fun setFragment(fragment: WalletFragment, binding: FragmentWalletBinding) - - fun removeFragment() - - fun changeWalletView(fragment: WalletFragment, binding: FragmentWalletBinding) - - fun onViewCreated() - - fun onNewState(state: WalletState) + fun removeFragment() { + fragment = null + binding = null + } + abstract fun changeWalletView(fragment: WalletFragment, binding: FragmentWalletBinding) + abstract fun onViewCreated() + abstract fun onNewState(state: WalletState) } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_wallet.xml b/app/src/main/res/layout/fragment_wallet.xml index 102ae199f4..b2118902ec 100644 --- a/app/src/main/res/layout/fragment_wallet.xml +++ b/app/src/main/res/layout/fragment_wallet.xml @@ -148,6 +148,16 @@ android:visibility="gone" app:layout_constraintTop_toBottomOf="@id/rv_pending_transaction" /> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/domain/src/main/java/com/tangem/domain/common/TapWorkarounds.kt b/domain/src/main/java/com/tangem/domain/common/TapWorkarounds.kt index e273a4dae2..a11441c51c 100644 --- a/domain/src/main/java/com/tangem/domain/common/TapWorkarounds.kt +++ b/domain/src/main/java/com/tangem/domain/common/TapWorkarounds.kt @@ -9,20 +9,18 @@ import java.util.* [REDACTED_AUTHOR] */ object TapWorkarounds { - fun isStart2CoinIssuer(cardIssuer: String?): Boolean { return cardIssuer?.lowercase(Locale.US) == START_2_COIN_ISSUER } val Card.isStart2Coin: Boolean get() = isStart2CoinIssuer(issuer.name) - + val Card.isSaltPay: Boolean + get() = false //TODO fix when we know which cards are SaltPay cards val Card.isTestCard: Boolean get() = batchId == TEST_CARD_BATCH && cardId.startsWith(TEST_CARD_ID_STARTS_WITH) - val Card.useOldStyleDerivation: Boolean get() = batchId == "AC01" || batchId == "AC02" || batchId == "CB95" - val Card.derivationStyle: DerivationStyle? get() = if (!settings.isHDWalletAllowed) { null @@ -42,21 +40,19 @@ object TapWorkarounds { return false } - fun Card.isTangemNote(): Boolean = tangemNoteBatches.contains(batchId) - + fun Card.isTangemNote(): Boolean = tangemNoteBatches.contains(batchId) || isSaltPay fun isTangemWalletBatch(card: Card): Boolean = tangemWalletBatches.contains(card.batchId) - - fun Card.getTangemNoteBlockchain(): Blockchain? = tangemNoteBatches[batchId] + fun Card.getTangemNoteBlockchain(): Blockchain? = + tangemNoteBatches[batchId] ?: if (isSaltPay) Blockchain.Gnosis else null private const val START_2_COIN_ISSUER = "start2coin" private const val TEST_CARD_BATCH = "99FF" private const val TEST_CARD_ID_STARTS_WITH = "FF99" - private val excludedBatches = listOf( "0027", "0030", "0031", - "0035" + "0035", ) private val excludedIssuers = listOf( From 104e365934dbb0ea1d88dea24a84b6bee5b3ac89 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 8 Aug 2022 16:35:39 +0400 Subject: [PATCH 08/10] Updated on 2026-08-14 --- .../details/ui/appsettings/AppSettingsScreen.kt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt index 9b1dd4af03..34018707cf 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/appsettings/AppSettingsScreen.kt @@ -48,7 +48,7 @@ fun AppSettingsScreen( } @Composable -fun AppSettings( +private fun AppSettings( state: AppSettingsScreenState, modifier: Modifier = Modifier, ) { @@ -69,13 +69,15 @@ fun AppSettings( .fillMaxSize(), ) { AppSettingsElement( - state = state, setting = PrivacySetting.SaveWallets, + state = state, + setting = PrivacySetting.SaveWallets, onDialogStateChange = onDialogStateChange, modifier = modifier, ) Spacer(modifier = Modifier.size(32.dp)) AppSettingsElement( - state = state, setting = PrivacySetting.SaveAccessCode, + state = state, + setting = PrivacySetting.SaveAccessCode, onDialogStateChange = onDialogStateChange, modifier = modifier, ) @@ -83,7 +85,7 @@ fun AppSettings( } @Composable -fun AppSettingsElement( +private fun AppSettingsElement( state: AppSettingsScreenState, setting: PrivacySetting, onDialogStateChange: (PrivacySetting?) -> Unit, @@ -103,7 +105,6 @@ fun AppSettingsElement( modifier = modifier .fillMaxWidth() .padding(start = 20.dp), - // .clickable { state.onSettingToggled(element, !checked) }, verticalAlignment = Alignment.CenterVertically, ) { Column( @@ -140,7 +141,7 @@ fun AppSettingsElement( } } -fun onCheckedChange( +private fun onCheckedChange( element: PrivacySetting, enabled: Boolean, onSettingToggled: (PrivacySetting, Boolean) -> Unit, onDialogStateChange: (PrivacySetting?) -> Unit, @@ -154,7 +155,7 @@ fun onCheckedChange( } @Composable -fun SettingsAlertDialog( +private fun SettingsAlertDialog( element: PrivacySetting, onDialogStateChange: (PrivacySetting?) -> Unit, onSettingToggled: (PrivacySetting, Boolean) -> Unit, From 2a812a836ccd53eafea2d674242aa45a7c19c7d1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 8 Aug 2022 16:54:14 +0400 Subject: [PATCH 09/10] Updated on 2026-08-14 --- .../details/ui/common/TangemSwitch.kt | 50 ++++++------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/common/TangemSwitch.kt b/app/src/main/java/com/tangem/tap/features/details/ui/common/TangemSwitch.kt index 3132bb6fcc..9eda9be886 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/common/TangemSwitch.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/common/TangemSwitch.kt @@ -6,7 +6,6 @@ import androidx.compose.animation.core.LinearOutSlowInEasing import androidx.compose.animation.core.animateDp import androidx.compose.animation.core.tween import androidx.compose.animation.core.updateTransition -import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.indication @@ -19,7 +18,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Card import androidx.compose.material.ripple.rememberRipple import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -44,30 +42,22 @@ fun TangemSwitch( val transition = updateTransition(checked, label = "SwitchState") val color by transition.animateColor( transitionSpec = { - tween(200, easing = FastOutLinearInEasing) + tween(durationMillis = 200, easing = FastOutLinearInEasing) }, label = "", - ) { - when (it) { - true -> enabledColor - false -> disabledColor - } + ) { enabled -> + if (enabled) enabledColor else disabledColor } val interactionSource = remember { MutableInteractionSource() } - val clickable = Modifier.clickable( - interactionSource = interactionSource, - indication = null, - ) { - if (!checked) { - onCheckedChange(true) - } else { - onCheckedChange(false) - } - } Box( - modifier = Modifier - .then(clickable) + modifier = modifier + .clickable( + interactionSource = interactionSource, + indication = null, + ) { + onCheckedChange(!checked) + } .indication( interactionSource = MutableInteractionSource(), indication = rememberRipple( @@ -88,27 +78,19 @@ fun TangemSwitch( val roundCardSize = this.maxWidth / 2 val xOffset by transition.animateDp( transitionSpec = { - tween(150, easing = LinearOutSlowInEasing) + tween(durationMillis = 150, easing = LinearOutSlowInEasing) }, label = "xOffset", - ) { state -> - when (state) { - false -> 0.dp - true -> this.maxWidth - roundCardSize - } + ) { enabled -> + if (enabled) this.maxWidth - roundCardSize else 0.dp } - Card( + Box( modifier = Modifier .size(this.maxWidth / 2) .offset(x = xOffset, y = 0.dp) - .padding(3.dp), - shape = RoundedCornerShape(100), - backgroundColor = Color.White, - border = BorderStroke( - if (!checked) 0.5.dp else 0.dp, - color = Color.LightGray, - ), + .padding(3.dp) + .background(color = Color.White, shape = RoundedCornerShape(100)), ) { } } From d9e8be86c7b9ec442351a729390ae58edcf800bb Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 8 Aug 2022 17:05:47 +0400 Subject: [PATCH 10/10] Updated on 2026-08-14 --- .../tap/features/details/ui/common/TangemSwitch.kt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/common/TangemSwitch.kt b/app/src/main/java/com/tangem/tap/features/details/ui/common/TangemSwitch.kt index 9eda9be886..bf5268bf6f 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/common/TangemSwitch.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/common/TangemSwitch.kt @@ -59,10 +59,9 @@ fun TangemSwitch( onCheckedChange(!checked) } .indication( - interactionSource = MutableInteractionSource(), + interactionSource = interactionSource, indication = rememberRipple( - bounded = true, - radius = 100.dp, + bounded = false, color = Color.Transparent, ), ), @@ -71,7 +70,7 @@ fun TangemSwitch( modifier = modifier .width(size) .height(size / 2) - .indication(MutableInteractionSource(), null) + .indication(interactionSource, null) .background(color = color, shape = RoundedCornerShape(100)), contentAlignment = Alignment.CenterStart, ) { @@ -91,8 +90,7 @@ fun TangemSwitch( .offset(x = xOffset, y = 0.dp) .padding(3.dp) .background(color = Color.White, shape = RoundedCornerShape(100)), - ) { - } + ) } } } \ No newline at end of file