From 3b05c5db10d1d0de1432b2932190ee4e262ca0d0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 15 Dec 2021 15:14:17 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../java/com/tangem/tap/domain/ProductType.kt | 3 +- .../com/tangem/tap/domain/TangemSdkManager.kt | 2 +- .../com/tangem/tap/domain/TapWorkarounds.kt | 3 +- .../tasks/product/CreateProductWalletTask.kt | 76 +++---- .../domain/tasks/product/ScanProductTask.kt | 193 ++++++++++++------ .../tap/domain/twins/FinalizeTwinTask.kt | 3 +- .../features/details/redux/DetailsReducer.kt | 6 +- .../features/onboarding/OnboardingHelper.kt | 7 +- .../wallet/redux/OnboardingWalletAction.kt | 2 +- .../redux/OnboardingWalletMiddleware.kt | 9 +- .../wallet/redux/OnboardingWalletReducer.kt | 5 +- .../wallet/redux/OnboardingWalletState.kt | 3 +- .../products/wallet/ui/BackupCardsWidget.kt | 27 ++- .../wallet/ui/OnboardingWalletFragment.kt | 42 ++-- .../features/tokens/redux/TokensMiddleware.kt | 4 +- .../middlewares/MultiWalletMiddleware.kt | 4 +- 16 files changed, 240 insertions(+), 149 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/ProductType.kt b/app/src/main/java/com/tangem/tap/domain/ProductType.kt index 07cbea8905..4f57e8949d 100644 --- a/app/src/main/java/com/tangem/tap/domain/ProductType.kt +++ b/app/src/main/java/com/tangem/tap/domain/ProductType.kt @@ -4,5 +4,6 @@ package com.tangem.tap.domain [REDACTED_AUTHOR] */ enum class ProductType { - Note, Wallet, Twins, Other + Note, Twins, Wallet + } \ No newline at end of file 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 af6b04b1e9..455a6b973d 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSdkManager.kt @@ -45,7 +45,7 @@ class TangemSdkManager(private val tangemSdk: TangemSdk, private val context: Co analyticsHandler.triggerEvent(AnalyticsEvent.READY_TO_SCAN, null) val message = Message(context.getString(messageRes ?: R.string.initial_message_scan_header)) - return runTaskAsyncReturnOnMain(ScanProductTask(null, currenciesRepository, shouldDeriveWC), null, message) + return runTaskAsyncReturnOnMain(ScanProductTask(null, currenciesRepository), null, message) .also { sendScanFailuresToAnalytics(analyticsHandler, it) } } diff --git a/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt b/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt index 45e19eb81a..ffc8df824c 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWorkarounds.kt @@ -35,8 +35,7 @@ object TapWorkarounds { @Deprecated("Use ScanResponse.isTangemNote") fun isTangemNote(card: Card): Boolean = tangemNoteBatches.contains(card.batchId) - @Deprecated("Use ScanResponse.isTangemWallet") - fun isTangemWallet(card: Card): Boolean = tangemWalletBatches.contains(card.batchId) + fun isTangemWalletBatch(card: Card): Boolean = tangemWalletBatches.contains(card.batchId) fun getTangemNoteBlockchain(card: Card): Blockchain? = tangemNoteBatches[card.batchId] diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt index 99e8cd0f62..25e3d98836 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/CreateProductWalletTask.kt @@ -2,7 +2,6 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.common.CompletionResult import com.tangem.common.card.Card import com.tangem.common.card.EllipticCurve -import com.tangem.common.card.FirmwareVersion import com.tangem.common.core.CardSession import com.tangem.common.core.CardSessionRunnable import com.tangem.common.core.TangemSdkError @@ -45,8 +44,7 @@ class CreateProductWalletTask( val commandProcessor = when (type) { ProductType.Note -> CreateWalletTangemNote() ProductType.Twins -> throw UnsupportedOperationException("Use the TwinCardsManager to create a wallet") - ProductType.Wallet -> CreateWalletTangemWallet() - else -> CreateWalletOtherCards() + else -> CreateWalletTangemWallet() } commandProcessor.proceed(card, session) { when (it) { @@ -106,13 +104,27 @@ private class CreateWalletTangemWallet : ProductCommandProcessor) -> Unit, ) { - val supportedCurves = setOf(EllipticCurve.Secp256k1, EllipticCurve.Ed25519) - val curves = card.getCurvesForNonCreatedWallets().intersect(supportedCurves).toList() + val curves = card.getCurvesForNonCreatedWallets() CreateWalletsTask(curves).run(session) { result -> when (result) { is CompletionResult.Success -> { createWalletResponse = result.data.createWalletResponses[0] - linkPrimaryCard(card, session, callback) + when { + card.settings.isBackupAllowed -> { + linkPrimaryCard(session, callback) + } + card.settings.isHDWalletAllowed -> { + deriveKeys(session, callback) + } + else -> { + callback( + CompletionResult.Success( + CreateProductWalletTaskResponse(card = session.environment.card!!) + ) + ) + } + } + } is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) } @@ -120,7 +132,6 @@ private class CreateWalletTangemWallet : ProductCommandProcessor) -> Unit, ) { @@ -128,7 +139,7 @@ private class CreateWalletTangemWallet : ProductCommandProcessor { primaryCard = result.data - deriveKeys(card, session, callback) + deriveKeys(session, callback) } is CompletionResult.Failure -> { callback(CompletionResult.Failure(result.error)) @@ -138,7 +149,6 @@ private class CreateWalletTangemWallet : ProductCommandProcessor) -> Unit, ) { @@ -149,42 +159,34 @@ private class CreateWalletTangemWallet : ProductCommandProcessor when (result) { is CompletionResult.Success -> { val derivedKeys = mapOf(response.wallet.publicKey.toMapKey() to result.data) - callback(CompletionResult.Success(CreateProductWalletTaskResponse( - card = session.environment.card!!, - derivedKeys = derivedKeys, - primaryCard = primaryCard - ))) + callback( + CompletionResult.Success( + CreateProductWalletTaskResponse( + card = session.environment.card!!, + derivedKeys = derivedKeys, + primaryCard = primaryCard + ) + ) + ) } is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) } } } -} - -private class CreateWalletOtherCards : ProductCommandProcessor { - - override fun proceed( - card: Card, - session: CardSession, - callback: (result: CompletionResult) -> Unit, - ) { - val firmwareVersion = card.firmwareVersion - val task = if (firmwareVersion < FirmwareVersion.MultiWalletAvailable) { - CreateWalletsTask(listOf(card.supportedCurves.first())) - } else { - CreateWalletsTask(card.getCurvesForNonCreatedWallets()) - } - - task.run(session) { result -> - when (result) { - is CompletionResult.Success -> callback(CompletionResult.Success(result.data.createWalletResponses[0])) - is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) - } - } - } } \ No newline at end of file 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 278e424a2a..40c7a00ded 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 @@ -47,7 +47,8 @@ data class ScanResponse( ) : CommandResponse { fun getBlockchain(): Blockchain { - if (productType == ProductType.Note) return getTangemNoteBlockchain(card) ?: return Blockchain.Unknown + if (productType == ProductType.Note) return getTangemNoteBlockchain(card) + ?: return Blockchain.Unknown val blockchainName: String = walletData?.blockchain ?: return Blockchain.Unknown return Blockchain.fromId(blockchainName) } @@ -66,17 +67,19 @@ data class ScanResponse( fun isTangemNote(): Boolean = productType == ProductType.Note fun isTangemWallet(): Boolean = productType == ProductType.Wallet fun isTangemTwins(): Boolean = productType == ProductType.Twins - fun isTangemOtherCards(): Boolean = productType == ProductType.Other - fun twinsIsTwinned(): Boolean = card.isTangemTwins() && walletData != null && secondTwinPublicKey != null + fun supportsHdWallet(): Boolean = card.settings.isHDWalletAllowed + fun supportsBackup(): Boolean = card.settings.isBackupAllowed + + fun twinsIsTwinned(): Boolean = + card.isTangemTwins() && walletData != null && secondTwinPublicKey != null } typealias KeyWalletPublicKey = ByteArrayKey class ScanProductTask( val card: Card? = null, - private val currenciesRepository: CurrenciesRepository?, - private val shouldDeriveWC: Boolean + private val currenciesRepository: CurrenciesRepository? ) : CardSessionRunnable { override fun run( @@ -97,15 +100,22 @@ class ScanProductTask( val commandProcessor = when { TapWorkarounds.isTangemNote(card) -> ScanNoteProcessor() card.isTangemTwins() -> ScanTwinProcessor() - TapWorkarounds.isTangemWallet(card) -> ScanWalletProcessor(currenciesRepository, shouldDeriveWC) - else -> ScanOtherCardsProcessor() + else -> ScanWalletProcessor(currenciesRepository) } commandProcessor.proceed(card, session) { processorResult -> when (processorResult) { is CompletionResult.Success -> ScanTask().run(session) { scanTaskResult -> when (scanTaskResult) { - is CompletionResult.Success -> callback(CompletionResult.Success(processorResult.data)) - is CompletionResult.Failure -> callback(CompletionResult.Failure(scanTaskResult.error)) + is CompletionResult.Success -> callback( + CompletionResult.Success( + processorResult.data + ) + ) + is CompletionResult.Failure -> callback( + CompletionResult.Failure( + scanTaskResult.error + ) + ) } } is CompletionResult.Failure -> callback(CompletionResult.Failure(processorResult.error)) @@ -129,13 +139,20 @@ private class ScanNoteProcessor : ProductCommandProcessor { session: CardSession, callback: (result: CompletionResult) -> Unit ) { - callback(CompletionResult.Success(ScanResponse(card, ProductType.Note, session.environment.walletData))) + callback( + CompletionResult.Success( + ScanResponse( + card, + ProductType.Note, + session.environment.walletData + ) + ) + ) } } private class ScanWalletProcessor( - private val currenciesRepository: CurrenciesRepository?, - private val shouldDeriveWC: Boolean + private val currenciesRepository: CurrenciesRepository? ) : ProductCommandProcessor { var primaryCard: PrimaryCard? = null @@ -145,9 +162,60 @@ private class ScanWalletProcessor( session: CardSession, callback: (result: CompletionResult) -> Unit ) { - val activationIsFinished = preferencesStorage.usedCardsPrefStorage.isActivationFinished(card.cardId) + createMissingWalletsIfNeeded(card, session, callback) + } - if (card.backupStatus?.isActive != true && !activationIsFinished && card.wallets.isNotEmpty()) { + private fun createMissingWalletsIfNeeded( + card: Card, + session: CardSession, + callback: (result: CompletionResult) -> Unit + ) { + if (card.wallets.isEmpty() || card.firmwareVersion < FirmwareVersion.MultiWalletAvailable) { + startLinkingForBackupIfNeeded(card, session, callback) + return + } + + val curvesToCreate = card.getCurvesForNonCreatedWallets() + if (curvesToCreate.isEmpty()) { + startLinkingForBackupIfNeeded(card, session, callback) + return + } + + CreateWalletsTask(curvesToCreate).run(session) { result -> + when (result) { + is CompletionResult.Success -> { + PreflightReadTask( + PreflightReadMode.FullCardRead, + card.cardId + ).run(session) { readResult -> + when (readResult) { + is CompletionResult.Success -> { + startLinkingForBackupIfNeeded(card, session, callback) + } + is CompletionResult.Failure -> callback( + CompletionResult.Failure( + readResult.error + ) + ) + } + } + } + is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) + } + } + } + + private fun startLinkingForBackupIfNeeded( + card: Card, + session: CardSession, + callback: (result: CompletionResult) -> Unit + ) { + val activationIsFinished = + preferencesStorage.usedCardsPrefStorage.isActivationFinished(card.cardId) + + if (card.backupStatus == Card.BackupStatus.NoBackup && + !activationIsFinished && card.wallets.isNotEmpty() + ) { StartPrimaryCardLinkingTask().run(session) { linkingResult -> when (linkingResult) { is CompletionResult.Success -> { @@ -162,7 +230,6 @@ private class ScanWalletProcessor( } else { deriveKeysIfNeeded(card, session, callback) } - } private fun deriveKeysIfNeeded( @@ -174,12 +241,16 @@ private class ScanWalletProcessor( val wallet = card.wallets.firstOrNull { it.curve == EllipticCurve.Secp256k1 } if (derivationPaths.isNullOrEmpty() || wallet == null || wallet.chainCode == null) { - callback(CompletionResult.Success(ScanResponse( - card = card, - productType = ProductType.Wallet, - walletData = session.environment.walletData, - primaryCard = primaryCard - ))) + callback( + CompletionResult.Success( + ScanResponse( + card = card, + productType = ProductType.Wallet, + walletData = session.environment.walletData, + primaryCard = primaryCard + ) + ) + ) return } @@ -213,8 +284,14 @@ private class ScanWalletProcessor( (cardCurrencies.blockchains + tokenBlockchains).toMutableList() } - if (shouldDeriveWC) { - blockchainsToDerive.addAll(listOf(Blockchain.Ethereum, Blockchain.Binance, Blockchain.EthereumTestnet)) + if (card.settings.isHDWalletAllowed) { + blockchainsToDerive.addAll( + listOf( + Blockchain.Ethereum, + Blockchain.Binance, + Blockchain.EthereumTestnet + ) + ) } return blockchainsToDerive.toSet() @@ -234,17 +311,39 @@ private class ScanTwinProcessor : ProductCommandProcessor { is CompletionResult.Success -> { val publicKey = card.getSingleWallet()?.publicKey if (publicKey == null) { - callback(CompletionResult.Success(ScanResponse(card, ProductType.Twins, null))) + callback( + CompletionResult.Success( + ScanResponse( + card, + ProductType.Twins, + null + ) + ) + ) return@run } - val verified = TwinsHelper.verifyTwinPublicKey(readDataResult.data.issuerData, publicKey) + val verified = + TwinsHelper.verifyTwinPublicKey(readDataResult.data.issuerData, publicKey) if (verified) { val twinPublicKey = readDataResult.data.issuerData.sliceArray(0 until 65) val walletData = session.environment.walletData - val response = ScanResponse(card, ProductType.Twins, walletData, twinPublicKey.toHexString()) + val response = ScanResponse( + card, + ProductType.Twins, + walletData, + twinPublicKey.toHexString() + ) callback(CompletionResult.Success(response)) } else { - callback(CompletionResult.Success(ScanResponse(card, ProductType.Twins, null))) + callback( + CompletionResult.Success( + ScanResponse( + card, + ProductType.Twins, + null + ) + ) + ) } } is CompletionResult.Failure -> @@ -255,43 +354,9 @@ private class ScanTwinProcessor : ProductCommandProcessor { } -private class ScanOtherCardsProcessor : ProductCommandProcessor { - - override fun proceed(card: Card, session: CardSession, callback: (result: CompletionResult) -> Unit) { - val walletData = session.environment.walletData - - if (card.wallets.isEmpty() || card.firmwareVersion < FirmwareVersion.MultiWalletAvailable) { - callback(CompletionResult.Success(ScanResponse(card, ProductType.Other, walletData))) - return - } - - val curvesToCreate = card.getCurvesForNonCreatedWallets() - if (curvesToCreate.isEmpty()) { - callback(CompletionResult.Success(ScanResponse(card, ProductType.Other, walletData))) - return - } - - CreateWalletsTask(curvesToCreate).run(session) { result -> - when (result) { - is CompletionResult.Success -> { - PreflightReadTask(PreflightReadMode.FullCardRead, card.cardId).run(session) { readResult -> - when (readResult) { - is CompletionResult.Success -> { - val response = ScanResponse(readResult.data, ProductType.Other, walletData) - callback(CompletionResult.Success(response)) - } - is CompletionResult.Failure -> callback(CompletionResult.Failure(readResult.error)) - } - } - } - is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error)) - } - } - } -} - fun Card.getCurvesForNonCreatedWallets(): List { - val curvesPresent = wallets.map { it.curve } - val curvesForNonCreatedWallets = supportedCurves.subtract(curvesPresent) + val curvesPresent = wallets.map { it.curve }.toSet() + val curvesForNonCreatedWallets = supportedCurves + .subtract(curvesPresent + EllipticCurve.Secp256r1) return curvesForNonCreatedWallets.toList() } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt index 6fb4bb28c6..51ade7b4c3 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/FinalizeTwinTask.kt @@ -23,7 +23,8 @@ class FinalizeTwinTask( PreflightReadTask(PreflightReadMode.FullCardRead).run(session) { readResult -> when (readResult) { is CompletionResult.Success -> - ScanProductTask(readResult.data, null, false).run(session, callback) + ScanProductTask(readResult.data, null) + .run(session, callback) is CompletionResult.Failure -> callback(CompletionResult.Failure(readResult.error)) } 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 71f4bd5fd7..7ea35d3284 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 @@ -51,7 +51,7 @@ private fun handlePrepareScreen( cardInfo = action.scanResponse.card.toCardInfo(), appCurrencyState = AppCurrencyState(action.fiatCurrencyName), cardTermsOfUseUrl = action.cardTou.getUrl(action.scanResponse.card), - createBackupAllowed = action.scanResponse.isTangemWallet() && !backupIsActive, + createBackupAllowed = action.scanResponse.card.backupStatus == Card.BackupStatus.NoBackup, ) } @@ -65,7 +65,7 @@ private fun handleEraseWallet( val notAllowedByAnyWallet = card?.wallets?.any { it.settings.isPermanent } ?: false val notAllowedByCard = notAllowedByAnyWallet || (card?.isWalletDataSupported == true && - (!state.scanResponse.isTangemNote() && !state.scanResponse.isTangemWallet())) + (!state.scanResponse.isTangemNote() && !state.scanResponse.supportsBackup())) val notEmpty = state.wallets.any { it.hasPendingTransactions() || it.amounts.toSendableAmounts().isNotEmpty() @@ -139,7 +139,7 @@ private fun handleSecurityAction( state.scanResponse?.isTangemNote() == true -> { EnumSet.of(SecurityOption.LongTap) } - state.scanResponse?.isTangemWallet() == true -> { + state.scanResponse?.supportsBackup() == true -> { EnumSet.of(state.securityScreenState?.currentOption) } else -> prepareAllowedSecurityOptions( diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt index 6a097f6511..258701cabc 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt @@ -32,9 +32,12 @@ class OnboardingHelper { fun whereToNavigate(scanResponse: ScanResponse): AppScreen { return when (scanResponse.productType) { ProductType.Note -> AppScreen.OnboardingNote - ProductType.Wallet -> AppScreen.OnboardingWallet + ProductType.Wallet -> if (scanResponse.card.settings.isBackupAllowed) { + AppScreen.OnboardingWallet + } else { + AppScreen.OnboardingOther + } ProductType.Twins -> AppScreen.OnboardingTwins - ProductType.Other -> AppScreen.OnboardingOther } } } 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 d900eaf35f..9bfdaaf381 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 @@ -22,7 +22,7 @@ sealed class OnboardingWalletAction : Action { sealed class BackupAction : Action { object DetermineBackupStep : BackupAction() - object IntroduceBackup : BackupAction() + data class IntroduceBackup(val buyCardsUrl: String? = null) : BackupAction() object StartBackup : BackupAction() object DismissBackup : BackupAction() 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 14a8788714..1816465f6e 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 @@ -110,7 +110,14 @@ private fun handleWalletAction(action: Action) { BackupService.State.FinalizingPrimaryCard -> BackupAction.PrepareToWritePrimaryCard is BackupService.State.FinalizingBackupCard -> BackupAction.PrepareToWriteBackupCard(backupState.index) - else -> BackupAction.IntroduceBackup + else -> { + val url = if (card?.issuer?.name?.lowercase()?.contains("tangem") == true) { + BUY_WALLET_URL + } else { + null + } + BackupAction.IntroduceBackup(url) + } } store.dispatch(newAction) } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt index 09aad69d48..89542c532e 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt @@ -39,9 +39,10 @@ class BackupReducer { ): BackupState { return when (action) { - BackupAction.IntroduceBackup -> BackupState( + is BackupAction.IntroduceBackup -> BackupState( backupStep = BackupStep.InitBackup, - canSkipBackup = state.canSkipBackup + canSkipBackup = state.canSkipBackup, + buyAdditionalCardsUrl = action.buyCardsUrl ) BackupAction.StartAddingPrimaryCard -> state.copy(backupStep = BackupStep.ScanOriginCard) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt index d8d0c687b7..a048261a6d 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt @@ -52,7 +52,8 @@ data class BackupState( val accessCodeError: AccessCodeError? = null, val backupStep: BackupStep = BackupStep.InitBackup, val maxBackupCards: Int = 2, - val canSkipBackup: Boolean = true + val canSkipBackup: Boolean = true, + val buyAdditionalCardsUrl: String? = null ) enum class AccessCodeError { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt index d5b5065f36..e4de53c9a4 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/BackupCardsWidget.kt @@ -15,7 +15,13 @@ class BackupCardsWidget( val getTopOfAnchorViewForActivateState: () -> Float, ) { + var currentState: WidgetState? = null + fun toWelcome(animate: Boolean = true, onEnd: () -> Unit = {}) { + if (currentState == WidgetState.WELCOME) return + + currentState = WidgetState.WELCOME + val animator = createAnimator(animate, onEnd) animator.playTogether( createAnimator(BackupCardType.ORIGIN, createWelcomeProperties(BackupCardType.ORIGIN)), @@ -26,6 +32,10 @@ class BackupCardsWidget( } fun toFolded(animate: Boolean = true, onEnd: () -> Unit = {}) { + if (currentState == WidgetState.FOLDED) return + + currentState = WidgetState.FOLDED + val animator = createAnimator(animate, onEnd) animator.playTogether( createAnimator(BackupCardType.ORIGIN, createLeapfrogProperties(BackupCardType.ORIGIN)), @@ -36,6 +46,10 @@ class BackupCardsWidget( } fun toFan(animate: Boolean = true, onEnd: () -> Unit = {}) { + if (currentState == WidgetState.FAN) return + + currentState = WidgetState.FAN + val animator = createAnimator(animate, onEnd) animator.playTogether( createAnimator(BackupCardType.ORIGIN, createFanProperties(BackupCardType.ORIGIN)), @@ -46,6 +60,8 @@ class BackupCardsWidget( } fun toLeapfrog(animate: Boolean = true, onEnd: () -> Unit = {}) { + currentState = WidgetState.LEAPFROG + val animator = createAnimator(animate, onEnd) animator.playTogether( createAnimator(BackupCardType.ORIGIN, createLeapfrogProperties(BackupCardType.ORIGIN)), @@ -60,15 +76,6 @@ class BackupCardsWidget( animator.start() } } -// -// fun toActivate(animate: Boolean = true, onEnd: () -> Unit = {}) { -// val animator = createAnimator(animate, onEnd) -// animator.playTogether( -// createAnimator(TwinCardNumber.First, createActivateProperties(TwinCardNumber.First)), -// createAnimator(TwinCardNumber.Second, createActivateProperties(TwinCardNumber.Second)) -// ) -// animator.start() -// } private fun createAnimator(animate: Boolean, onEnd: () -> Unit): AnimatorSet { return AnimatorSet().apply { @@ -196,6 +203,8 @@ class BackupCardsWidget( fun getSecondBackupCardView(): ImageView { return getLeapViewByCardNumber(BackupCardType.SECOND_BACKUP).view as ImageView } + + enum class WidgetState { WELCOME, FOLDED, FAN, LEAPFROG } } 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 f415e176b9..5a1ccf6684 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 @@ -148,19 +148,10 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), } private fun showScanOriginCard(state: BackupState) { - - toolbar.title = getText(R.string.onboarding_navbar_title_creating_backup) + prepareBackupView() cardsWidget.toFolded() - tv_header.show() - tv_body.show() - view_pager_backup_info.hide() - tab_layout_backup_info.hide() - - imv_first_backup_card.show() - imv_second_backup_card.show() - tv_header.text = getText(R.string.onboarding_title_scan_origin_card) tv_body.text = getString( R.string.onboarding_subtitle_scan_origin_card, @@ -171,9 +162,20 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), btn_main_action.setOnClickListener { store.dispatch(BackupAction.ScanPrimaryCard) } } - private fun showAddBackupCards(state: BackupState) { + private fun prepareBackupView() { + toolbar.title = getText(R.string.onboarding_navbar_title_creating_backup) + + tv_header.show() + tv_body.show() + view_pager_backup_info.hide() + tab_layout_backup_info.hide() + imv_first_backup_card.show() imv_second_backup_card.show() + } + + private fun showAddBackupCards(state: BackupState) { + prepareBackupView() accessCodeDialog?.dismiss() accessCodeDialog = null @@ -190,11 +192,12 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), when (state.backupCardsNumber) { 0 -> { - cardsWidget.toFan() + cardsWidget.toFan() { + cardsWidget.getFirstBackupCardView().animate().alpha(0.6f).setDuration(200) + cardsWidget.getSecondBackupCardView().animate().alpha(0.2f).setDuration(200) + } tv_header.text = getText(R.string.onboarding_title_no_backup_cards) tv_body.text = getText(R.string.onboarding_subtitle_no_backup_cards) - cardsWidget.getFirstBackupCardView().alpha = 0.6f - cardsWidget.getSecondBackupCardView().alpha = 0.2f } 1 -> { tv_header.text = getText(R.string.onboarding_title_one_backup_card) @@ -283,10 +286,6 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), cardsWidget.toLeapfrog() -// imv_front_card.alpha = 1f -// imv_first_backup_card.alpha = 1f -// imv_second_backup_card.alpha = 1f - btn_alternative_action.hide() } @@ -373,9 +372,12 @@ class OnboardingWalletFragment : Fragment(R.layout.fragment_onboarding_wallet), override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.shop, menu) - val backupStep = store.state.onboardingWalletState.backupState.backupStep + val backupState = store.state.onboardingWalletState.backupState + val backupStep = backupState.backupStep + val shopMenuShouldBeVisible = - backupStep == BackupStep.ScanOriginCard || backupStep == BackupStep.AddBackupCards + (backupStep == BackupStep.ScanOriginCard || backupStep == BackupStep.AddBackupCards) && + backupState.buyAdditionalCardsUrl != null menu.getItem(0).isVisible = shopMenuShouldBeVisible } diff --git a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt index 2176e4ea51..92fe81b661 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/redux/TokensMiddleware.kt @@ -46,7 +46,7 @@ class TokensMiddleware { isTestNet = isTestcard ) val currencies = CurrencyListItem.createListOfCurrencies(blockchains, tokens).toMutableList() - if (scanResponse.isTangemWallet()) { + if (scanResponse.supportsHdWallet()) { currencies.forEach { when (it) { is CurrencyListItem.TitleListItem -> { @@ -81,7 +81,7 @@ class TokensMiddleware { .map { it.token } if (blockchains.isEmpty() && tokens.isEmpty()) return - if (scanResponse.isTangemWallet()) { + if (scanResponse.supportsHdWallet()) { deriveMissingBlockchains(scanResponse, blockchains, tokens) } else { submitAdd(blockchains, tokens) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index 11d7232cd3..ace2084261 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -85,7 +85,7 @@ class MultiWalletMiddleware { } is WalletAction.MultiWallet.FindBlockchainsInUse -> { val scanResponse = globalState.scanResponse ?: return - if (scanResponse.isTangemWallet()) return + if (scanResponse.supportsHdWallet()) return val cardFirmware = scanResponse.card.firmwareVersion val blockchains = currenciesRepository.getBlockchains(cardFirmware) @@ -125,7 +125,7 @@ class MultiWalletMiddleware { } is WalletAction.MultiWallet.FindTokensInUse -> { val scanResponse = globalState.scanResponse ?: return - if (scanResponse.isTangemWallet()) return + if (scanResponse.supportsHdWallet()) return val walletFactory = tapWalletManager.walletManagerFactory val card = scanResponse.card