Updated on 2026-08-14

This commit is contained in:
Tangem 2025-01-27 11:12:31 +03:00
parent ae9bb1fc07
commit bbad1bdfd9
3 changed files with 82 additions and 107 deletions

View file

@ -14,6 +14,7 @@
</value>
</option>
<option name="LINE_BREAK_AFTER_MULTILINE_WHEN_ENTRY" value="false" />
<option name="INDENT_BEFORE_ARROW_ON_NEW_LINE" value="false" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="5" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="3" />
<option name="ALLOW_TRAILING_COMMA" value="true" />

View file

@ -99,7 +99,7 @@ object OnboardingHelper {
}
}
fun saveWallet(
suspend fun saveWallet(
alreadyCreatedWallet: UserWallet?,
scanResponse: ScanResponse,
accessCode: String? = null,
@ -107,46 +107,42 @@ object OnboardingHelper {
hasBackupError: Boolean = false,
) {
Analytics.setContext(scanResponse)
scope.launch {
val settingsRepository = store.inject(DaggerGraphState::settingsRepository)
when {
// When should save user wallets, then save card without navigate to save wallet screen
store.inject(DaggerGraphState::walletsRepository).shouldSaveUserWalletsSync() -> {
store.dispatchWithMain(
SaveWalletAction.ProvideBackupInfo(
scanResponse = scanResponse,
accessCode = accessCode,
backupCardsIds = backupCardsIds?.toSet(),
),
)
val settingsRepository = store.inject(DaggerGraphState::settingsRepository)
when {
// When should save user wallets, then save card without navigate to save wallet screen
store.inject(DaggerGraphState::walletsRepository).shouldSaveUserWalletsSync() -> {
store.dispatchWithMain(
SaveWalletAction.ProvideBackupInfo(
scanResponse = scanResponse,
accessCode = accessCode,
backupCardsIds = backupCardsIds?.toSet(),
),
)
store.dispatchWithMain(
SaveWalletAction.SaveWalletAfterBackup(
hasBackupError = hasBackupError,
shouldNavigateToWallet = false,
),
)
}
// When should not save user wallets but device has biometry and save wallet screen has not been shown,
// then open save wallet screen
tangemSdkManager.checkCanUseBiometry() && settingsRepository.shouldShowSaveUserWalletScreen() -> {
proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError, alreadyCreatedWallet)
delay(timeMillis = 1_200)
store.dispatchOnMain(
SaveWalletAction.ProvideBackupInfo(
scanResponse = scanResponse,
accessCode = accessCode,
backupCardsIds = backupCardsIds?.toSet(),
),
)
}
// If device has no biometry and save wallet screen has been shown, then go through old scenario
else -> {
proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError, alreadyCreatedWallet)
}
store.dispatchWithMain(
SaveWalletAction.SaveWalletAfterBackup(
hasBackupError = hasBackupError,
shouldNavigateToWallet = false,
),
)
}
// When should not save user wallets but device has biometry and save wallet screen has not been shown,
// then open save wallet screen
tangemSdkManager.checkCanUseBiometry() && settingsRepository.shouldShowSaveUserWalletScreen() -> {
proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError, alreadyCreatedWallet)
delay(timeMillis = 1_200)
store.dispatchWithMain(
SaveWalletAction.ProvideBackupInfo(
scanResponse = scanResponse,
accessCode = accessCode,
backupCardsIds = backupCardsIds?.toSet(),
),
)
}
// If device has no biometry and save wallet screen has been shown, then go through old scenario
else -> proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError, alreadyCreatedWallet)
}
}

View file

