Updated on 2026-08-14
This commit is contained in:
parent
342b6a2f50
commit
ec40334d8a
26 changed files with 527 additions and 50 deletions
|
|
@ -52,6 +52,7 @@ import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
|
||||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||||
import com.tangem.feature.qrscanning.QrScanningRouter
|
import com.tangem.feature.qrscanning.QrScanningRouter
|
||||||
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
|
||||||
|
import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
|
||||||
import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter
|
import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter
|
||||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||||
import com.tangem.features.send.api.navigation.SendRouter
|
import com.tangem.features.send.api.navigation.SendRouter
|
||||||
|
|
@ -59,6 +60,7 @@ import com.tangem.features.staking.api.navigation.StakingRouter
|
||||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||||
import com.tangem.features.wallet.navigation.WalletRouter
|
import com.tangem.features.wallet.navigation.WalletRouter
|
||||||
import com.tangem.operations.backup.BackupService
|
import com.tangem.operations.backup.BackupService
|
||||||
|
import com.tangem.sdk.api.BackupServiceHolder
|
||||||
import com.tangem.sdk.api.TangemSdkManager
|
import com.tangem.sdk.api.TangemSdkManager
|
||||||
import com.tangem.sdk.extensions.init
|
import com.tangem.sdk.extensions.init
|
||||||
import com.tangem.tap.common.ActivityResultCallbackHolder
|
import com.tangem.tap.common.ActivityResultCallbackHolder
|
||||||
|
|
@ -185,6 +187,12 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var shouldInitiallyAskPermissionUseCase: ShouldInitiallyAskPermissionUseCase
|
lateinit var shouldInitiallyAskPermissionUseCase: ShouldInitiallyAskPermissionUseCase
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var backupServiceHolder: BackupServiceHolder
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var onboardingV2FeatureToggles: OnboardingV2FeatureToggles
|
||||||
|
|
||||||
internal val viewModel: MainViewModel by viewModels()
|
internal val viewModel: MainViewModel by viewModels()
|
||||||
|
|
||||||
private lateinit var appThemeModeFlow: SharedFlow<AppThemeMode>
|
private lateinit var appThemeModeFlow: SharedFlow<AppThemeMode>
|
||||||
|
|
@ -294,7 +302,14 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
||||||
cardSdkOwner.register(activity = this)
|
cardSdkOwner.register(activity = this)
|
||||||
tangemSdkManager = injectedTangemSdkManager
|
tangemSdkManager = injectedTangemSdkManager
|
||||||
appStateHolder.tangemSdkManager = tangemSdkManager
|
appStateHolder.tangemSdkManager = tangemSdkManager
|
||||||
|
|
||||||
|
if (onboardingV2FeatureToggles.isOnboardingV2Enabled) {
|
||||||
|
backupServiceHolder.createAndSetService(cardSdkConfigRepository.sdk, this)
|
||||||
|
backupService = backupServiceHolder.backupService.get()!! // will be deleted eventually
|
||||||
|
} else {
|
||||||
backupService = BackupService.init(cardSdkConfigRepository.sdk, this)
|
backupService = BackupService.init(cardSdkConfigRepository.sdk, this)
|
||||||
|
}
|
||||||
|
|
||||||
lockUserWalletsTimer = LockUserWalletsTimer(
|
lockUserWalletsTimer = LockUserWalletsTimer(
|
||||||
owner = this,
|
owner = this,
|
||||||
settingsRepository = settingsRepository,
|
settingsRepository = settingsRepository,
|
||||||
|
|
@ -550,6 +565,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO add onboarding v2 handling
|
||||||
store.dispatch(BackupAction.CheckForUnfinishedBackup)
|
store.dispatch(BackupAction.CheckForUnfinishedBackup)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
17
app/src/main/java/com/tangem/tap/di/TangemSdkModule.kt
Normal file
17
app/src/main/java/com/tangem/tap/di/TangemSdkModule.kt
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.tangem.tap.di
|
||||||
|
|
||||||
|
import com.tangem.sdk.api.BackupServiceHolder
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
internal object TangemSdkModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideBackupServiceHolder(): BackupServiceHolder = BackupServiceHolder()
|
||||||
|
}
|
||||||
|
|
@ -67,7 +67,10 @@ object OnboardingHelper {
|
||||||
|
|
||||||
fun whereToNavigate(scanResponse: ScanResponse): AppRoute {
|
fun whereToNavigate(scanResponse: ScanResponse): AppRoute {
|
||||||
if (store.inject(DaggerGraphState::onboardingV2FeatureToggles).isOnboardingV2Enabled) {
|
if (store.inject(DaggerGraphState::onboardingV2FeatureToggles).isOnboardingV2Enabled) {
|
||||||
return AppRoute.Onboarding(scanResponse)
|
return AppRoute.Onboarding(
|
||||||
|
scanResponse = scanResponse,
|
||||||
|
startFromBackup = false,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return when (val type = scanResponse.productType) {
|
return when (val type = scanResponse.productType) {
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,10 @@ internal class ChildFactory @Inject constructor(
|
||||||
is AppRoute.Onboarding -> {
|
is AppRoute.Onboarding -> {
|
||||||
route.asComponentChild(
|
route.asComponentChild(
|
||||||
contextProvider = contextProvider(route, contextFactory),
|
contextProvider = contextProvider(route, contextFactory),
|
||||||
params = OnboardingEntryComponent.Params(route.scanResponse),
|
params = OnboardingEntryComponent.Params(
|
||||||
|
scanResponse = route.scanResponse,
|
||||||
|
startBackupFlow = route.startFromBackup,
|
||||||
|
),
|
||||||
componentFactory = onboardingEntryComponentFactory,
|
componentFactory = onboardingEntryComponentFactory,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -300,5 +300,8 @@ sealed class AppRoute(val path: String) : Route {
|
||||||
) : AppRoute(path = "/sell_crypto/${userWalletId.stringValue}")
|
) : AppRoute(path = "/sell_crypto/${userWalletId.stringValue}")
|
||||||
|
|
||||||
// Onboarding V2
|
// Onboarding V2
|
||||||
data class Onboarding(val scanResponse: ScanResponse) : AppRoute(path = "/onboarding_v2")
|
data class Onboarding(
|
||||||
|
val scanResponse: ScanResponse,
|
||||||
|
val startFromBackup: Boolean,
|
||||||
|
) : AppRoute(path = "/onboarding_v2${if (startFromBackup) "/backup" else ""}")
|
||||||
}
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ interface OnboardingEntryComponent : ComposableContentComponent {
|
||||||
|
|
||||||
data class Params(
|
data class Params(
|
||||||
val scanResponse: ScanResponse,
|
val scanResponse: ScanResponse,
|
||||||
|
val startBackupFlow: Boolean,
|
||||||
)
|
)
|
||||||
|
|
||||||
interface Factory : ComponentFactory<Params, OnboardingEntryComponent>
|
interface Factory : ComponentFactory<Params, OnboardingEntryComponent>
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ dependencies {
|
||||||
implementation(projects.domain.models)
|
implementation(projects.domain.models)
|
||||||
implementation(projects.domain.feedback)
|
implementation(projects.domain.feedback)
|
||||||
implementation(projects.domain.core)
|
implementation(projects.domain.core)
|
||||||
|
implementation(projects.domain.card)
|
||||||
|
|
||||||
/** Tangem libraries */
|
/** Tangem libraries */
|
||||||
implementation(projects.libs.tangemSdkApi)
|
implementation(projects.libs.tangemSdkApi)
|
||||||
|
|
@ -54,6 +55,7 @@ dependencies {
|
||||||
implementation(deps.kotlin.immutable.collections)
|
implementation(deps.kotlin.immutable.collections)
|
||||||
implementation(deps.kotlin.serialization)
|
implementation(deps.kotlin.serialization)
|
||||||
implementation(deps.timber)
|
implementation(deps.timber)
|
||||||
|
implementation(deps.firebase.crashlytics)
|
||||||
|
|
||||||
/** DI */
|
/** DI */
|
||||||
implementation(deps.hilt.android)
|
implementation(deps.hilt.android)
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,12 @@ internal class OnboardingEntryModel @Inject constructor(
|
||||||
return when (scanResponse.productType) {
|
return when (scanResponse.productType) {
|
||||||
ProductType.Note -> TODO()
|
ProductType.Note -> TODO()
|
||||||
ProductType.Twins -> TODO()
|
ProductType.Twins -> TODO()
|
||||||
ProductType.Wallet -> OnboardingRoute.Wallet12(
|
ProductType.Wallet -> OnboardingRoute.MultiWallet(
|
||||||
scanResponse = scanResponse,
|
scanResponse = scanResponse,
|
||||||
withSeedPhraseFlow = false,
|
withSeedPhraseFlow = false,
|
||||||
titleProvider = titleProvider,
|
titleProvider = titleProvider,
|
||||||
)
|
)
|
||||||
ProductType.Wallet2 -> OnboardingRoute.Wallet12(
|
ProductType.Wallet2 -> OnboardingRoute.MultiWallet(
|
||||||
scanResponse = scanResponse,
|
scanResponse = scanResponse,
|
||||||
withSeedPhraseFlow = true,
|
withSeedPhraseFlow = true,
|
||||||
titleProvider = titleProvider,
|
titleProvider = titleProvider,
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@ import com.tangem.features.onboarding.v2.multiwallet.api.OnboardingMultiWalletCo
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal class OnboardingChildFactory @Inject constructor(
|
internal class OnboardingChildFactory @Inject constructor(
|
||||||
private val wallet12ComponentFactory: OnboardingMultiWalletComponent.Factory,
|
private val multiWalletComponentFactory: OnboardingMultiWalletComponent.Factory,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun createChild(route: OnboardingRoute, childContext: AppComponentContext): Any {
|
fun createChild(route: OnboardingRoute, childContext: AppComponentContext): Any {
|
||||||
return when (route) {
|
return when (route) {
|
||||||
is OnboardingRoute.Wallet12 -> wallet12ComponentFactory.create(
|
is OnboardingRoute.MultiWallet -> multiWalletComponentFactory.create(
|
||||||
context = childContext,
|
context = childContext,
|
||||||
params = OnboardingMultiWalletComponent.Params(
|
params = OnboardingMultiWalletComponent.Params(
|
||||||
scanResponse = route.scanResponse,
|
scanResponse = route.scanResponse,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ sealed class OnboardingRoute : Route {
|
||||||
|
|
||||||
data object None : OnboardingRoute()
|
data object None : OnboardingRoute()
|
||||||
|
|
||||||
data class Wallet12(
|
data class MultiWallet(
|
||||||
val titleProvider: TitleProvider,
|
val titleProvider: TitleProvider,
|
||||||
val scanResponse: ScanResponse,
|
val scanResponse: ScanResponse,
|
||||||
val withSeedPhraseFlow: Boolean,
|
val withSeedPhraseFlow: Boolean,
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ internal inline fun OnboardingEntry(
|
||||||
animation = stackAnimation(slide()),
|
animation = stackAnimation(slide()),
|
||||||
) {
|
) {
|
||||||
when (it.configuration) {
|
when (it.configuration) {
|
||||||
is OnboardingRoute.Wallet12 -> {
|
is OnboardingRoute.MultiWallet -> {
|
||||||
(it.instance as OnboardingMultiWalletComponent).Content(
|
(it.instance as OnboardingMultiWalletComponent).Content(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,11 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor
|
||||||
) : OnboardingMultiWalletComponent, AppComponentContext by context {
|
) : OnboardingMultiWalletComponent, AppComponentContext by context {
|
||||||
|
|
||||||
private val model: OnboardingMultiWalletModel = getOrCreateModel(params)
|
private val model: OnboardingMultiWalletModel = getOrCreateModel(params)
|
||||||
|
|
||||||
private val stackNavigation = StackNavigation<OnboardingMultiWalletState.Step>()
|
private val stackNavigation = StackNavigation<OnboardingMultiWalletState.Step>()
|
||||||
|
|
||||||
override val innerNavigation: InnerNavigation = object : InnerNavigation {
|
override val innerNavigation: InnerNavigation = object : InnerNavigation {
|
||||||
override val state = MutableStateFlow(
|
override val state = MutableStateFlow(
|
||||||
Wallet12InnerNavigationState(1, 5),
|
MultiWalletInnerNavigationState(1, 5),
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun pop(onComplete: (Boolean) -> Unit) {
|
override fun pop(onComplete: (Boolean) -> Unit) {
|
||||||
|
|
@ -83,8 +82,10 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor
|
||||||
|
|
||||||
private fun onStepDone() {
|
private fun onStepDone() {
|
||||||
when (model.state.value.currentStep) {
|
when (model.state.value.currentStep) {
|
||||||
OnboardingMultiWalletState.Step.CreateWallet ->
|
OnboardingMultiWalletState.Step.CreateWallet -> {
|
||||||
stackNavigation.push(OnboardingMultiWalletState.Step.AddBackupDevice)
|
stackNavigation.push(OnboardingMultiWalletState.Step.AddBackupDevice)
|
||||||
|
// innerNavigation.state.value TODO
|
||||||
|
}
|
||||||
OnboardingMultiWalletState.Step.AddBackupDevice -> TODO()
|
OnboardingMultiWalletState.Step.AddBackupDevice -> TODO()
|
||||||
OnboardingMultiWalletState.Step.FinishBackup -> TODO()
|
OnboardingMultiWalletState.Step.FinishBackup -> TODO()
|
||||||
OnboardingMultiWalletState.Step.Done -> TODO()
|
OnboardingMultiWalletState.Step.Done -> TODO()
|
||||||
|
|
@ -112,7 +113,7 @@ internal class DefaultOnboardingMultiWalletComponent @AssistedInject constructor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Wallet12InnerNavigationState(
|
data class MultiWalletInnerNavigationState(
|
||||||
override val stackSize: Int,
|
override val stackSize: Int,
|
||||||
override val stackMaxSize: Int?,
|
override val stackMaxSize: Int?,
|
||||||
) : InnerNavigationState
|
) : InnerNavigationState
|
||||||
|
|
@ -12,6 +12,7 @@ import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChild
|
||||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildComponent
|
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildComponent
|
||||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.model.MultiWalletBackupModel
|
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.model.MultiWalletBackupModel
|
||||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.MultiWalletBackup
|
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.MultiWalletBackup
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Suppress("UnusedPrivateMember")
|
@Suppress("UnusedPrivateMember")
|
||||||
class MultiWalletBackupComponent(
|
class MultiWalletBackupComponent(
|
||||||
|
|
@ -26,6 +27,10 @@ class MultiWalletBackupComponent(
|
||||||
params.parentParams.titleProvider.changeTitle(
|
params.parentParams.titleProvider.changeTitle(
|
||||||
text = resourceReference(R.string.onboarding_navbar_title_creating_backup),
|
text = resourceReference(R.string.onboarding_navbar_title_creating_backup),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
componentScope.launch {
|
||||||
|
model.onDoneFlow.collect { onDone() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.model
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import com.tangem.common.card.Card
|
||||||
|
|
||||||
|
// TODO maybe delete some fields in the future
|
||||||
|
data class BackupState(
|
||||||
|
val primaryCardId: String? = null,
|
||||||
|
val primaryCardBatchId: String? = null,
|
||||||
|
val backupCardsNumber: Int = 0,
|
||||||
|
val backupCards: List<Card> = emptyList(),
|
||||||
|
val backupCardIds: List<CardId> = emptyList(),
|
||||||
|
val backupCardBatchIds: List<CardId> = emptyList(),
|
||||||
|
@Transient
|
||||||
|
val backupCardsArtworks: Map<CardId, Bitmap> = emptyMap(),
|
||||||
|
val accessCode: String = "",
|
||||||
|
val accessCodeError: AccessCodeError? = null,
|
||||||
|
val backupStep: BackupStep? = null,
|
||||||
|
val maxBackupCards: Int = 2,
|
||||||
|
val canSkipBackup: Boolean = true,
|
||||||
|
val isInterruptedBackup: Boolean = false,
|
||||||
|
val showBtnLoading: Boolean = false,
|
||||||
|
val hasBackupError: Boolean = false,
|
||||||
|
val startedSource: BackupStartedSource = BackupStartedSource.Onboarding,
|
||||||
|
val hasRing: Boolean = false,
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class BackupStartedSource {
|
||||||
|
Onboarding, CreateBackup
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class AccessCodeError {
|
||||||
|
CodeTooShort, CodesDoNotMatch
|
||||||
|
}
|
||||||
|
|
||||||
|
typealias CardId = String
|
||||||
|
|
||||||
|
sealed class BackupStep {
|
||||||
|
data object InitBackup : BackupStep()
|
||||||
|
data object ScanOriginCard : BackupStep()
|
||||||
|
data object AddBackupCards : BackupStep()
|
||||||
|
data object SetAccessCode : BackupStep()
|
||||||
|
data object EnterAccessCode : BackupStep()
|
||||||
|
data object ReenterAccessCode : BackupStep()
|
||||||
|
data object WritePrimaryCard : BackupStep()
|
||||||
|
data class WriteBackupCard(val cardNumber: Int) : BackupStep()
|
||||||
|
data object Finished : BackupStep()
|
||||||
|
}
|
||||||
|
|
@ -1,31 +1,201 @@
|
||||||
package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.model
|
package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.model
|
||||||
|
|
||||||
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
|
import com.tangem.common.CompletionResult
|
||||||
|
import com.tangem.common.core.TangemSdkError
|
||||||
import com.tangem.core.decompose.di.ComponentScoped
|
import com.tangem.core.decompose.di.ComponentScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
|
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||||
|
import com.tangem.domain.models.scan.ProductType
|
||||||
|
import com.tangem.features.onboarding.v2.impl.R
|
||||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
|
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
|
||||||
|
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.backupCardAttestationFailedDialog
|
||||||
|
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.resetBackupCardDialog
|
||||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.state.MultiWalletBackupUM
|
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.state.MultiWalletBackupUM
|
||||||
|
import com.tangem.operations.backup.BackupService
|
||||||
|
import com.tangem.sdk.api.BackupServiceHolder
|
||||||
|
import com.tangem.sdk.api.TangemSdkManager
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ComponentScoped
|
@ComponentScoped
|
||||||
class MultiWalletBackupModel @Inject constructor(
|
class MultiWalletBackupModel @Inject constructor(
|
||||||
paramsContainer: ParamsContainer,
|
paramsContainer: ParamsContainer,
|
||||||
override val dispatchers: CoroutineDispatcherProvider,
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
|
private val backupServiceHolder: BackupServiceHolder,
|
||||||
|
private val cardSdkConfigRepository: CardSdkConfigRepository,
|
||||||
|
private val tangemSdkManager: TangemSdkManager,
|
||||||
) : Model() {
|
) : Model() {
|
||||||
|
|
||||||
@Suppress("UnusedPrivateMember")
|
@Suppress("UnusedPrivateMember")
|
||||||
private val params = paramsContainer.require<MultiWalletChildParams>()
|
private val params = paramsContainer.require<MultiWalletChildParams>()
|
||||||
|
private val scanResponse
|
||||||
|
get() = params.multiWalletState.value.currentScanResponse
|
||||||
|
private val backupService
|
||||||
|
get() = backupServiceHolder.backupService.get()!!
|
||||||
|
|
||||||
|
private val state = MutableStateFlow(BackupState())
|
||||||
|
|
||||||
private val _uiState = MutableStateFlow(
|
private val _uiState = MutableStateFlow(
|
||||||
MultiWalletBackupUM(
|
when (scanResponse.productType) {
|
||||||
finalizeButtonEnabled = false,
|
ProductType.Wallet -> getWallet1State()
|
||||||
|
ProductType.Wallet2,
|
||||||
|
ProductType.Ring,
|
||||||
|
-> MultiWalletBackupUM.Wallet2(
|
||||||
|
isRing = scanResponse.productType == ProductType.Ring,
|
||||||
|
backupAdded = false, // backupService.hasIncompletedBackup,
|
||||||
onAddBackupClick = {},
|
onAddBackupClick = {},
|
||||||
onFinalizeButtonClick = {},
|
onFinalizeButtonClick = {},
|
||||||
),
|
)
|
||||||
|
else -> error("Type: ${scanResponse.productType.name} is not supported!")
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
val uiState: StateFlow<MultiWalletBackupUM> = _uiState
|
val uiState: StateFlow<MultiWalletBackupUM> = _uiState
|
||||||
|
val onDoneFlow = MutableSharedFlow<Unit>()
|
||||||
|
|
||||||
|
private fun getWallet1State(): MultiWalletBackupUM.Wallet1 {
|
||||||
|
return when (backupService.currentState) {
|
||||||
|
BackupService.State.Preparing -> {
|
||||||
|
MultiWalletBackupUM.Wallet1(
|
||||||
|
title = resourceReference(R.string.onboarding_title_no_backup_cards),
|
||||||
|
bodyText = resourceReference(R.string.onboarding_subtitle_no_backup_cards),
|
||||||
|
showFinalizeButton = false,
|
||||||
|
addBackupButtonEnabled = true,
|
||||||
|
addBackupButtonLoading = false,
|
||||||
|
artworkNumberOfBackupCards = 0,
|
||||||
|
onAddBackupClick = ::startBackupWallet1,
|
||||||
|
onFinalizeButtonClick = {},
|
||||||
|
onSkipButtonClick = { onDoneFlow.tryEmit(Unit) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is BackupService.State.FinalizingBackupCard -> TODO()
|
||||||
|
BackupService.State.FinalizingPrimaryCard -> TODO()
|
||||||
|
BackupService.State.Finished -> TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startBackupWallet1() {
|
||||||
|
backupService.discardSavedBackup()
|
||||||
|
val primaryCard = scanResponse.primaryCard
|
||||||
|
|
||||||
|
if (primaryCard != null) {
|
||||||
|
backupService.setPrimaryCard(primaryCard)
|
||||||
|
addBackupCardWithService()
|
||||||
|
} else {
|
||||||
|
// TODO wallet 2 ??? or from main?
|
||||||
|
// BackupAction.StartAddingPrimaryCard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setNumberOfBackupCardsWallet1(number: Int) {
|
||||||
|
// set state for Wallet1 for adding backup cards and disable button if there is more than 2 backup cards
|
||||||
|
_uiState.update { st ->
|
||||||
|
if (st !is MultiWalletBackupUM.Wallet1) return@update st
|
||||||
|
|
||||||
|
when (number) {
|
||||||
|
0 -> {
|
||||||
|
st.copy(
|
||||||
|
title = resourceReference(R.string.onboarding_title_no_backup_cards),
|
||||||
|
bodyText = resourceReference(R.string.onboarding_subtitle_no_backup_cards),
|
||||||
|
artworkNumberOfBackupCards = 0,
|
||||||
|
addBackupButtonEnabled = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
st.copy(
|
||||||
|
title = resourceReference(R.string.onboarding_title_one_backup_card),
|
||||||
|
bodyText = resourceReference(R.string.onboarding_subtitle_one_backup_card),
|
||||||
|
artworkNumberOfBackupCards = 1,
|
||||||
|
addBackupButtonEnabled = true,
|
||||||
|
showFinalizeButton = true,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
st.copy(
|
||||||
|
title = resourceReference(R.string.onboarding_title_two_backup_cards),
|
||||||
|
bodyText = resourceReference(R.string.onboarding_subtitle_two_backup_cards),
|
||||||
|
artworkNumberOfBackupCards = 2,
|
||||||
|
addBackupButtonEnabled = false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> st.copy(addBackupButtonEnabled = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addBackupCardWithService() {
|
||||||
|
updateWallet1State { st ->
|
||||||
|
st.copy(addBackupButtonLoading = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
backupService.addBackupCard { result ->
|
||||||
|
backupService.skipCompatibilityChecks = false
|
||||||
|
cardSdkConfigRepository.sdk.config.filter.cardIdFilter = null
|
||||||
|
|
||||||
|
updateWallet1State { st ->
|
||||||
|
st.copy(addBackupButtonLoading = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
when (result) {
|
||||||
|
is CompletionResult.Success -> {
|
||||||
|
// TODO change artwork
|
||||||
|
state.update {
|
||||||
|
it.copy(
|
||||||
|
backupCards = it.backupCards + result.data,
|
||||||
|
backupCardsNumber = it.backupCardsNumber + 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
setNumberOfBackupCardsWallet1(state.value.backupCardsNumber)
|
||||||
|
}
|
||||||
|
is CompletionResult.Failure -> {
|
||||||
|
when (val error = result.error) {
|
||||||
|
is TangemSdkError.BackupFailedNotEmptyWallets -> {
|
||||||
|
updateWallet1State { st ->
|
||||||
|
st.copy(
|
||||||
|
dialog = resetBackupCardDialog(
|
||||||
|
onReset = { resetBackupCard(cardId = error.cardId) },
|
||||||
|
onDismiss = { updateWallet1State { it.copy(dialog = null) } },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is TangemSdkError.IssuerSignatureLoadingFailed -> {
|
||||||
|
updateWallet1State { st ->
|
||||||
|
st.copy(
|
||||||
|
dialog = backupCardAttestationFailedDialog(
|
||||||
|
onDismiss = { updateWallet1State { it.copy(dialog = null) } },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> FirebaseCrashlytics.getInstance().recordException(result.error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resetBackupCard(cardId: String) {
|
||||||
|
modelScope.launch {
|
||||||
|
tangemSdkManager.resetToFactorySettings(
|
||||||
|
cardId = cardId,
|
||||||
|
allowsRequestAccessCodeFromRepository = false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateWallet1State(block: (MultiWalletBackupUM.Wallet1) -> MultiWalletBackupUM.Wallet1) {
|
||||||
|
_uiState.update { state ->
|
||||||
|
if (state !is MultiWalletBackupUM.Wallet1) return@update state
|
||||||
|
block(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui
|
||||||
|
|
||||||
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
|
import com.tangem.features.onboarding.v2.impl.R
|
||||||
|
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.state.MultiWalletBackupUMDialog
|
||||||
|
|
||||||
|
internal fun resetBackupCardDialog(onReset: () -> Unit, onDismiss: () -> Unit) = MultiWalletBackupUMDialog(
|
||||||
|
title = resourceReference(R.string.common_attention),
|
||||||
|
bodyText = resourceReference(R.string.onboarding_linking_error_card_with_wallets),
|
||||||
|
confirmText = resourceReference(R.string.common_cancel),
|
||||||
|
cancelText = resourceReference(R.string.card_settings_action_sheet_reset),
|
||||||
|
warningCancelColor = true,
|
||||||
|
onDismiss = onDismiss,
|
||||||
|
onConfirm = onDismiss,
|
||||||
|
onCancel = { onReset(); onDismiss() },
|
||||||
|
)
|
||||||
|
|
||||||
|
internal fun backupCardAttestationFailedDialog(onDismiss: () -> Unit) = MultiWalletBackupUMDialog(
|
||||||
|
title = resourceReference(R.string.common_error),
|
||||||
|
bodyText = resourceReference(R.string.issuer_signature_loading_failed),
|
||||||
|
confirmText = resourceReference(R.string.common_ok),
|
||||||
|
cancelText = null,
|
||||||
|
warningCancelColor = true,
|
||||||
|
onDismiss = onDismiss,
|
||||||
|
onConfirm = onDismiss,
|
||||||
|
onCancel = null,
|
||||||
|
)
|
||||||
|
|
@ -4,15 +4,19 @@ import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.tangem.core.ui.components.PrimaryButtonIconEnd
|
import com.tangem.core.ui.components.*
|
||||||
import com.tangem.core.ui.components.SecondaryButton
|
import com.tangem.core.ui.extensions.resolveReference
|
||||||
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreview
|
import com.tangem.core.ui.res.TangemThemePreview
|
||||||
import com.tangem.features.onboarding.v2.impl.R
|
import com.tangem.features.onboarding.v2.impl.R
|
||||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.state.MultiWalletBackupUM
|
import com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.state.MultiWalletBackupUM
|
||||||
|
|
@ -38,11 +42,90 @@ fun MultiWalletBackup(state: MultiWalletBackupUM, modifier: Modifier = Modifier)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
when (state) {
|
||||||
|
is MultiWalletBackupUM.Wallet1 -> Wallet1Content(state)
|
||||||
|
is MultiWalletBackupUM.Wallet2 -> TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val dialog = state.dialog
|
||||||
|
if (dialog != null) {
|
||||||
|
BasicDialog(
|
||||||
|
title = dialog.title.resolveReference(),
|
||||||
|
message = dialog.bodyText.resolveReference(),
|
||||||
|
confirmButton = DialogButtonUM(
|
||||||
|
title = dialog.confirmText.resolveReference(),
|
||||||
|
onClick = dialog.onConfirm,
|
||||||
|
),
|
||||||
|
dismissButton = if (dialog.cancelText != null && dialog.onCancel != null) {
|
||||||
|
DialogButtonUM(
|
||||||
|
title = dialog.cancelText.resolveReference(),
|
||||||
|
warning = dialog.warningCancelColor,
|
||||||
|
onClick = dialog.onCancel,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
onDismissDialog = dialog.onDismiss,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ColumnScope.Wallet1Content(state: MultiWalletBackupUM.Wallet1) {
|
||||||
|
Column(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 32.dp, end = 32.dp, bottom = 74.dp)
|
||||||
|
.weight(1f),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
) {
|
||||||
|
// artwork
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = state.title.resolveReference(),
|
||||||
|
style = TangemTheme.typography.h2,
|
||||||
|
color = TangemTheme.colors.text.primary1,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.padding(top = 16.dp),
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = state.bodyText.resolveReference(),
|
||||||
|
style = TangemTheme.typography.body1,
|
||||||
|
color = TangemTheme.colors.text.secondary,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.padding(top = 12.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.showFinalizeButton) {
|
||||||
|
SecondaryButtonIconEnd(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
iconResId = R.drawable.ic_tangem_24,
|
||||||
|
enabled = state.addBackupButtonEnabled,
|
||||||
|
showProgress = state.addBackupButtonLoading,
|
||||||
|
text = stringResource(R.string.onboarding_button_add_backup_card),
|
||||||
|
onClick = state.onAddBackupClick,
|
||||||
|
)
|
||||||
|
|
||||||
|
PrimaryButton(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
text = stringResource(R.string.onboarding_button_finalize_backup),
|
||||||
|
onClick = state.onFinalizeButtonClick,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
PrimaryButtonIconEnd(
|
PrimaryButtonIconEnd(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp)
|
.padding(start = 16.dp, end = 16.dp, bottom = 12.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
iconResId = R.drawable.ic_tangem_24,
|
iconResId = R.drawable.ic_tangem_24,
|
||||||
|
enabled = state.addBackupButtonEnabled,
|
||||||
|
showProgress = state.addBackupButtonLoading,
|
||||||
text = stringResource(R.string.onboarding_button_add_backup_card),
|
text = stringResource(R.string.onboarding_button_add_backup_card),
|
||||||
onClick = state.onAddBackupClick,
|
onClick = state.onAddBackupClick,
|
||||||
)
|
)
|
||||||
|
|
@ -51,20 +134,33 @@ fun MultiWalletBackup(state: MultiWalletBackupUM, modifier: Modifier = Modifier)
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
|
.padding(start = 16.dp, end = 16.dp, bottom = 16.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
enabled = state.finalizeButtonEnabled,
|
text = stringResource(R.string.onboarding_button_skip_backup),
|
||||||
text = stringResource(R.string.onboarding_button_finalize_backup),
|
onClick = state.onSkipButtonClick,
|
||||||
onClick = state.onFinalizeButtonClick,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun Preview() {
|
private fun PreviewWallet1() {
|
||||||
TangemThemePreview {
|
TangemThemePreview {
|
||||||
MultiWalletBackup(
|
MultiWalletBackup(
|
||||||
state = MultiWalletBackupUM(
|
state = MultiWalletBackupUM.Wallet1(
|
||||||
finalizeButtonEnabled = true,
|
title = stringReference("Title"),
|
||||||
|
bodyText = stringReference("Body body body"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun PreviewWallet2() {
|
||||||
|
TangemThemePreview {
|
||||||
|
MultiWalletBackup(
|
||||||
|
state = MultiWalletBackupUM.Wallet2(
|
||||||
|
isRing = false,
|
||||||
|
backupAdded = true,
|
||||||
onAddBackupClick = {},
|
onAddBackupClick = {},
|
||||||
onFinalizeButtonClick = {},
|
onFinalizeButtonClick = {},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import com.tangem.core.ui.res.TangemThemePreview
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Wallet1Artwork(modifier: Modifier = Modifier) {
|
||||||
|
Box(modifier) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun Preview() {
|
||||||
|
TangemThemePreview {
|
||||||
|
Wallet1Artwork()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,45 @@
|
||||||
package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.state
|
package com.tangem.features.onboarding.v2.multiwallet.impl.child.backup.ui.state
|
||||||
|
|
||||||
data class MultiWalletBackupUM(
|
import androidx.annotation.IntRange
|
||||||
val finalizeButtonEnabled: Boolean,
|
import androidx.compose.runtime.Immutable
|
||||||
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
sealed class MultiWalletBackupUM {
|
||||||
|
|
||||||
|
abstract val dialog: MultiWalletBackupUMDialog?
|
||||||
|
|
||||||
|
data class Wallet1(
|
||||||
|
val title: TextReference = stringReference(""),
|
||||||
|
val bodyText: TextReference = stringReference(""),
|
||||||
|
val addBackupButtonEnabled: Boolean = true,
|
||||||
|
val addBackupButtonLoading: Boolean = false,
|
||||||
|
val showFinalizeButton: Boolean = false,
|
||||||
|
val oneBackupAdded: Boolean = false,
|
||||||
|
@IntRange(0, 2) val artworkNumberOfBackupCards: Int = 0, // highlights cards on 0, 1, 2
|
||||||
|
val onAddBackupClick: () -> Unit = {},
|
||||||
|
val onFinalizeButtonClick: () -> Unit = {},
|
||||||
|
val onSkipButtonClick: () -> Unit = {},
|
||||||
|
override val dialog: MultiWalletBackupUMDialog? = null,
|
||||||
|
) : MultiWalletBackupUM()
|
||||||
|
|
||||||
|
data class Wallet2(
|
||||||
|
val isRing: Boolean,
|
||||||
|
val backupAdded: Boolean,
|
||||||
val onAddBackupClick: () -> Unit,
|
val onAddBackupClick: () -> Unit,
|
||||||
val onFinalizeButtonClick: () -> Unit,
|
val onFinalizeButtonClick: () -> Unit,
|
||||||
|
override val dialog: MultiWalletBackupUMDialog? = null,
|
||||||
|
) : MultiWalletBackupUM()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class MultiWalletBackupUMDialog(
|
||||||
|
val title: TextReference,
|
||||||
|
val bodyText: TextReference,
|
||||||
|
val confirmText: TextReference,
|
||||||
|
val cancelText: TextReference?,
|
||||||
|
val warningCancelColor: Boolean = false,
|
||||||
|
val onConfirm: () -> Unit,
|
||||||
|
val onCancel: (() -> Unit)?,
|
||||||
|
val onDismiss: () -> Unit,
|
||||||
)
|
)
|
||||||
|
|
@ -4,13 +4,20 @@ import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.features.onboarding.v2.impl.R
|
import com.tangem.features.onboarding.v2.impl.R
|
||||||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui.state.MultiWalletCreateWalletUM
|
import com.tangem.features.onboarding.v2.multiwallet.impl.child.createwallet.ui.state.MultiWalletCreateWalletUM
|
||||||
|
|
||||||
internal fun resetCardDialog(onConfirm: () -> Unit, onDismiss: () -> Unit, onDismissButtonClick: () -> Unit) =
|
internal fun resetCardDialog(onConfirm: () -> Unit, dismiss: () -> Unit, onDismissButtonClick: () -> Unit) =
|
||||||
MultiWalletCreateWalletUM.Dialog(
|
MultiWalletCreateWalletUM.Dialog(
|
||||||
title = resourceReference(R.string.onboarding_activation_error_title),
|
title = resourceReference(R.string.onboarding_activation_error_title),
|
||||||
description = resourceReference(R.string.onboarding_activation_error_message),
|
description = resourceReference(R.string.onboarding_activation_error_message),
|
||||||
confirmButtonText = resourceReference(R.string.common_ok),
|
confirmButtonText = resourceReference(R.string.common_support),
|
||||||
dismissButtonText = resourceReference(R.string.common_support),
|
dismissButtonText = resourceReference(R.string.common_ok),
|
||||||
onDismiss = onDismiss,
|
dismissWarningColor = true,
|
||||||
onConfirm = onConfirm,
|
onDismiss = dismiss,
|
||||||
onDismissButtonClick = onDismissButtonClick,
|
onConfirm = {
|
||||||
|
onConfirm()
|
||||||
|
dismiss()
|
||||||
|
},
|
||||||
|
onDismissButtonClick = {
|
||||||
|
onDismissButtonClick()
|
||||||
|
dismiss()
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -5,6 +5,7 @@ import com.tangem.common.core.TangemSdkError
|
||||||
import com.tangem.core.decompose.di.ComponentScoped
|
import com.tangem.core.decompose.di.ComponentScoped
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.core.decompose.model.ParamsContainer
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
|
import com.tangem.domain.card.repository.CardRepository
|
||||||
import com.tangem.domain.feedback.GetCardInfoUseCase
|
import com.tangem.domain.feedback.GetCardInfoUseCase
|
||||||
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
||||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||||
|
|
@ -26,6 +27,7 @@ class MultiWalletCreateWalletModel @Inject constructor(
|
||||||
private val tangemSdkManager: TangemSdkManager,
|
private val tangemSdkManager: TangemSdkManager,
|
||||||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||||
private val getCardInfoUseCase: GetCardInfoUseCase,
|
private val getCardInfoUseCase: GetCardInfoUseCase,
|
||||||
|
private val cardRepository: CardRepository,
|
||||||
) : Model() {
|
) : Model() {
|
||||||
|
|
||||||
private val params = paramsContainer.require<MultiWalletChildParams>()
|
private val params = paramsContainer.require<MultiWalletChildParams>()
|
||||||
|
|
@ -63,6 +65,7 @@ class MultiWalletCreateWalletModel @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cardRepository.startCardActivation(cardId = result.data.card.cardId)
|
||||||
onDone.emit(Unit)
|
onDone.emit(Unit)
|
||||||
// TODO
|
// TODO
|
||||||
// Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
|
// Analytics.send(Onboarding.CreateWallet.WalletCreatedSuccessfully())
|
||||||
|
|
@ -82,14 +85,9 @@ class MultiWalletCreateWalletModel @Inject constructor(
|
||||||
_uiState.update { state ->
|
_uiState.update { state ->
|
||||||
state.copy(
|
state.copy(
|
||||||
dialog = resetCardDialog(
|
dialog = resetCardDialog(
|
||||||
onConfirm = {
|
onConfirm = ::navigateToSupportScreen,
|
||||||
_uiState.update { it.copy(dialog = null) }
|
dismiss = { _uiState.update { it.copy(dialog = null) } },
|
||||||
resetCard()
|
onDismissButtonClick = ::resetCard,
|
||||||
},
|
|
||||||
onDismiss = {
|
|
||||||
_uiState.update { it.copy(dialog = null) }
|
|
||||||
},
|
|
||||||
onDismissButtonClick = ::navigateToSupportScreen,
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ fun MultiWalletCreateWallet(state: MultiWalletCreateWalletUM, modifier: Modifier
|
||||||
),
|
),
|
||||||
dismissButton = DialogButtonUM(
|
dismissButton = DialogButtonUM(
|
||||||
title = state.dialog.dismissButtonText.resolveReference(),
|
title = state.dialog.dismissButtonText.resolveReference(),
|
||||||
|
warning = state.dialog.dismissWarningColor,
|
||||||
onClick = state.dialog.onDismissButtonClick,
|
onClick = state.dialog.onDismissButtonClick,
|
||||||
),
|
),
|
||||||
onDismissDialog = state.dialog.onDismiss,
|
onDismissDialog = state.dialog.onDismiss,
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ data class MultiWalletCreateWalletUM(
|
||||||
val description: TextReference,
|
val description: TextReference,
|
||||||
val dismissButtonText: TextReference,
|
val dismissButtonText: TextReference,
|
||||||
val confirmButtonText: TextReference,
|
val confirmButtonText: TextReference,
|
||||||
|
val dismissWarningColor: Boolean = false,
|
||||||
val onConfirm: () -> Unit,
|
val onConfirm: () -> Unit,
|
||||||
val onDismissButtonClick: () -> Unit,
|
val onDismissButtonClick: () -> Unit,
|
||||||
val onDismiss: () -> Unit,
|
val onDismiss: () -> Unit,
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,10 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
||||||
)
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
// TODO add analytics
|
||||||
|
// if (!manager.isActivationStarted(notNullCard.cardId)) {
|
||||||
|
// Analytics.send(Onboarding.Started())
|
||||||
|
// }
|
||||||
initScreenTitleSub()
|
initScreenTitleSub()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,11 +53,10 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
||||||
params.titleProvider.changeTitle(title)
|
params.titleProvider.changeTitle(title)
|
||||||
|
|
||||||
modelScope.launch {
|
modelScope.launch {
|
||||||
state
|
state.map { it.currentStep }
|
||||||
.map { it.currentStep }
|
|
||||||
.collectLatest { step ->
|
.collectLatest { step ->
|
||||||
val title = screenTitleByStep(step)
|
val stepTitle = screenTitleByStep(step)
|
||||||
params.titleProvider.changeTitle(title)
|
params.titleProvider.changeTitle(stepTitle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ data class OnboardingMultiWalletState(
|
||||||
val currentStep: Step,
|
val currentStep: Step,
|
||||||
val currentScanResponse: ScanResponse,
|
val currentScanResponse: ScanResponse,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
enum class Step {
|
enum class Step {
|
||||||
CreateWallet, AddBackupDevice, FinishBackup, Done
|
CreateWallet, AddBackupDevice, FinishBackup, Done
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.tangem.sdk.api
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import com.tangem.TangemSdk
|
||||||
|
import com.tangem.operations.backup.BackupService
|
||||||
|
import com.tangem.sdk.extensions.init
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
|
class BackupServiceHolder {
|
||||||
|
|
||||||
|
lateinit var backupService: WeakReference<BackupService>
|
||||||
|
private set
|
||||||
|
|
||||||
|
fun createAndSetService(tangemSdk: TangemSdk, activity: ComponentActivity) {
|
||||||
|
backupService = WeakReference(BackupService.init(tangemSdk, activity))
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue