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/feedback/FeedbackManager.kt b/app/src/main/java/com/tangem/tap/features/feedback/FeedbackManager.kt index 0e4fe0a875..0ae3d143a8 100644 --- a/app/src/main/java/com/tangem/tap/features/feedback/FeedbackManager.kt +++ b/app/src/main/java/com/tangem/tap/features/feedback/FeedbackManager.kt @@ -218,7 +218,6 @@ interface EmailData { fun joinTogether(infoHolder: AdditionalEmailInfo): String { return "$mainMessage\n\n\n\n" + - "Following information is optional. You can erase it if you don’t want to share it.\n" + createOptionalMessage(infoHolder) } } 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 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 041c1aa018..a8830f8137 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -109,7 +109,7 @@ You may experience NFC problems with some iPhone 7/7+ during the extraction This card has been already topped up and signed transactions in the past. Consider immediate withdrawal of all funds if you have received this card from an untrusted source. Warning - This card it is not designed to work with Tangem + This card is not designed to work with this app The card you scanned is a development card. Don’t accept it as a payment Tangem cards manufactured before September 2019 cannot currently be extracted with an iPhone. We’re working hard with Apple to make it possible in future versions of iOS.