@ -4,7 +4,6 @@ import android.net.Uri
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tangem.common.CompletionResult
import com.tangem.common.card.Card
import com.tangem.common.core.TangemError
import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.ifNotNull
import com.tangem.common.extensions.toHexString
@ -12,6 +11,7 @@ import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.common.services.Result
import com.tangem.core.analytics.Analytics
import com.tangem.core.analytics.models.AnalyticsParam.ScreensSources
import com.tangem.core.analytics.models.event.OnboardingAnalyticsEvent
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.toWrappedList
@ -43,7 +43,6 @@ import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.features.demo.DemoHelper
import com.tangem.tap.features.home.redux.HomeAction
import com.tangem.tap.features.onboarding.OnboardingDialog
import com.tangem.tap.features.onboarding.OnboardingHelper
import com.tangem.tap.proxy.redux.DaggerGraphState
@ -52,7 +51,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.rekotlin.Action
import org.rekotlin.Middleware
import timber.log.Timber
object OnboardingWalletMiddleware {
val handler = onboardingWalletMiddleware
@ -203,7 +201,7 @@ private fun handleWalletAction(action: Action) {
}
}
private fun handleFinishBackup(scanResponse: ScanResponse, userWallet: UserWallet? = null) {
private suspend fun handleFinishBackup(scanResponse: ScanResponse, userWallet: UserWallet? = null) {
val backupState = store.state.onboardingWalletState.backupState
val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState)
@ -234,31 +232,14 @@ private fun navigateToWalletScreen() {
}
}
private suspend fun readCard(onSuccess: suspend (ScanResponse) -> Unit, onFailure: (TangemError) -> Unit) {
private suspend fun readCard(): CompletionResult<ScanResponse> {
val shouldSaveAccessCodes = store.inject(DaggerGraphState::settingsRepository).shouldSaveAccessCodes()
store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
isBiometricsRequestPolicy = shouldSaveAccessCodes,
)
store.inject(DaggerGraphState::scanCardProcessor).scan(
analyticsSource = com.tangem.core.analytics.models.AnalyticsParam.ScreensSources.Intro,
onProgressStateChange = { showProgress ->
if (showProgress) {
store.dispatch(HomeAction.ScanInProgress(scanInProgress = true))
} else {
delay(HIDE_PROGRESS_DELAY)
store.dispatch(HomeAction.ScanInProgress(scanInProgress = false))
}
},
onFailure = {
Timber.e(it, "Unable to scan card")
delay(HIDE_PROGRESS_DELAY)
store.dispatch(HomeAction.ScanInProgress(scanInProgress = false))
onFailure(it)
},
onSuccess = onSuccess,
)
return store.inject(DaggerGraphState::scanCardProcessor).scan(analyticsSource = ScreensSources.Intro)
}
private suspend fun loadArtworkForCard(cardId: String, cardPublicKey: ByteArray, defaultArtwork: Uri?): Uri {
@ -478,7 +459,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
is TangemSdkError.CardVerificationFailed -> {
Analytics.send(
event = OnboardingAnalyticsEvent.Onboarding.OfflineAttestationFailed(
com.tangem.core.analytics.models.AnalyticsParam.ScreensSources.Backup,
ScreensSources.Backup,
),
)
@ -660,23 +641,22 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
Analytics.send(Onboarding.Finished())
scope.launch {
store.state.globalState.onboardingState.onboardingManager?.finishActivation(
cardIds = gatherCardIds(backupState, card),
)
}
if (scanResponse == null) {
scope.launch {
readCard(
onSuccess = { newScanResponse ->
handleFinishBackup(newScanResponse)
},
onFailure = {
store.dispatchNavigationAction(AppRouter::pop)
},
launch {
store.state.globalState.onboardingState.onboardingManager?.finishActivation(
cardIds = gatherCardIds(backupState, card),
)
}
} else {
handleFinishBackup(scanResponse)
with(scanResponse) {
if (this == null) {
when (val result = readCard()) {
is CompletionResult.Success -> handleFinishBackup(result.data)
is CompletionResult.Failure -> store.dispatchNavigationAction(AppRouter::pop)
}
} else {
handleFinishBackup(scanResponse = this)
}
}
}
}
is BackupAction.FinishBackup -> {
@ -692,40 +672,39 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
scanResponse = requireNotNull(value = scanResponse, lazyMessage = { "ScanResponse is null" }),
backupState = backupState,
)
val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
when (backupState.startedSource) {
BackupStartedSource.Onboarding -> saveWallet(
userWalletsListManager = userWalletsListManager,
userWallet = userWallet,
scanResponse = scanResponse,
backupState = backupState,
)
BackupStartedSource.CreateBackup -> updateWallet(
userWalletsListManager = userWalletsListManager,
userWallet = userWallet,
backupState = backupState,
)
}
} else {
delay(HIDE_PROGRESS_DELAY)
readCard(
onSuccess = { newScanResponse ->
scanResponse = newScanResponse
userWallet = createUserWallet(newScanResponse, backupState)
},
onFailure = {
when (val result = readCard()) {
is CompletionResult.Failure -> {
store.dispatchNavigationAction(AppRouter::pop)
},
return@launch
}
is CompletionResult.Success -> {
scanResponse = result.data
userWallet = createUserWallet(scanResponse = result.data, backupState = backupState)
}
}
}
val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
when (backupState.startedSource) {
BackupStartedSource.Onboarding -> saveWallet(
userWalletsListManager = userWalletsListManager,
userWallet = userWallet,
scanResponse = scanResponse,
backupState = backupState,
)
BackupStartedSource.CreateBackup -> updateWallet(
userWalletsListManager = userWalletsListManager,
userWallet = userWallet,
backupState = backupState,
)
}
scope.launch {
userWallet?.let {
if (it.scanResponse.cardTypesResolver.isWallet2() && it.isImported) {
store.inject(DaggerGraphState::walletsRepository).markWallet2WasCreated(it.walletId)
}
if (userWallet.scanResponse.cardTypesResolver.isWallet2() && userWallet.isImported) {
store.inject(DaggerGraphState::walletsRepository).markWallet2WasCreated(userWallet.walletId)
}
}
@ -740,7 +719,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
// All cardIds may already be activated if the backup was skipped before.
if (notActivatedCardIds.isEmpty()) {
delay(1000)
store.dispatchWithMain(BackupAction.BackupFinished(userWallet?.walletId))
store.dispatchWithMain(BackupAction.BackupFinished(userWallet.walletId))
return@launch
}
@ -748,8 +727,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
store.state.globalState.onboardingState.onboardingManager?.finishActivation(notActivatedCardIds)
handleFinishBackup(requireNotNull(scanResponse), userWallet)
delay(1000)
store.dispatchWithMain(BackupAction.BackupFinished(userWalletId = userWallet?.walletId))
store.dispatchWithMain(BackupAction.BackupFinished(userWalletId = userWallet.walletId))
}
}