From cded6b8eb5153c2ee652860e62961584c974b5d4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 5 Sep 2023 12:18:56 +0300 Subject: [PATCH 01/10] Updated on 2026-08-14 --- app/src/main/res/layout/layout_onboarding_buttons_common.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/res/layout/layout_onboarding_buttons_common.xml b/app/src/main/res/layout/layout_onboarding_buttons_common.xml index 919923f821..1c756307dc 100644 --- a/app/src/main/res/layout/layout_onboarding_buttons_common.xml +++ b/app/src/main/res/layout/layout_onboarding_buttons_common.xml @@ -8,7 +8,6 @@ Date: Tue, 5 Sep 2023 18:06:04 +0300 Subject: [PATCH 02/10] Updated on 2026-08-14 --- app/src/main/res/drawable/splash_logo.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/res/drawable/splash_logo.xml b/app/src/main/res/drawable/splash_logo.xml index 29cb6365cf..ef37dfda51 100644 --- a/app/src/main/res/drawable/splash_logo.xml +++ b/app/src/main/res/drawable/splash_logo.xml @@ -1,15 +1,15 @@ + android:viewportWidth="450" + android:viewportHeight="450"> + android:fillColor="#ffffff" + android:pathData="M284.96,82H165.04C146.12,82 136.67,82 129.44,85.68C123.08,88.93 117.91,94.08 114.68,100.44C111,107.67 111,117.12 111,136.04V156.1H339V136.04C339,117.12 339,107.67 335.32,100.44C332.07,94.08 326.92,88.91 320.56,85.68C313.33,82 303.88,82 284.96,82Z" /> + android:fillColor="#ffffff" + android:pathData="M262.99,218.8H338.99V312.96C338.99,331.88 338.99,341.33 335.31,348.56C332.07,354.92 326.91,360.09 320.56,363.32C313.32,367 303.87,367 284.95,367H263.01L262.99,218.8Z" /> + android:fillColor="#ffffff" + android:pathData="M111,218.8H186.99V367H165.04C146.12,367 136.67,367 129.44,363.32C123.08,360.09 117.93,354.92 114.68,348.56C111,341.33 111,331.88 111,312.96V218.8Z" /> From f96ee9dbaf5894b306dc3aeaaa2d47678c4df6ba Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 5 Sep 2023 14:33:33 +0300 Subject: [PATCH 03/10] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/domain/TangemSdkManager.kt | 7 +++++-- .../tap/domain/tasks/product/ResetToFactorySettingsTask.kt | 4 +++- .../tangem/tap/features/details/redux/DetailsMiddleware.kt | 2 +- .../products/wallet/redux/OnboardingWalletMiddleware.kt | 2 +- .../src/main/java/com/tangem/domain/demo/DemoConfig.kt | 2 ++ 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt index 51e0adb686..6796da1e72 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -134,9 +134,12 @@ class TangemSdkManager(private val cardSdkConfigRepository: CardSdkConfigReposit return runTaskAsyncReturnOnMain(DeriveMultipleWalletPublicKeysTask(derivations), cardId) } - suspend fun resetToFactorySettings(cardId: String): CompletionResult { + suspend fun resetToFactorySettings( + cardId: String, + allowsRequestAccessCodeFromRepository: Boolean, + ): CompletionResult { return runTaskAsyncReturnOnMain( - runnable = ResetToFactorySettingsTask(), + runnable = ResetToFactorySettingsTask(allowsRequestAccessCodeFromRepository), cardId = cardId, initialMessage = Message(resources.getString(R.string.card_settings_reset_card_to_factory)), ) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt index a2622b218d..96b0593c4e 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ResetToFactorySettingsTask.kt @@ -8,7 +8,9 @@ import com.tangem.common.extensions.guard import com.tangem.operations.backup.ResetBackupCommand import com.tangem.operations.wallet.PurgeWalletCommand -class ResetToFactorySettingsTask : CardSessionRunnable { +class ResetToFactorySettingsTask( + override val allowsRequestAccessCodeFromRepository: Boolean, +) : CardSessionRunnable { override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { deleteWallets(session, callback) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index 5778b35562..88614a197f 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -123,7 +123,7 @@ class DetailsMiddleware { scope.launch { val userWalletId = UserWalletIdBuilder.card(card).build() - tangemSdkManager.resetToFactorySettings(card.cardId) + tangemSdkManager.resetToFactorySettings(card.cardId, true) .flatMap { userWalletsListManager.delete(listOfNotNull(userWalletId)) } .flatMap { tangemSdkManager.deleteSavedUserCodes(setOf(card.cardId)) } .doOnSuccess { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 2ec12176f7..7d3b5e7eb1 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -460,7 +460,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) } is BackupAction.ResetBackupCard -> { - scope.launch { tangemSdkManager.resetToFactorySettings(action.cardId) } + scope.launch { tangemSdkManager.resetToFactorySettings(action.cardId, false) } } else -> Unit diff --git a/domain/demo/src/main/java/com/tangem/domain/demo/DemoConfig.kt b/domain/demo/src/main/java/com/tangem/domain/demo/DemoConfig.kt index 864ed232f9..1ed5f92538 100644 --- a/domain/demo/src/main/java/com/tangem/domain/demo/DemoConfig.kt +++ b/domain/demo/src/main/java/com/tangem/domain/demo/DemoConfig.kt @@ -405,6 +405,8 @@ class DemoConfig { "AF04000000012014", "AF04000000012022", "AF04000000012030", + + // "AF02000000000003", ) @Suppress("ClassOrdering") From 665e6c66c4219042671893201df0a3604b067c64 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 5 Sep 2023 15:24:10 +0300 Subject: [PATCH 04/10] Updated on 2026-08-14 --- .../domain/tasks/product/ScanProductTask.kt | 5 ++- .../tap/domain/tokens/UserTokensRepository.kt | 44 +++++++++++-------- .../DefaultWalletStoresManager.kt | 4 +- .../tangem/tap/proxy/UserWalletManagerImpl.kt | 2 +- .../java/com/tangem/domain/demo/DemoConfig.kt | 2 - 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt index 2717354cc4..e17d4e2ebb 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt @@ -247,7 +247,10 @@ private class ScanWalletProcessor( derivationStyleProvider: DerivationStyleProvider, ): List { val userTokensRepository = userTokensRepository ?: return emptyList() - val blockchainsToDerive = userTokensRepository.loadBlockchainsToDerive(card) + val blockchainsToDerive = userTokensRepository.loadBlockchainsToDerive( + card, + derivationStyleProvider.getDerivationStyle(), + ) .toMutableList() .ifEmpty { mutableListOf( diff --git a/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt b/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt index 1304588781..7026203db3 100644 --- a/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt +++ b/app/src/main/java/com/tangem/tap/domain/tokens/UserTokensRepository.kt @@ -28,18 +28,23 @@ class UserTokensRepository( private val networkConnectionManager: NetworkConnectionManager, ) { - suspend fun getUserTokens(card: CardDTO): List = withContext(dispatchers.io) { - val userWalletId = getUserWalletId(card) ?: return@withContext emptyList() + suspend fun getUserTokens(card: CardDTO, derivationStyle: DerivationStyle?): List = + withContext(dispatchers.io) { + val userWalletId = getUserWalletId(card) ?: return@withContext emptyList() - if (DemoHelper.isDemoCardId(card.cardId)) { - return@withContext loadTokensOffline(userWalletId = userWalletId).ifEmpty(::loadDemoCurrencies) + if (DemoHelper.isDemoCardId(card.cardId)) { + return@withContext loadTokensOffline(userWalletId = userWalletId).ifEmpty { + loadDemoCurrencies( + derivationStyle, + ) + } + } + + if (!networkConnectionManager.isOnline) return@withContext loadTokensOffline(userWalletId = userWalletId) + + return@withContext remoteGetUserTokens(userWalletId = userWalletId) } - if (!networkConnectionManager.isOnline) return@withContext loadTokensOffline(userWalletId = userWalletId) - - return@withContext remoteGetUserTokens(userWalletId = userWalletId) - } - suspend fun saveUserTokens(card: CardDTO, tokens: List) = withContext(dispatchers.io) { val userWalletId = getUserWalletId(card) ?: return@withContext val userTokens = tokens.toUserTokensResponse() @@ -48,28 +53,29 @@ class UserTokensRepository( } // FIXME: Move to data layer - suspend fun loadBlockchainsToDerive(card: CardDTO): List = withContext(dispatchers.io) { - val userWalletId = getUserWalletId(card) ?: return@withContext emptyList() - val blockchainNetworks = loadTokensOffline(userWalletId = userWalletId).toBlockchainNetworks() + suspend fun loadBlockchainsToDerive(card: CardDTO, derivationStyle: DerivationStyle?): List = + withContext(dispatchers.io) { + val userWalletId = getUserWalletId(card) ?: return@withContext emptyList() + val blockchainNetworks = loadTokensOffline(userWalletId = userWalletId).toBlockchainNetworks() - if (DemoHelper.isDemoCardId(card.cardId)) { - return@withContext blockchainNetworks.ifEmpty(loadDemoCurrencies()::toBlockchainNetworks) + if (DemoHelper.isDemoCardId(card.cardId)) { + return@withContext blockchainNetworks.ifEmpty(loadDemoCurrencies(derivationStyle)::toBlockchainNetworks) + } + + return@withContext blockchainNetworks } - return@withContext blockchainNetworks - } - private fun loadTokensOffline(userWalletId: String): List { return storageService.getUserTokens(userWalletId = userWalletId) ?: emptyList() } // FIXME: Move to user wallet config - private fun loadDemoCurrencies(): List { + private fun loadDemoCurrencies(derivationStyle: DerivationStyle?): List { return DemoHelper.config.demoBlockchains .map { blockchain -> BlockchainNetwork( blockchain = blockchain, - derivationPath = blockchain.derivationPath(DerivationStyle.LEGACY)?.rawPath, + derivationPath = blockchain.derivationPath(derivationStyle)?.rawPath, tokens = emptyList(), ) } diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt index f2af46b082..4e60254106 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt @@ -3,6 +3,7 @@ package com.tangem.tap.domain.walletStores.implementation import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.address.AddressType import com.tangem.common.* +import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.wallets.legacy.WalletManagersRepository import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId @@ -126,8 +127,9 @@ internal class DefaultWalletStoresManager( private suspend fun fetchMultiWallets(userWallet: UserWallet): CompletionResult { val scanResponse = userWallet.scanResponse + val derivationStyle = scanResponse.derivationStyleProvider.getDerivationStyle() val userTokens = withContext(Dispatchers.IO) { - userTokensRepository.getUserTokens(scanResponse.card) + userTokensRepository.getUserTokens(scanResponse.card, derivationStyle) } val userWalletId = userWallet.walletId diff --git a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt index 432dc559a1..0403ad4383 100644 --- a/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt +++ b/app/src/main/java/com/tangem/tap/proxy/UserWalletManagerImpl.kt @@ -40,7 +40,7 @@ class UserWalletManagerImpl( val userTokensRepository = requireNotNull(appStateHolder.userTokensRepository) { "userTokensRepository is null" } return if (card != null) { - userTokensRepository.getUserTokens(card) + userTokensRepository.getUserTokens(card, null) // refactor in [REDACTED_JIRA] .filter { val checkCustom = if (isExcludeCustom) { !it.isCustomCurrency(null) diff --git a/domain/demo/src/main/java/com/tangem/domain/demo/DemoConfig.kt b/domain/demo/src/main/java/com/tangem/domain/demo/DemoConfig.kt index 1ed5f92538..864ed232f9 100644 --- a/domain/demo/src/main/java/com/tangem/domain/demo/DemoConfig.kt +++ b/domain/demo/src/main/java/com/tangem/domain/demo/DemoConfig.kt @@ -405,8 +405,6 @@ class DemoConfig { "AF04000000012014", "AF04000000012022", "AF04000000012030", - - // "AF02000000000003", ) @Suppress("ClassOrdering") From da21d46af1cc27680058c87b272f1e61a66fe3b0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 6 Sep 2023 13:38:46 +0500 Subject: [PATCH 05/10] Updated on 2026-08-14 --- .../features/send/redux/SendScreenAction.kt | 7 ++++ .../send/redux/middlewares/SendMiddleware.kt | 13 ++++++++ .../send/redux/reducers/SendScreenReducer.kt | 1 + .../send/ui/dialogs/ChiaWarningDialog.kt | 32 +++++++++++++++++++ .../stateSubscribers/SendStateSubscriber.kt | 12 ++++--- .../main/res/values-ru/strings-blockchain.xml | 3 ++ .../main/res/values/strings-blockchain.xml | 3 ++ gradle/dependencies.toml | 2 +- 8 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/features/send/ui/dialogs/ChiaWarningDialog.kt 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 cd9ad2160d..4c9eaf36a5 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 @@ -155,6 +155,13 @@ sealed class SendAction : SendScreenAction { val onOk: () -> Unit, ) : Dialog() + data class ChiaWarningDialog( + val blockchainName: String, + val maxOutputs: Int, + val maxAmount: BigDecimal, + val onOk: () -> Unit, + ) : Dialog() + sealed class SendTransactionFails : Dialog() { data class CardSdkError(val error: TangemSdkError) : Dialog() data class BlockchainSdkError(val error: com.tangem.blockchain.common.BlockchainSdkError) : 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 628e934435..4e4d53efc4 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 @@ -307,6 +307,19 @@ private fun sendTransaction( ), ) } + is BlockchainSdkError.Chia.UtxoAmountError -> { + dispatch( + SendAction.Dialog.ChiaWarningDialog( + blockchainName = Blockchain.Chia.fullName, + maxOutputs = error.maxOutputs, + maxAmount = error.maxAmount, + onOk = { + dispatch(AmountAction.SetAmount(error.maxAmount, isUserInput = false)) + dispatch(AmountActionUi.CheckAmountToSend) + }, + ), + ) + } else -> { when { error.customMessage.contains(DemoTransactionSender.ID) -> { diff --git a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt index 463b0dcaea..8a9cab2329 100644 --- a/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/send/redux/reducers/SendScreenReducer.kt @@ -46,6 +46,7 @@ private class SendReducer : SendInternalReducer { } is SendAction.Dialog.TezosWarningDialog -> sendState.copy(dialog = action) is SendAction.Dialog.KaspaWarningDialog -> sendState.copy(dialog = action) + is SendAction.Dialog.ChiaWarningDialog -> sendState.copy(dialog = action) is SendAction.Dialog.SendTransactionFails.CardSdkError -> sendState.copy(dialog = action) is SendAction.Dialog.SendTransactionFails.BlockchainSdkError -> sendState.copy(dialog = action) is SendAction.Dialog.RequestFeeError -> sendState.copy(dialog = action) diff --git a/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/ChiaWarningDialog.kt b/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/ChiaWarningDialog.kt new file mode 100644 index 0000000000..b4ba056146 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/send/ui/dialogs/ChiaWarningDialog.kt @@ -0,0 +1,32 @@ +package com.tangem.tap.features.send.ui.dialogs + +import android.content.Context +import androidx.appcompat.app.AlertDialog +import com.tangem.tap.features.send.redux.SendAction +import com.tangem.tap.store +import com.tangem.wallet.R + +// TODO: [REDACTED_JIRA] +object ChiaWarningDialog { + + fun create(context: Context, dialog: SendAction.Dialog.ChiaWarningDialog): AlertDialog { + return AlertDialog.Builder(context).apply { + setTitle(R.string.common_warning) + setMessage( + context.getString( + R.string.common_utxo_validate_withdrawal_message_warning, + dialog.blockchainName, + dialog.maxOutputs, + dialog.maxAmount.toPlainString(), + ), + ) + setPositiveButton(R.string.common_ok) { _, _ -> + dialog.onOk() + } + setOnDismissListener { + store.dispatch(SendAction.Dialog.Hide) + } + } + .create() + } +} \ No newline at end of file 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 6de86eba68..e05278fceb 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 @@ -18,10 +18,7 @@ import com.tangem.tap.features.send.redux.SendAction import com.tangem.tap.features.send.redux.states.* import com.tangem.tap.features.send.ui.FeeUiHelper import com.tangem.tap.features.send.ui.SendFragment -import com.tangem.tap.features.send.ui.dialogs.KaspaWarningDialog -import com.tangem.tap.features.send.ui.dialogs.RequestFeeErrorDialog -import com.tangem.tap.features.send.ui.dialogs.SendTransactionFailsDialog -import com.tangem.tap.features.send.ui.dialogs.TezosWarningDialog +import com.tangem.tap.features.send.ui.dialogs.* import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.utils.ROUGH_SIGN import com.tangem.tap.features.wallet.redux.utils.UNKNOWN_AMOUNT_SIGN @@ -124,6 +121,7 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber } } + @Suppress("ComplexMethod") private fun handleSendScreen(fg: SendFragment, state: SendState) = with(fg.binding) { when (state.dialog) { is SendAction.Dialog.TezosWarningDialog -> { @@ -138,6 +136,12 @@ class SendStateSubscriber(fragment: BaseStoreFragment) : FragmentStateSubscriber dialog?.show() } } + is SendAction.Dialog.ChiaWarningDialog -> { + if (dialog == null) { + dialog = ChiaWarningDialog.create(fg.requireContext(), state.dialog) + dialog?.show() + } + } is SendAction.Dialog.SendTransactionFails.CardSdkError -> { if (dialog == null) { dialog = SendTransactionFailsDialog.create(fg.requireContext(), state.dialog) diff --git a/core/res/src/main/res/values-ru/strings-blockchain.xml b/core/res/src/main/res/values-ru/strings-blockchain.xml index 0e716ae5d1..fcec1f9e0c 100644 --- a/core/res/src/main/res/values-ru/strings-blockchain.xml +++ b/core/res/src/main/res/values-ru/strings-blockchain.xml @@ -3,6 +3,9 @@ По умолчанию Устаревший Не удалось получить комиссию + Из-за ограничений %1$s в одну транзакцию может поместиться только %2$d UTXO. Это означает, что вы можете отправить только %3$s или меньше. Вам нужно уменьшить сумму. + Недостаточно средств для совершения транзакции. Пожалуйста, пополните свой аккаунт. + Произошла ошибка. Код: %s. Из-за ограничений Kaspa в одну транзакцию может поместиться только %1$d UTXO. Это означает, что вы можете отправить только %2$s или меньше. Вам нужно уменьшить сумму. Пополните счет на %1$s+ %2$s, чтобы создать аккаунт Аккаунт получателя не активирован. Отправьте %s или более для активации аккаунта. diff --git a/core/res/src/main/res/values/strings-blockchain.xml b/core/res/src/main/res/values/strings-blockchain.xml index 41209dd8f9..7e938d5420 100644 --- a/core/res/src/main/res/values/strings-blockchain.xml +++ b/core/res/src/main/res/values/strings-blockchain.xml @@ -3,6 +3,9 @@ Default Legacy Failed to get fee + Due to %1$s limitations only %2$d UTXOs can fit in a single transaction. This means you can only send %3$s or less. You need to reduce the amount. + Not enough funds for the transaction. Please top up your account. + An error occurred. Code: %s. Due to Kaspa limitations only %1$d UTXOs can fit in a single transaction. This means you can only send %2$s or less. You need to reduce the amount. Load %1$s+ %2$s to create account Destination account is not active. Send %s or more to activate the account. diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index b8af65e72b..f9144bb4cf 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -80,7 +80,7 @@ okHttp-prettyLogging = "3.1.0" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_4.10-336" +tangemBlockchainSdk = "release-app_4.10-341" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_4.10-292" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds From fcb6110d56d8ca0806394355d17eb6e340c4e56b Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 6 Sep 2023 10:19:21 +0300 Subject: [PATCH 06/10] Updated on 2026-08-14 --- .../res/drawable/ic_launcher_foreground.xml | 29 +++++++------- app/src/main/res/drawable/ic_tangem_logo.xml | 39 ++++--------------- .../main/res/drawable/img_tangem_logo_96.xml | 10 ++--- core/res/src/main/res/values-ru/strings.xml | 2 +- 4 files changed, 29 insertions(+), 51 deletions(-) diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index 2b59c5b299..3b1aea3367 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -3,18 +3,19 @@ android:height="108dp" android:viewportWidth="146" android:viewportHeight="146"> - - - - - + + + + + diff --git a/app/src/main/res/drawable/ic_tangem_logo.xml b/app/src/main/res/drawable/ic_tangem_logo.xml index 08d67c8cf7..8cd0cc5ff8 100644 --- a/app/src/main/res/drawable/ic_tangem_logo.xml +++ b/app/src/main/res/drawable/ic_tangem_logo.xml @@ -1,33 +1,10 @@ - - - - - - - - - + android:width="51dp" + android:height="11dp" + android:viewportWidth="74" + android:viewportHeight="16"> + diff --git a/app/src/main/res/drawable/img_tangem_logo_96.xml b/app/src/main/res/drawable/img_tangem_logo_96.xml index 93fe8d9c0f..f12f6ccf0b 100644 --- a/app/src/main/res/drawable/img_tangem_logo_96.xml +++ b/app/src/main/res/drawable/img_tangem_logo_96.xml @@ -1,15 +1,15 @@ + android:viewportWidth="98" + android:viewportHeight="98"> + android:pathData="M59.285,24.464H38.715C35.469,24.464 33.848,24.464 32.607,25.095C31.517,25.652 30.629,26.536 30.076,27.626C29.444,28.867 29.444,30.488 29.444,33.734V37.175H68.555V33.734C68.555,30.488 68.555,28.867 67.924,27.626C67.367,26.536 66.483,25.648 65.393,25.095C64.152,24.464 62.531,24.464 59.285,24.464Z" /> + android:pathData="M55.516,47.93H68.554V64.082C68.554,67.328 68.554,68.949 67.923,70.19C67.366,71.28 66.482,72.168 65.392,72.721C64.151,73.353 62.53,73.353 59.284,73.353H55.52L55.516,47.93Z" /> + android:pathData="M29.444,47.93H42.479V73.353H38.715C35.469,73.353 33.848,73.353 32.607,72.721C31.517,72.168 30.633,71.28 30.076,70.19C29.444,68.949 29.444,67.328 29.444,64.082V47.93Z" /> diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 91773de93c..2831c8d27d 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -568,5 +568,5 @@ Войти с %s Сканировать карту Используйте %s или отсканируйте карту для входа в приложение - C возвращением! + С возвращением! From e430798dc97864e624c0e14ae4f7d6a8b1fa4699 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 6 Sep 2023 11:08:46 +0300 Subject: [PATCH 07/10] Updated on 2026-08-14 --- .../com/tangem/tap/features/home/compose/StoriesScreen.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt b/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt index d29b602c5d..01d6c35c2d 100644 --- a/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt @@ -23,6 +23,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider import androidx.compose.ui.unit.dp import com.google.accompanist.systemuicontroller.rememberSystemUiController +import com.tangem.core.ui.res.TangemColorPalette import com.tangem.core.ui.res.TangemTheme import com.tangem.feature.learn2earn.presentation.ui.Learn2earnStoriesScreen import com.tangem.tap.features.home.compose.content.* @@ -169,7 +170,11 @@ private fun StoriesScreenContent(config: StoriesScreenContentConfig, modifier: M .height(17.dp) .alpha(if (hideContent) 0f else 1f) .align(Alignment.Start), - colorFilter = if (config.currentStory.isDarkBackground) null else ColorFilter.tint(Color.Black), + colorFilter = if (config.currentStory.isDarkBackground) { + null + } else { + ColorFilter.tint(TangemColorPalette.Dark6) + } ) when (config.currentStory) { Stories.OneInchPromo -> Learn2earnStoriesScreen(config.onLearn2earnClick) From 903dd160b1c38d52c3bf7b7a31db78c0ebb58f81 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 6 Sep 2023 17:29:41 +0800 Subject: [PATCH 08/10] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/MainActivity.kt | 19 +++++-- .../tangem/tap/features/home/HomeFragment.kt | 8 ++- .../tap/features/home/redux/HomeAction.kt | 9 ++++ .../tap/features/home/redux/HomeMiddleware.kt | 53 ++++++++++--------- .../handlers/BackgroundScanIntentHandler.kt | 9 ++-- .../wallet/redux/OnboardingWalletAction.kt | 3 +- .../redux/OnboardingWalletMiddleware.kt | 4 +- .../wallet/ui/OnboardingWalletFragment.kt | 5 +- .../tap/features/wallet/redux/WalletAction.kt | 8 ++- .../redux/middlewares/WalletMiddleware.kt | 16 ++++-- .../tap/features/wallet/ui/WalletFragment.kt | 6 ++- .../features/welcome/redux/WelcomeAction.kt | 3 +- .../welcome/redux/WelcomeMiddleware.kt | 39 +++++++------- .../features/welcome/ui/WelcomeFragment.kt | 11 ++-- .../features/welcome/ui/WelcomeViewModel.kt | 5 +- 15 files changed, 122 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/MainActivity.kt b/app/src/main/java/com/tangem/tap/MainActivity.kt index 429cbe3e57..17b20dbe41 100644 --- a/app/src/main/java/com/tangem/tap/MainActivity.kt +++ b/app/src/main/java/com/tangem/tap/MainActivity.kt @@ -8,6 +8,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsControllerCompat +import androidx.lifecycle.lifecycleScope import by.kirich1409.viewbindingdelegate.viewBinding import com.google.android.material.snackbar.Snackbar import com.tangem.core.navigation.AppScreen @@ -180,7 +181,12 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac private fun initIntentHandlers() { val hasSavedWalletsProvider = { store.state.globalState.userWalletsListManager?.hasUserWallets == true } - intentProcessor.addHandler(BackgroundScanIntentHandler(hasSavedWalletsProvider)) + intentProcessor.addHandler( + BackgroundScanIntentHandler( + hasSavedWalletsProvider, + lifecycleScope, + ), + ) intentProcessor.addHandler(WalletConnectLinkIntentHandler()) intentProcessor.addHandler(BuyCurrencyIntentHandler()) intentProcessor.addHandler(SellCurrencyIntentHandler()) @@ -222,7 +228,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac */ cardSdkLifecycleObserver.onCreate(context = this) - scope.launch { + lifecycleScope.launch { intentProcessor.handleIntent(intent) } } @@ -294,8 +300,11 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac if (store.state.globalState.userWalletsListManager?.hasUserWallets == true) { store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Welcome)) store.dispatchOnMain(WelcomeAction.SetInitialIntent(intentWhichStartedActivity)) - scope.launch { - val handler = BackgroundScanIntentHandler(hasSavedUserWalletsProvider = { true }) + lifecycleScope.launch { + val handler = BackgroundScanIntentHandler( + hasSavedUserWalletsProvider = { true }, + lifecycleCoroutineScope = lifecycleScope, + ) val isBackgroundScanHandled = handler.handleIntent(intentWhichStartedActivity) val hasNotIncompletedBackup = !backupService.hasIncompletedBackup if (!isBackgroundScanHandled && hasNotIncompletedBackup) { @@ -304,7 +313,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac } } else { store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Home)) - scope.launch { + lifecycleScope.launch { intentProcessor.handleIntent(intentWhichStartedActivity) } } diff --git a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt index 95b558c438..1f6f2abc69 100644 --- a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt @@ -13,6 +13,7 @@ import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsControllerCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels +import androidx.lifecycle.lifecycleScope import com.tangem.core.analytics.Analytics import com.tangem.core.navigation.AppScreen import com.tangem.core.navigation.NavigationAction @@ -26,6 +27,7 @@ import com.tangem.tap.features.home.redux.Stories import com.tangem.tap.features.tokens.legacy.redux.TokensAction import com.tangem.tap.store import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch import org.rekotlin.StoreSubscriber @AndroidEntryPoint @@ -94,7 +96,11 @@ class HomeFragment : Fragment(), StoreSubscriber { onLearn2earnClick = learn2earnViewModel.uiState.storyScreenState.onClick, onScanButtonClick = { Analytics.send(IntroductionProcess.ButtonScanCard()) - store.dispatch(HomeAction.ReadCard()) + lifecycleScope.launch { + store.dispatch( + HomeAction.ReadCard(lifecycleCoroutineScope = lifecycleScope), + ) + } }, onShopButtonClick = { Analytics.send(IntroductionProcess.ButtonBuyCards()) diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt index 93479d1767..18fbd8f4fb 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.home.redux +import androidx.lifecycle.LifecycleCoroutineScope import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Basic @@ -13,8 +14,16 @@ sealed class HomeAction : Action { data class InsertStory(val position: Int, val story: Stories) : HomeAction() + /** + * Action for scanning card + * + * @property analyticsEvent analytics event + * @property lifecycleCoroutineScope lifecycle scope. It will be canceled when lifecycle-aware component is + * destroyed. + */ data class ReadCard( val analyticsEvent: AnalyticsEvent? = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.Introduction), + val lifecycleCoroutineScope: LifecycleCoroutineScope, ) : HomeAction() data class ScanInProgress(val scanInProgress: Boolean) : HomeAction() diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index 162d99281a..48f2f37be5 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.home.redux +import androidx.lifecycle.LifecycleCoroutineScope import com.tangem.common.doOnFailure import com.tangem.common.doOnResult import com.tangem.common.doOnSuccess @@ -62,7 +63,7 @@ private fun handleHomeAction(action: Action) { store.dispatch(GlobalAction.FetchUserCountry) } is HomeAction.ReadCard -> { - readCard(action.analyticsEvent) + readCard(action.analyticsEvent, action.lifecycleCoroutineScope) } is HomeAction.GoToShop -> { Analytics.send(Shop.ScreenOpened()) @@ -77,32 +78,34 @@ private fun handleHomeAction(action: Action) { } } -private fun readCard(analyticsEvent: AnalyticsEvent?) = scope.launch { - delay(timeMillis = 200) - store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy( - isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes, - ) +private fun readCard(analyticsEvent: AnalyticsEvent?, lifecycleCoroutineScope: LifecycleCoroutineScope) { + lifecycleCoroutineScope.launch { + delay(timeMillis = 200) + store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy( + isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes, + ) - store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan( - analyticsEvent = analyticsEvent, - onProgressStateChange = { showProgress -> - if (showProgress) { - changeButtonState(ButtonState.PROGRESS) - } else { + store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan( + analyticsEvent = analyticsEvent, + onProgressStateChange = { showProgress -> + if (showProgress) { + changeButtonState(ButtonState.PROGRESS) + } else { + changeButtonState(ButtonState.ENABLED) + } + }, + onScanStateChange = { scanInProgress -> + store.dispatch(HomeAction.ScanInProgress(scanInProgress)) + }, + onFailure = { + Timber.e(it, "Unable to scan card") changeButtonState(ButtonState.ENABLED) - } - }, - onScanStateChange = { scanInProgress -> - store.dispatch(HomeAction.ScanInProgress(scanInProgress)) - }, - onFailure = { - Timber.e(it, "Unable to scan card") - changeButtonState(ButtonState.ENABLED) - }, - onSuccess = { scanResponse -> - proceedWithScanResponse(scanResponse) - }, - ) + }, + onSuccess = { scanResponse -> + proceedWithScanResponse(scanResponse) + }, + ) + } } private fun proceedWithScanResponse(scanResponse: ScanResponse) = scope.launch { diff --git a/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BackgroundScanIntentHandler.kt b/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BackgroundScanIntentHandler.kt index df5b3759d8..09a682cdb5 100644 --- a/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BackgroundScanIntentHandler.kt +++ b/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/BackgroundScanIntentHandler.kt @@ -4,11 +4,11 @@ import android.content.Intent import android.nfc.NfcAdapter import android.nfc.Tag import android.os.Build +import androidx.lifecycle.LifecycleCoroutineScope import com.tangem.tap.common.extensions.dispatchWithMain import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.intentHandler.IntentHandler import com.tangem.tap.features.welcome.redux.WelcomeAction -import com.tangem.tap.scope import com.tangem.tap.store import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -18,6 +18,7 @@ import kotlinx.coroutines.launch */ class BackgroundScanIntentHandler( private val hasSavedUserWalletsProvider: () -> Boolean, + private val lifecycleCoroutineScope: LifecycleCoroutineScope, ) : IntentHandler { private val nfcActions = arrayOf( @@ -40,12 +41,12 @@ class BackgroundScanIntentHandler( intent.action = null if (hasSavedUserWalletsProvider.invoke()) { // TODO: Remove delay after [REDACTED_JIRA] - scope.launch { + lifecycleCoroutineScope.launch { delay(timeMillis = 200) - store.dispatchWithMain(WelcomeAction.ProceedWithCard) + store.dispatchWithMain(WelcomeAction.ProceedWithCard(lifecycleCoroutineScope)) } } else { - store.dispatchWithMain(HomeAction.ReadCard()) + store.dispatchWithMain(HomeAction.ReadCard(lifecycleCoroutineScope = lifecycleCoroutineScope)) } return true diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt index b1f339be2a..9446f718c1 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.onboarding.products.wallet.redux import android.net.Uri +import androidx.lifecycle.LifecycleCoroutineScope import com.tangem.common.CompletionResult import com.tangem.feature.onboarding.data.model.CreateWalletResponse import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource @@ -17,7 +18,7 @@ sealed class OnboardingWalletAction : Action { ) : OnboardingWalletAction() object Done : OnboardingWalletAction() - object FinishOnboarding : OnboardingWalletAction() + data class FinishOnboarding(val lifecycleCoroutineScope: LifecycleCoroutineScope) : OnboardingWalletAction() object ResumeBackup : OnboardingWalletAction() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 7d3b5e7eb1..b255ab3536 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -146,12 +146,12 @@ private fun handleWalletAction(action: Action) { is CompletionResult.Failure -> Unit } } - OnboardingWalletAction.FinishOnboarding -> { + is OnboardingWalletAction.FinishOnboarding -> { store.dispatch(GlobalAction.Onboarding.Stop) if (scanResponse == null) { store.dispatch(NavigationAction.PopBackTo()) - store.dispatch(HomeAction.ReadCard()) + store.dispatch(HomeAction.ReadCard(lifecycleCoroutineScope = action.lifecycleCoroutineScope)) } else { val backupState = store.state.onboardingWalletState.backupState val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index b1021876bc..ff40ab5ad6 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -11,6 +11,7 @@ import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity import androidx.core.view.MenuProvider import androidx.fragment.app.viewModels +import androidx.lifecycle.lifecycleScope import androidx.transition.TransitionInflater import androidx.transition.TransitionManager import by.kirich1409.viewbindingdelegate.viewBinding @@ -428,7 +429,9 @@ class OnboardingWalletFragment : layoutButtonsCommon.btnWalletAlternativeAction.hide() layoutButtonsCommon.btnWalletMainAction.setOnClickListener { showConfetti(false) - store.dispatch(OnboardingWalletAction.FinishOnboarding) + lifecycleScope.launch { + store.dispatch(OnboardingWalletAction.FinishOnboarding(lifecycleCoroutineScope = lifecycleScope)) + } } animator.showSuccess { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index 10803cf57f..adca4f96f4 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.wallet.redux import android.content.Context +import androidx.lifecycle.LifecycleCoroutineScope import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.address.AddressType import com.tangem.core.analytics.models.AnalyticsEvent @@ -73,7 +74,10 @@ sealed class WalletAction : Action { class CheckRemainingSignatures(val remainingSignatures: Int?) : Warnings() } - data class Scan(val onScanSuccessEvent: AnalyticsEvent?) : WalletAction() + data class Scan( + val onScanSuccessEvent: AnalyticsEvent?, + val lifecycleScope: LifecycleCoroutineScope, + ) : WalletAction() data class Send(val amount: Amount? = null) : WalletAction() @@ -109,7 +113,7 @@ sealed class WalletAction : Action { data class ExploreAddress(val exploreUrl: String, val context: Context) : WalletAction() object CreateWallet : WalletAction() - object ChangeWallet : WalletAction() + data class ChangeWallet(val lifecycleScope: LifecycleCoroutineScope) : WalletAction() object ShowSaveWalletIfNeeded : WalletAction() sealed class TradeCryptoAction : WalletAction() { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index c84ac7fa2d..2072690c1c 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.wallet.redux.middlewares +import androidx.lifecycle.LifecycleCoroutineScope import com.google.firebase.crashlytics.FirebaseCrashlytics import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.AmountType @@ -114,9 +115,9 @@ class WalletMiddleware { } is WalletAction.Scan -> { store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) - scope.launch { + action.lifecycleScope.launch { delay(timeMillis = 700) - store.dispatchOnMain(HomeAction.ReadCard(action.onScanSuccessEvent)) + store.dispatchOnMain(HomeAction.ReadCard(action.onScanSuccessEvent, action.lifecycleScope)) } } is WalletAction.LoadData, @@ -225,7 +226,7 @@ class WalletMiddleware { showSaveWalletIfNeeded() } is WalletAction.ChangeWallet -> { - changeWallet(walletState) + changeWallet(walletState, action.lifecycleScope) } is WalletAction.UserWalletChanged -> Unit is WalletAction.WalletStoresChanged -> { @@ -378,7 +379,7 @@ class WalletMiddleware { } } - private fun changeWallet(state: WalletState) { + private fun changeWallet(state: WalletState, lifecycleScope: LifecycleCoroutineScope) { when { state.canSaveUserWallets -> { Analytics.send(MainScreen.ButtonMyWallets()) @@ -386,7 +387,12 @@ class WalletMiddleware { } else -> { Analytics.send(MainScreen.ButtonScanCard()) - store.dispatch(WalletAction.Scan(Basic.CardWasScanned(AnalyticsParam.ScannedFrom.Main))) + store.dispatch( + WalletAction.Scan( + onScanSuccessEvent = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.Main), + lifecycleScope = lifecycleScope, + ), + ) } } } 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 af1d2100aa..bcbad9fc7a 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 @@ -141,7 +141,11 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber proceedWithBiometrics(state) - is WelcomeAction.ProceedWithCard -> proceedWithCard(state) + is WelcomeAction.ProceedWithCard -> proceedWithCard(state, action.lifecycleCoroutineScope) is WelcomeAction.ClearUserWallets -> disableUserWalletsSaving() else -> Unit } @@ -77,25 +78,27 @@ internal class WelcomeMiddleware { } } - private fun proceedWithCard(state: WelcomeState) = scope.launch { - scanCardInternal { scanResponse -> - val userWallet = UserWalletBuilder(scanResponse).build() ?: return@scanCardInternal + private fun proceedWithCard(state: WelcomeState, lifecycleCoroutineScope: LifecycleCoroutineScope) { + lifecycleCoroutineScope.launch { + scanCardInternal { scanResponse -> + val userWallet = UserWalletBuilder(scanResponse).build() ?: return@scanCardInternal - userWalletsListManager.save(userWallet, canOverride = true) - .doOnFailure { error -> - Timber.e(error, "Unable to save user wallet") - store.dispatchOnMain(WelcomeAction.ProceedWithCard.Error(error)) - } - .doOnSuccess { - store.dispatchOnMain(SignInAction.SetSignInType(Basic.SignedIn.SignInType.Card)) - store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet)) - store.dispatchOnMain(WelcomeAction.ProceedWithCard.Success) - store.onUserWalletSelected(userWallet = userWallet) - - state.intent?.let { - WalletConnectLinkIntentHandler().handleIntent(it) + userWalletsListManager.save(userWallet, canOverride = true) + .doOnFailure { error -> + Timber.e(error, "Unable to save user wallet") + store.dispatchOnMain(WelcomeAction.ProceedWithCard.Error(error)) } - } + .doOnSuccess { + store.dispatchOnMain(SignInAction.SetSignInType(Basic.SignedIn.SignInType.Card)) + store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet)) + store.dispatchOnMain(WelcomeAction.ProceedWithCard.Success) + store.onUserWalletSelected(userWallet = userWallet) + + state.intent?.let { + WalletConnectLinkIntentHandler().handleIntent(it) + } + } + } } } diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt index 0554bdf27c..0713e33482 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt @@ -7,17 +7,12 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.material.SnackbarHost import androidx.compose.material.SnackbarHostState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.fragment.app.viewModels +import androidx.lifecycle.lifecycleScope import com.tangem.core.analytics.Analytics import com.tangem.core.ui.components.SystemBarsEffect import com.tangem.core.ui.fragments.ComposeFragment @@ -67,7 +62,7 @@ internal class WelcomeFragment : ComposeFragment() { showUnlockProgress = state.showUnlockWithBiometricsProgress, showScanCardProgress = state.showUnlockWithCardProgress, onUnlockClick = viewModel::unlockWallets, - onScanCardClick = viewModel::scanCard, + onScanCardClick = { viewModel.scanCard(lifecycleCoroutineScope = lifecycleScope) }, ) SnackbarHost( diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt index 3731da6378..4f7587289d 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.welcome.ui +import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.ViewModel import com.tangem.common.core.TangemError import com.tangem.core.analytics.Analytics @@ -30,9 +31,9 @@ internal class WelcomeViewModel : ViewModel(), StoreSubscriber { store.dispatch(WelcomeAction.ProceedWithBiometrics) } - fun scanCard() { + fun scanCard(lifecycleCoroutineScope: LifecycleCoroutineScope) { Analytics.send(SignIn.ButtonCardSignIn()) - store.dispatch(WelcomeAction.ProceedWithCard) + store.dispatch(WelcomeAction.ProceedWithCard(lifecycleCoroutineScope)) } fun closeError() { From 1e8bed20a4305c9c047c31a3f5494afaae94f8fc Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 6 Sep 2023 13:14:49 +0300 Subject: [PATCH 09/10] Updated on 2026-08-14 --- .../components/buttons/common/TangemButton.kt | 120 ++++++++++-------- 1 file changed, 69 insertions(+), 51 deletions(-) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/buttons/common/TangemButton.kt b/core/ui/src/main/java/com/tangem/core/ui/components/buttons/common/TangemButton.kt index b724e84d48..6560c617e0 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/buttons/common/TangemButton.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/buttons/common/TangemButton.kt @@ -1,12 +1,20 @@ package com.tangem.core.ui.components.buttons.common -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.requiredSizeIn import androidx.compose.material.* import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.composed import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.tangem.core.ui.components.SpacerW import com.tangem.core.ui.res.TangemTheme @Suppress("LongParameterList") @@ -30,67 +38,77 @@ fun TangemButton( elevation = elevation, shape = size.toShape(), colors = colors, - contentPadding = if (showProgress) ButtonDefaults.ContentPadding else size.toContentPadding(icon = icon), + contentPadding = size.toContentPadding(icon = icon), ) { - ButtonContent( - text = text, - textStyle = textStyle, + ButtonContentContainer( buttonIcon = icon, - colors = colors, + iconPadding = size.toIconPadding(), showProgress = showProgress, - enabled = enabled, - size = size, + progressIndicator = { + CircularProgressIndicator( + modifier = Modifier.buttonContentSize(textStyle), + color = colors.contentColor(enabled = enabled).value, + strokeWidth = TangemTheme.dimens.size4, + ) + }, + text = { + Text( + modifier = Modifier.alignByBaseline(), + text = text, + style = textStyle, + color = colors.contentColor(enabled = enabled).value, + textAlign = TextAlign.Center, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + }, + icon = { iconResId -> + Icon( + modifier = Modifier.buttonContentSize(textStyle), + painter = painterResource(id = iconResId), + tint = colors.contentColor(enabled = enabled).value, + contentDescription = null, + ) + }, ) } } @Suppress("LongParameterList") @Composable -private fun ButtonContent( - text: String, - textStyle: TextStyle, +private inline fun RowScope.ButtonContentContainer( buttonIcon: TangemButtonIconPosition, - colors: ButtonColors, - size: TangemButtonSize, - enabled: Boolean, + iconPadding: Dp, showProgress: Boolean, + progressIndicator: @Composable RowScope.() -> Unit, + text: @Composable RowScope.() -> Unit, + icon: @Composable RowScope.(Int) -> Unit, ) { - val icon = @Composable { iconResId: Int -> - Icon( - modifier = Modifier.size(TangemTheme.dimens.size20), - painter = painterResource(id = iconResId), - tint = colors.contentColor(enabled = enabled).value, - contentDescription = null, - ) + if (showProgress) { + progressIndicator() + } else { + if (buttonIcon is TangemButtonIconPosition.Start) { + icon(buttonIcon.iconResId) + SpacerW(width = iconPadding) + } + text() + if (buttonIcon is TangemButtonIconPosition.End) { + SpacerW(width = iconPadding) + icon(buttonIcon.iconResId) + } + } +} + +private fun Modifier.buttonContentSize(buttonTextStyle: TextStyle): Modifier = composed { + val minContentElementSize = TangemTheme.dimens.size20 + val maxContentElementSize = remember(key1 = buttonTextStyle.lineHeight) { + buttonTextStyle.lineHeight.value.dp + 4.dp } - if (showProgress) { - Box(modifier = Modifier.wrapContentSize()) { - CircularProgressIndicator( - modifier = Modifier - .align(Alignment.Center) - .size(TangemTheme.dimens.size24), - color = colors.contentColor(enabled = enabled).value, - strokeWidth = TangemTheme.dimens.size4, - ) - } - } else { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(size.toIconPadding()), - ) { - if (buttonIcon is TangemButtonIconPosition.Start) { - icon(buttonIcon.iconResId) - } - Text( - text = text, - style = textStyle, - color = colors.contentColor(enabled = enabled).value, - maxLines = 1, - ) - if (buttonIcon is TangemButtonIconPosition.End) { - icon(buttonIcon.iconResId) - } - } - } + this.requiredSizeIn( + minWidth = minContentElementSize, + minHeight = minContentElementSize, + maxWidth = maxContentElementSize, + maxHeight = maxContentElementSize, + ) } \ No newline at end of file From 5d22cad1c8049a36a1659145499bb30735fab87f Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 6 Sep 2023 13:31:59 +0300 Subject: [PATCH 10/10] Updated on 2026-08-14 --- .../java/com/tangem/tap/features/home/compose/StoriesScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt b/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt index 01d6c35c2d..64b737596f 100644 --- a/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/home/compose/StoriesScreen.kt @@ -174,7 +174,7 @@ private fun StoriesScreenContent(config: StoriesScreenContentConfig, modifier: M null } else { ColorFilter.tint(TangemColorPalette.Dark6) - } + }, ) when (config.currentStory) { Stories.OneInchPromo -> Learn2earnStoriesScreen(config.onLearn2earnClick)