Updated on 2026-08-14
This commit is contained in:
parent
f009a78876
commit
e07246d25d
33 changed files with 736 additions and 87 deletions
|
|
@ -63,6 +63,7 @@ internal class ChildFactory @Inject constructor(
|
|||
private val detailsComponentFactory: DetailsComponent.Factory,
|
||||
private val walletSettingsComponentFactory: WalletSettingsComponent.Factory,
|
||||
private val walletBackupComponentFactory: WalletBackupComponent.Factory,
|
||||
private val walletHardwareBackupComponentFactory: WalletHardwareBackupComponent.Factory,
|
||||
private val disclaimerComponentFactory: DisclaimerComponent.Factory,
|
||||
private val manageTokensComponentFactory: ManageTokensComponent.Factory,
|
||||
private val marketsTokenDetailsComponentFactory: MarketsTokenDetailsComponent.Factory,
|
||||
|
|
@ -189,6 +190,15 @@ internal class ChildFactory @Inject constructor(
|
|||
componentFactory = walletBackupComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.WalletHardwareBackup -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = WalletHardwareBackupComponent.Params(
|
||||
userWalletId = route.userWalletId,
|
||||
),
|
||||
componentFactory = walletHardwareBackupComponentFactory,
|
||||
)
|
||||
}
|
||||
is AppRoute.MarketsTokenDetails -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
|
|
@ -542,6 +552,7 @@ internal class ChildFactory @Inject constructor(
|
|||
context = context,
|
||||
params = CreateWalletBackupComponent.Params(
|
||||
userWalletId = route.userWalletId,
|
||||
isUpgradeFlow = route.isUpgradeFlow,
|
||||
),
|
||||
componentFactory = createWalletBackupComponentFactory,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -220,6 +220,11 @@ sealed class AppRoute(val path: String) : Route {
|
|||
val userWalletId: UserWalletId,
|
||||
) : AppRoute(path = "/wallet_backup/${userWalletId.stringValue}")
|
||||
|
||||
@Serializable
|
||||
data class WalletHardwareBackup(
|
||||
val userWalletId: UserWalletId,
|
||||
) : AppRoute(path = "/wallet_hardware_backup/${userWalletId.stringValue}")
|
||||
|
||||
@Serializable
|
||||
data object Markets : AppRoute(path = "/markets")
|
||||
|
||||
|
|
@ -347,6 +352,7 @@ sealed class AppRoute(val path: String) : Route {
|
|||
@Serializable
|
||||
data class CreateWalletBackup(
|
||||
val userWalletId: UserWalletId,
|
||||
val isUpgradeFlow: Boolean,
|
||||
) : AppRoute(path = "/create_wallet_backup/${userWalletId.stringValue}")
|
||||
|
||||
@Serializable
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
|
|
@ -8,6 +8,7 @@ interface CreateWalletBackupComponent : ComposableContentComponent {
|
|||
|
||||
data class Params(
|
||||
val userWalletId: UserWalletId,
|
||||
val isUpgradeFlow: Boolean,
|
||||
)
|
||||
|
||||
interface Factory : ComponentFactory<Params, CreateWalletBackupComponent>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package com.tangem.features.hotwallet
|
||||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
interface WalletHardwareBackupComponent : ComposableContentComponent {
|
||||
|
||||
data class Params(
|
||||
val userWalletId: UserWalletId,
|
||||
)
|
||||
|
||||
interface Factory : ComponentFactory<Params, WalletHardwareBackupComponent>
|
||||
}
|
||||
|
|
@ -120,6 +120,8 @@ internal class AddExistingWalletModel @Inject constructor(
|
|||
override fun onContinueClick(userWalletId: UserWalletId) {
|
||||
stackNavigation.replaceAll(AddExistingWalletRoute.SetAccessCode(userWalletId))
|
||||
}
|
||||
|
||||
override fun onUpgradeClick(userWalletId: UserWalletId) = Unit
|
||||
}
|
||||
|
||||
inner class AccessCodeModelCallbacks : AccessCodeComponent.ModelCallbacks {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ internal class AddExistingWalletChildFactory @Inject constructor(
|
|||
params = ManualBackupCompletedComponent.Params(
|
||||
userWalletId = route.userWalletId,
|
||||
callbacks = model.manualBackupCompletedComponentModelCallbacks,
|
||||
isUpgradeFlow = false,
|
||||
),
|
||||
)
|
||||
is AddExistingWalletRoute.SetAccessCode -> accessCodeComponentFactory.create(
|
||||
|
|
|
|||
|
|
@ -3,11 +3,13 @@ package com.tangem.features.hotwallet.createwalletbackup
|
|||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.pop
|
||||
import com.arkivanov.decompose.router.stack.push
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.analytics.utils.AnalyticsContextProxy
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.navigation.popTo
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.features.hotwallet.CreateWalletBackupComponent
|
||||
import com.tangem.features.hotwallet.createwalletbackup.routing.CreateWalletBackupRoute
|
||||
|
|
@ -65,7 +67,7 @@ internal class CreateWalletBackupModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun onManualBackupChecked() {
|
||||
stackNavigation.push(CreateWalletBackupRoute.BackupCompleted)
|
||||
stackNavigation.push(CreateWalletBackupRoute.BackupCompleted(isUpgradeFlow = params.isUpgradeFlow))
|
||||
}
|
||||
|
||||
fun onManualBackupCompleted() {
|
||||
|
|
@ -94,5 +96,14 @@ internal class CreateWalletBackupModel @Inject constructor(
|
|||
override fun onContinueClick(userWalletId: UserWalletId) {
|
||||
onManualBackupCompleted()
|
||||
}
|
||||
|
||||
override fun onUpgradeClick(userWalletId: UserWalletId) {
|
||||
router.popTo<AppRoute.WalletSettings>()
|
||||
router.push(
|
||||
AppRoute.UpgradeWallet(
|
||||
userWalletId = userWalletId,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,31 +16,32 @@ internal class CreateWalletBackupChildFactory @Inject constructor() {
|
|||
childContext: AppComponentContext,
|
||||
model: CreateWalletBackupModel,
|
||||
): ComposableContentComponent = when (route) {
|
||||
CreateWalletBackupRoute.RecoveryPhraseStart -> ManualBackupStartComponent(
|
||||
is CreateWalletBackupRoute.RecoveryPhraseStart -> ManualBackupStartComponent(
|
||||
context = childContext,
|
||||
params = ManualBackupStartComponent.Params(
|
||||
callbacks = model.manualBackupStartModelCallbacks,
|
||||
),
|
||||
)
|
||||
CreateWalletBackupRoute.RecoveryPhrase -> ManualBackupPhraseComponent(
|
||||
is CreateWalletBackupRoute.RecoveryPhrase -> ManualBackupPhraseComponent(
|
||||
context = childContext,
|
||||
params = ManualBackupPhraseComponent.Params(
|
||||
userWalletId = model.params.userWalletId,
|
||||
callbacks = model.manualBackupPhraseModelCallbacks,
|
||||
),
|
||||
)
|
||||
CreateWalletBackupRoute.ConfirmBackup -> ManualBackupCheckComponent(
|
||||
is CreateWalletBackupRoute.ConfirmBackup -> ManualBackupCheckComponent(
|
||||
context = childContext,
|
||||
params = ManualBackupCheckComponent.Params(
|
||||
userWalletId = model.params.userWalletId,
|
||||
callbacks = model.manualBackupCheckModelCallbacks,
|
||||
),
|
||||
)
|
||||
CreateWalletBackupRoute.BackupCompleted -> ManualBackupCompletedComponent(
|
||||
is CreateWalletBackupRoute.BackupCompleted -> ManualBackupCompletedComponent(
|
||||
context = childContext,
|
||||
params = ManualBackupCompletedComponent.Params(
|
||||
userWalletId = model.params.userWalletId,
|
||||
callbacks = model.manualBackupCompletedModelCallbacks,
|
||||
isUpgradeFlow = route.isUpgradeFlow,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,7 @@ internal sealed interface CreateWalletBackupRoute {
|
|||
data object ConfirmBackup : CreateWalletBackupRoute
|
||||
|
||||
@Serializable
|
||||
data object BackupCompleted : CreateWalletBackupRoute
|
||||
data class BackupCompleted(
|
||||
val isUpgradeFlow: Boolean,
|
||||
) : CreateWalletBackupRoute
|
||||
}
|
||||
|
|
@ -29,10 +29,12 @@ internal class ManualBackupCompletedComponent @AssistedInject constructor(
|
|||
|
||||
interface ModelCallbacks {
|
||||
fun onContinueClick(userWalletId: UserWalletId)
|
||||
fun onUpgradeClick(userWalletId: UserWalletId)
|
||||
}
|
||||
|
||||
data class Params(
|
||||
val userWalletId: UserWalletId,
|
||||
val callbacks: ModelCallbacks,
|
||||
val isUpgradeFlow: Boolean,
|
||||
)
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class ManualBackupCompletedModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
|
|
@ -20,7 +21,14 @@ internal class ManualBackupCompletedModel @Inject constructor(
|
|||
internal val uiState: StateFlow<ManualBackupCompletedUM>
|
||||
field = MutableStateFlow(
|
||||
ManualBackupCompletedUM(
|
||||
onContinueClick = { params.callbacks.onContinueClick(params.userWalletId) },
|
||||
onContinueClick = {
|
||||
if (params.isUpgradeFlow) {
|
||||
params.callbacks.onUpgradeClick(params.userWalletId)
|
||||
} else {
|
||||
params.callbacks.onContinueClick(params.userWalletId)
|
||||
}
|
||||
},
|
||||
isLoading = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -2,4 +2,5 @@ package com.tangem.features.hotwallet.manualbackup.completed.entity
|
|||
|
||||
internal data class ManualBackupCompletedUM(
|
||||
val onContinueClick: () -> Unit,
|
||||
val isLoading: Boolean,
|
||||
)
|
||||
|
|
@ -65,8 +65,6 @@ internal fun ManualBackupCompletedContent(state: ManualBackupCompletedUM, modifi
|
|||
PrimaryButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.common_continue),
|
||||
showProgress = false,
|
||||
enabled = true,
|
||||
onClick = state.onContinueClick,
|
||||
)
|
||||
}
|
||||
|
|
@ -75,11 +73,26 @@ internal fun ManualBackupCompletedContent(state: ManualBackupCompletedUM, modifi
|
|||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewManualBackupCompletedContent() {
|
||||
private fun PreviewManualBackupCompletedContentRegular() {
|
||||
TangemThemePreview {
|
||||
ManualBackupCompletedContent(
|
||||
state = ManualBackupCompletedUM(
|
||||
onContinueClick = {},
|
||||
isLoading = false,
|
||||
onContinueClick = { },
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewManualBackupCompletedContentUpgrade() {
|
||||
TangemThemePreview {
|
||||
ManualBackupCompletedContent(
|
||||
state = ManualBackupCompletedUM(
|
||||
isLoading = false,
|
||||
onContinueClick = { },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,14 +53,14 @@ internal class UpgradeWalletModel @Inject constructor(
|
|||
) : Model() {
|
||||
private val params = paramsContainer.require<UpgradeWalletComponent.Params>()
|
||||
|
||||
private val _uiState = MutableStateFlow(
|
||||
UpgradeWalletUM(
|
||||
onBackClick = { router.pop() },
|
||||
onBuyTangemWalletClick = ::onBuyTangemWalletClick,
|
||||
onScanDeviceClick = ::onScanDeviceClick,
|
||||
),
|
||||
)
|
||||
internal val uiState: StateFlow<UpgradeWalletUM> = _uiState
|
||||
internal val uiState: StateFlow<UpgradeWalletUM>
|
||||
field = MutableStateFlow(
|
||||
UpgradeWalletUM(
|
||||
onBackClick = { router.pop() },
|
||||
onBuyTangemWalletClick = ::onBuyTangemWalletClick,
|
||||
onContinueClick = ::onContinueClick,
|
||||
),
|
||||
)
|
||||
|
||||
override fun onDestroy() {
|
||||
clearHotWalletContextualUnlockUseCase.invoke(params.userWalletId)
|
||||
|
|
@ -73,7 +73,7 @@ internal class UpgradeWalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun onScanDeviceClick() {
|
||||
private fun onContinueClick() {
|
||||
scanCard()
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ internal class UpgradeWalletModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun setLoading(isLoading: Boolean) {
|
||||
_uiState.update { it.copy(isLoading = isLoading) }
|
||||
uiState.update { it.copy(isLoading = isLoading) }
|
||||
}
|
||||
|
||||
private fun showCardVerificationFailedDialog(error: TangemError) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@ package com.tangem.features.hotwallet.upgradewallet.entity
|
|||
internal data class UpgradeWalletUM(
|
||||
val onBackClick: () -> Unit,
|
||||
val onBuyTangemWalletClick: () -> Unit,
|
||||
val onScanDeviceClick: () -> Unit,
|
||||
val onContinueClick: () -> Unit,
|
||||
val isLoading: Boolean = false,
|
||||
)
|
||||
|
|
@ -3,7 +3,9 @@ package com.tangem.features.hotwallet.upgradewallet.ui
|
|||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
|
@ -103,11 +105,11 @@ internal fun UpgradeWalletContent(state: UpgradeWalletUM, modifier: Modifier = M
|
|||
onClick = state.onBuyTangemWalletClick,
|
||||
)
|
||||
PrimaryButtonIconEnd(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.hw_upgrade_scan_device),
|
||||
onClick = state.onScanDeviceClick,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
iconResId = R.drawable.ic_tangem_24,
|
||||
text = stringResourceSafe(R.string.hw_upgrade_start_action),
|
||||
onClick = state.onContinueClick,
|
||||
showProgress = state.isLoading,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -116,13 +118,28 @@ internal fun UpgradeWalletContent(state: UpgradeWalletUM, modifier: Modifier = M
|
|||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewUpgradeWalletContent() {
|
||||
private fun PreviewUpgradeWalletContentBackup() {
|
||||
TangemThemePreview {
|
||||
UpgradeWalletContent(
|
||||
state = UpgradeWalletUM(
|
||||
onBackClick = {},
|
||||
onBuyTangemWalletClick = {},
|
||||
onScanDeviceClick = {},
|
||||
onContinueClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewUpgradeWalletContentScan() {
|
||||
TangemThemePreview {
|
||||
UpgradeWalletContent(
|
||||
state = UpgradeWalletUM(
|
||||
onBackClick = {},
|
||||
onBuyTangemWalletClick = {},
|
||||
onContinueClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,6 +147,8 @@ internal class WalletActivationModel @Inject constructor(
|
|||
override fun onContinueClick(userWalletId: UserWalletId) {
|
||||
stackNavigation.push(WalletActivationRoute.SetAccessCode)
|
||||
}
|
||||
|
||||
override fun onUpgradeClick(userWalletId: UserWalletId) = Unit
|
||||
}
|
||||
|
||||
inner class AccessCodeModelCallbacks : AccessCodeComponent.ModelCallbacks {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ internal class WalletActivationChildFactory @Inject constructor(
|
|||
params = ManualBackupCompletedComponent.Params(
|
||||
userWalletId = model.params.userWalletId,
|
||||
callbacks = model.manualBackupCompletedModelCallbacks,
|
||||
isUpgradeFlow = false,
|
||||
),
|
||||
)
|
||||
is WalletActivationRoute.SetAccessCode -> accessCodeComponentFactory.create(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ internal data class WalletBackupUM(
|
|||
val recoveryPhraseOption: LabelUM?,
|
||||
val googleDriveOption: LabelUM?,
|
||||
val googleDriveStatus: BackupStatus,
|
||||
val onBuyClick: () -> Unit,
|
||||
val onRecoveryPhraseClick: () -> Unit,
|
||||
val onGoogleDriveClick: () -> Unit,
|
||||
val onHardwareWalletClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
package com.tangem.features.hotwallet.walletbackup.model
|
||||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.label.entity.LabelStyle
|
||||
import com.tangem.core.ui.components.label.entity.LabelUM
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.domain.wallets.usecase.UnlockHotWalletContextualUseCase
|
||||
import com.tangem.features.hotwallet.WalletBackupComponent
|
||||
import com.tangem.features.hotwallet.walletbackup.entity.BackupStatus
|
||||
|
|
@ -21,12 +23,15 @@ import kotlinx.coroutines.launch
|
|||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class WalletBackupModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val unlockHotWalletContextualUseCase: UnlockHotWalletContextualUseCase,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val router: Router,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -45,6 +50,7 @@ internal class WalletBackupModel @Inject constructor(
|
|||
style = LabelStyle.REGULAR,
|
||||
),
|
||||
googleDriveStatus = BackupStatus.ComingSoon,
|
||||
onBuyClick = ::onBuyClick,
|
||||
onRecoveryPhraseClick = ::onRecoveryPhraseClick,
|
||||
onGoogleDriveClick = { },
|
||||
onHardwareWalletClick = ::onHardwareWalletClick,
|
||||
|
|
@ -95,6 +101,12 @@ internal class WalletBackupModel @Inject constructor(
|
|||
backedUp = userWallet.backedUp,
|
||||
)
|
||||
|
||||
private fun onBuyClick() {
|
||||
modelScope.launch {
|
||||
generateBuyTangemCardLinkUseCase.invoke().let { urlOpener.openUrl(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun onRecoveryPhraseClick() {
|
||||
if (uiState.value.backedUp) {
|
||||
getUserWalletUseCase.invoke(params.userWalletId)
|
||||
|
|
@ -113,7 +125,12 @@ internal class WalletBackupModel @Inject constructor(
|
|||
},
|
||||
)
|
||||
} else {
|
||||
router.push(AppRoute.CreateWalletBackup(params.userWalletId))
|
||||
router.push(
|
||||
AppRoute.CreateWalletBackup(
|
||||
userWalletId = params.userWalletId,
|
||||
isUpgradeFlow = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,6 +149,6 @@ internal class WalletBackupModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onHardwareWalletClick() {
|
||||
router.push(AppRoute.UpgradeWallet(params.userWalletId))
|
||||
router.push(AppRoute.WalletHardwareBackup(params.userWalletId))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +1,43 @@
|
|||
package com.tangem.features.hotwallet.walletbackup.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.hotwallet.walletbackup.entity.BackupStatus
|
||||
import com.tangem.features.hotwallet.walletbackup.entity.WalletBackupUM
|
||||
import com.tangem.features.hotwallet.common.ui.OptionBlock
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
|
||||
import com.tangem.core.ui.components.label.Label
|
||||
import com.tangem.core.ui.components.label.entity.LabelStyle
|
||||
import com.tangem.core.ui.components.label.entity.LabelUM
|
||||
import com.tangem.core.ui.components.rows.NetworkTitle
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.ForceDarkTheme
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.hotwallet.common.ui.OptionBlock
|
||||
import com.tangem.features.hotwallet.walletbackup.entity.BackupStatus
|
||||
import com.tangem.features.hotwallet.walletbackup.entity.WalletBackupUM
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
internal fun WalletBackupContent(state: WalletBackupUM, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
|
|
@ -46,11 +54,40 @@ internal fun WalletBackupContent(state: WalletBackupUM, modifier: Modifier = Mod
|
|||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 16.dp),
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
top = 12.dp,
|
||||
end = 16.dp,
|
||||
),
|
||||
) {
|
||||
Banner(state)
|
||||
|
||||
OptionBlock(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
title = stringResourceSafe(R.string.hw_backup_hardware_title),
|
||||
description = stringResourceSafe(R.string.hw_backup_hardware_description),
|
||||
badge = null,
|
||||
onClick = state.onHardwareWalletClick,
|
||||
enabled = true,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
)
|
||||
NetworkTitle(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp),
|
||||
title = {
|
||||
Text(
|
||||
modifier = Modifier,
|
||||
text = stringResourceSafe(R.string.onboarding_create_wallet_options_button_options),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
},
|
||||
)
|
||||
OptionBlock(
|
||||
modifier = Modifier,
|
||||
title = stringResourceSafe(R.string.hw_backup_seed_title),
|
||||
description = stringResourceSafe(R.string.hw_backup_seed_description),
|
||||
badge = {
|
||||
|
|
@ -60,7 +97,6 @@ internal fun WalletBackupContent(state: WalletBackupUM, modifier: Modifier = Mod
|
|||
enabled = true,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
)
|
||||
|
||||
OptionBlock(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp),
|
||||
|
|
@ -73,30 +109,125 @@ internal fun WalletBackupContent(state: WalletBackupUM, modifier: Modifier = Mod
|
|||
enabled = state.googleDriveStatus != BackupStatus.ComingSoon,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
)
|
||||
|
||||
NetworkTitle(
|
||||
title = {
|
||||
Text(
|
||||
modifier = Modifier,
|
||||
text = stringResourceSafe(R.string.express_provider_recommended),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
},
|
||||
)
|
||||
OptionBlock(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = stringResourceSafe(R.string.hw_backup_hardware_title),
|
||||
description = stringResourceSafe(R.string.hw_backup_hardware_description),
|
||||
badge = null,
|
||||
onClick = state.onHardwareWalletClick,
|
||||
enabled = true,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
)
|
||||
Spacer(modifier = Modifier.size(16.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
private fun Banner(state: WalletBackupUM, modifier: Modifier = Modifier) {
|
||||
ForceDarkTheme {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.background(
|
||||
color = TangemTheme.colors.background.primary,
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = 12.dp,
|
||||
top = 20.dp,
|
||||
end = 12.dp,
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
text = "Tangem Wallet",
|
||||
style = TangemTheme.typography.h3,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
top = 4.dp,
|
||||
),
|
||||
text = "Keeps your crypto safe and offline. Slim as a credit card, safer than a bank vault.",
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
FlowRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
start = 24.dp,
|
||||
top = 16.dp,
|
||||
end = 24.dp,
|
||||
),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
FeatureItem(
|
||||
iconResId = R.drawable.ic_shield_check_16,
|
||||
text = resourceReference(R.string.welcome_create_wallet_feature_class),
|
||||
)
|
||||
FeatureItem(
|
||||
iconResId = R.drawable.ic_flash_16,
|
||||
text = resourceReference(R.string.welcome_create_wallet_feature_delivery),
|
||||
)
|
||||
FeatureItem(
|
||||
iconResId = R.drawable.ic_sparkles_16,
|
||||
text = resourceReference(R.string.welcome_create_wallet_feature_use),
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = 8.dp,
|
||||
top = 12.dp,
|
||||
end = 8.dp,
|
||||
bottom = 20.dp,
|
||||
),
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.img_tangem_cards_vertical),
|
||||
contentDescription = null,
|
||||
)
|
||||
SecondaryButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.BottomCenter),
|
||||
text = stringResourceSafe(R.string.details_buy_wallet),
|
||||
onClick = state.onBuyClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FeatureItem(@DrawableRes iconResId: Int, text: TextReference) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.wrapContentWidth()
|
||||
.padding(horizontal = 8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(16.dp),
|
||||
painter = painterResource(iconResId),
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
text = text.resolveReference(),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
|
|
@ -119,6 +250,7 @@ private class WalletBackupUMProvider : CollectionPreviewParameterProvider<Wallet
|
|||
),
|
||||
googleDriveStatus = BackupStatus.ComingSoon,
|
||||
onBackClick = {},
|
||||
onBuyClick = {},
|
||||
onRecoveryPhraseClick = {},
|
||||
onGoogleDriveClick = {},
|
||||
onHardwareWalletClick = {},
|
||||
|
|
@ -135,6 +267,7 @@ private class WalletBackupUMProvider : CollectionPreviewParameterProvider<Wallet
|
|||
),
|
||||
googleDriveStatus = BackupStatus.NoBackup,
|
||||
onBackClick = {},
|
||||
onBuyClick = {},
|
||||
onRecoveryPhraseClick = {},
|
||||
onGoogleDriveClick = {},
|
||||
onHardwareWalletClick = {},
|
||||
|
|
@ -151,6 +284,7 @@ private class WalletBackupUMProvider : CollectionPreviewParameterProvider<Wallet
|
|||
),
|
||||
googleDriveStatus = BackupStatus.Done,
|
||||
onBackClick = {},
|
||||
onBuyClick = {},
|
||||
onRecoveryPhraseClick = {},
|
||||
onGoogleDriveClick = {},
|
||||
onHardwareWalletClick = {},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
package com.tangem.features.hotwallet.wallethardwarebackup.component
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.features.hotwallet.WalletHardwareBackupComponent
|
||||
import com.tangem.features.hotwallet.wallethardwarebackup.model.WalletHardwareBackupModel
|
||||
import com.tangem.features.hotwallet.wallethardwarebackup.ui.WalletHardwareBackupContent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class DefaultWalletHardwareBackupComponent @AssistedInject constructor(
|
||||
@Assisted private val context: AppComponentContext,
|
||||
@Assisted private val params: WalletHardwareBackupComponent.Params,
|
||||
) : WalletHardwareBackupComponent, AppComponentContext by context {
|
||||
|
||||
private val model: WalletHardwareBackupModel = getOrCreateModel(params)
|
||||
|
||||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.uiState.collectAsStateWithLifecycle()
|
||||
WalletHardwareBackupContent(
|
||||
state = state,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : WalletHardwareBackupComponent.Factory {
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: WalletHardwareBackupComponent.Params,
|
||||
): DefaultWalletHardwareBackupComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.tangem.features.hotwallet.wallethardwarebackup.di
|
||||
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.features.hotwallet.WalletHardwareBackupComponent
|
||||
import com.tangem.features.hotwallet.wallethardwarebackup.component.DefaultWalletHardwareBackupComponent
|
||||
import com.tangem.features.hotwallet.wallethardwarebackup.model.WalletHardwareBackupModel
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import dagger.multibindings.ClassKey
|
||||
import dagger.multibindings.IntoMap
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object WalletHardwareBackupModule
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal interface WalletHardwareBackupModuleBinds {
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindWalletHardwareBackupComponentFactory(
|
||||
impl: DefaultWalletHardwareBackupComponent.Factory,
|
||||
): WalletHardwareBackupComponent.Factory
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ClassKey(WalletHardwareBackupModel::class)
|
||||
fun bindWalletHardwareBackupModel(model: WalletHardwareBackupModel): Model
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.features.hotwallet.wallethardwarebackup.entity
|
||||
|
||||
import com.tangem.core.ui.components.label.entity.LabelUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
internal data class WalletHardwareBackupUM(
|
||||
val showPurchaseBlock: Boolean = false,
|
||||
val blocks: ImmutableList<Block>,
|
||||
val onBackClick: () -> Unit,
|
||||
val onBuyClick: () -> Unit,
|
||||
) {
|
||||
data class Block(
|
||||
val title: TextReference,
|
||||
val titleLabel: LabelUM?,
|
||||
val description: TextReference,
|
||||
val onClick: () -> Unit,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
package com.tangem.features.hotwallet.wallethardwarebackup.model
|
||||
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2
|
||||
import com.tangem.core.ui.components.bottomsheets.message.icon
|
||||
import com.tangem.core.ui.components.bottomsheets.message.infoBlock
|
||||
import com.tangem.core.ui.components.bottomsheets.message.onClick
|
||||
import com.tangem.core.ui.components.bottomsheets.message.primaryButton
|
||||
import com.tangem.core.ui.components.label.entity.LabelStyle
|
||||
import com.tangem.core.ui.components.label.entity.LabelUM
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.bottomSheetMessage
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.GenerateBuyTangemCardLinkUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.features.hotwallet.WalletHardwareBackupComponent
|
||||
import com.tangem.features.hotwallet.impl.R
|
||||
import com.tangem.features.hotwallet.wallethardwarebackup.entity.WalletHardwareBackupUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class WalletHardwareBackupModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val router: Router,
|
||||
private val generateBuyTangemCardLinkUseCase: GenerateBuyTangemCardLinkUseCase,
|
||||
private val urlOpener: UrlOpener,
|
||||
private val getUserWalletUseCase: GetUserWalletUseCase,
|
||||
private val messageSender: UiMessageSender,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<WalletHardwareBackupComponent.Params>()
|
||||
|
||||
// TODO actualize strings [REDACTED_TASK_KEY]
|
||||
private val makeBackupAtFirstAlertBS
|
||||
get() = bottomSheetMessage {
|
||||
infoBlock {
|
||||
icon(R.drawable.ic_passcode_lock_32) {
|
||||
type = MessageBottomSheetUMV2.Icon.Type.Accent
|
||||
backgroundType = MessageBottomSheetUMV2.Icon.BackgroundType.SameAsTint
|
||||
}
|
||||
title = stringReference("Finish Backup First")
|
||||
body = stringReference("To upgrade your wallet to hardware, back it up first.")
|
||||
}
|
||||
primaryButton {
|
||||
text = resourceReference(R.string.hw_backup_need_action)
|
||||
onClick {
|
||||
router.push(
|
||||
AppRoute.CreateWalletBackup(
|
||||
userWalletId = params.userWalletId,
|
||||
isUpgradeFlow = true,
|
||||
),
|
||||
)
|
||||
closeBs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO actualize strings [REDACTED_TASK_KEY]
|
||||
internal val uiState: StateFlow<WalletHardwareBackupUM>
|
||||
field = MutableStateFlow(
|
||||
WalletHardwareBackupUM(
|
||||
onBackClick = { router.pop() },
|
||||
blocks = persistentListOf(
|
||||
WalletHardwareBackupUM.Block(
|
||||
title = stringReference("Create new wallet"),
|
||||
titleLabel = LabelUM(
|
||||
text = resourceReference(R.string.common_recommended),
|
||||
style = LabelStyle.ACCENT,
|
||||
),
|
||||
description = stringReference(
|
||||
"Create a new secure wallet and transfer your funds for extra protection.",
|
||||
),
|
||||
onClick = ::onCreateNewWalletClick,
|
||||
),
|
||||
WalletHardwareBackupUM.Block(
|
||||
title = stringReference("Upgrade current wallet"),
|
||||
titleLabel = null,
|
||||
description = stringReference("Move your current wallet into Tangem Wallet."),
|
||||
onClick = ::onUpgradeCurrentWalletClick,
|
||||
),
|
||||
),
|
||||
onBuyClick = ::onBuyClick,
|
||||
),
|
||||
)
|
||||
|
||||
init {
|
||||
showPurchaseBlockWithDelay()
|
||||
}
|
||||
|
||||
private fun showPurchaseBlockWithDelay() {
|
||||
modelScope.launch {
|
||||
delay(SHOW_PURCHASE_BLOCK_DELAY)
|
||||
uiState.update { it.copy(showPurchaseBlock = true) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun onCreateNewWalletClick() {
|
||||
router.push(AppRoute.CreateHardwareWallet)
|
||||
}
|
||||
|
||||
private fun onUpgradeCurrentWalletClick() {
|
||||
val userWallet = getUserWalletUseCase.invoke(params.userWalletId)
|
||||
.getOrElse { error("Cannot find user wallet with id: ${params.userWalletId.stringValue}") }
|
||||
if (userWallet is UserWallet.Hot) {
|
||||
if (!userWallet.backedUp) {
|
||||
messageSender.send(makeBackupAtFirstAlertBS)
|
||||
} else {
|
||||
router.push(
|
||||
AppRoute.UpgradeWallet(
|
||||
userWalletId = params.userWalletId,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onBuyClick() {
|
||||
modelScope.launch {
|
||||
generateBuyTangemCardLinkUseCase.invoke().let { urlOpener.openUrl(it) }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val SHOW_PURCHASE_BLOCK_DELAY = 3000L
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
package com.tangem.features.hotwallet.wallethardwarebackup.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
|
||||
import com.tangem.core.ui.components.label.Label
|
||||
import com.tangem.core.ui.components.label.entity.LabelStyle
|
||||
import com.tangem.core.ui.components.label.entity.LabelUM
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.hotwallet.common.ui.OptionBlock
|
||||
import com.tangem.features.hotwallet.impl.R
|
||||
import com.tangem.features.hotwallet.wallethardwarebackup.entity.WalletHardwareBackupUM
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
internal fun WalletHardwareBackupContent(state: WalletHardwareBackupUM, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.background(TangemTheme.colors.background.secondary)
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding(),
|
||||
) {
|
||||
TopAppBar(
|
||||
modifier = Modifier
|
||||
.statusBarsPadding(),
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = TangemTheme.colors.background.secondary,
|
||||
),
|
||||
navigationIcon = {
|
||||
IconButton(onClick = state.onBackClick) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_back_24),
|
||||
tint = TangemTheme.colors.icon.primary1,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.hw_backup_hardware_title),
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
},
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
top = 4.dp,
|
||||
end = 16.dp,
|
||||
),
|
||||
) {
|
||||
state.blocks.forEach { block ->
|
||||
OptionBlock(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp),
|
||||
title = block.title.resolveReference(),
|
||||
description = block.description.resolveReference(),
|
||||
badge = block.titleLabel?.let {
|
||||
{ Label(it) }
|
||||
},
|
||||
enabled = true,
|
||||
backgroundColor = TangemTheme.colors.background.primary,
|
||||
onClick = block.onClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(state.showPurchaseBlock) {
|
||||
PurchaseBlock(
|
||||
onBuyClick = state.onBuyClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PurchaseBlock(onBuyClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
.background(
|
||||
color = TangemTheme.colors.background.primary,
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
)
|
||||
.padding(
|
||||
horizontal = 20.dp,
|
||||
vertical = 16.dp,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(end = 16.dp),
|
||||
text = stringResourceSafe(R.string.wallet_add_hardware_purchase),
|
||||
style = TangemTheme.typography.button,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
|
||||
SecondaryButton(
|
||||
text = stringResourceSafe(R.string.wallet_import_buy_title),
|
||||
onClick = onBuyClick,
|
||||
size = TangemButtonSize.RoundedAction,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewWalletHardwareBackupContent() {
|
||||
TangemThemePreview {
|
||||
WalletHardwareBackupContent(
|
||||
state = WalletHardwareBackupUM(
|
||||
onBackClick = { },
|
||||
blocks = persistentListOf(
|
||||
WalletHardwareBackupUM.Block(
|
||||
title = stringReference("Create new wallet"),
|
||||
titleLabel = LabelUM(
|
||||
text = resourceReference(R.string.common_recommended),
|
||||
style = LabelStyle.ACCENT,
|
||||
),
|
||||
description = stringReference(
|
||||
"Create a new secure wallet and transfer your funds for extra protection.",
|
||||
),
|
||||
onClick = { },
|
||||
),
|
||||
WalletHardwareBackupUM.Block(
|
||||
title = stringReference("Upgrade current wallet"),
|
||||
titleLabel = null,
|
||||
description = stringReference("Move your current wallet into Tangem Wallet."),
|
||||
onClick = { },
|
||||
),
|
||||
),
|
||||
showPurchaseBlock = true,
|
||||
onBuyClick = { },
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -38,11 +38,7 @@ import com.tangem.domain.wallets.usecase.*
|
|||
import com.tangem.feature.walletsettings.analytics.Settings
|
||||
import com.tangem.feature.walletsettings.analytics.WalletSettingsAnalyticEvents
|
||||
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
|
||||
import com.tangem.feature.walletsettings.entity.DialogConfig
|
||||
import com.tangem.feature.walletsettings.entity.NetworksAvailableForNotificationBSConfig
|
||||
import com.tangem.feature.walletsettings.entity.WalletSettingsAccountsUM
|
||||
import com.tangem.feature.walletsettings.entity.WalletSettingsItemUM
|
||||
import com.tangem.feature.walletsettings.entity.WalletSettingsUM
|
||||
import com.tangem.feature.walletsettings.entity.*
|
||||
import com.tangem.feature.walletsettings.impl.R
|
||||
import com.tangem.feature.walletsettings.utils.AccountItemsDelegate
|
||||
import com.tangem.feature.walletsettings.utils.ItemsBuilder
|
||||
|
|
@ -112,10 +108,15 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
title = resourceReference(R.string.hw_backup_need_title)
|
||||
body = resourceReference(R.string.hw_backup_need_description)
|
||||
}
|
||||
secondaryButton {
|
||||
primaryButton {
|
||||
text = resourceReference(R.string.hw_backup_need_action)
|
||||
onClick {
|
||||
router.push(AppRoute.CreateWalletBackup(params.userWalletId))
|
||||
router.push(
|
||||
AppRoute.CreateWalletBackup(
|
||||
userWalletId = params.userWalletId,
|
||||
isUpgradeFlow = false,
|
||||
),
|
||||
)
|
||||
closeBs()
|
||||
}
|
||||
}
|
||||
|
|
@ -354,7 +355,11 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
|
||||
private fun onUpgradeWalletClick() {
|
||||
unlockWalletIfNeedAndProceed {
|
||||
router.push(AppRoute.UpgradeWallet(params.userWalletId))
|
||||
router.push(
|
||||
AppRoute.UpgradeWallet(
|
||||
userWalletId = params.userWalletId,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -452,7 +457,12 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
primaryButton {
|
||||
text = stringReference("Go to backup")
|
||||
onClick {
|
||||
router.push(AppRoute.CreateWalletBackup(userWallet.walletId))
|
||||
router.push(
|
||||
AppRoute.CreateWalletBackup(
|
||||
userWalletId = userWallet.walletId,
|
||||
isUpgradeFlow = false,
|
||||
),
|
||||
)
|
||||
closeBs()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.feature.wallet.utils
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.common.ui.userwallet.converter.ArtworkUMConverter
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
|
|
@ -45,16 +44,15 @@ class DefaultUserWalletImageFetcher @Inject constructor(
|
|||
.map { allWallets -> allWallets.filter { (walletId, _) -> wallets.any { it.walletId == walletId } } }
|
||||
.distinctUntilChanged()
|
||||
|
||||
override fun walletImage(walletId: UserWalletId, size: ArtworkSize): Flow<UserWalletItemUM.ImageState> = flow {
|
||||
val imagesFlow = getUserWalletUseCase.invokeFlow(walletId)
|
||||
// emit Loading and wait wallet
|
||||
.onEach { if (it.isLeft()) emit(UserWalletItemUM.ImageState.Loading) }
|
||||
.filterIsInstance<Either.Right<UserWallet>>()
|
||||
.map { it.value }
|
||||
override fun walletImage(walletId: UserWalletId, size: ArtworkSize): Flow<UserWalletItemUM.ImageState> =
|
||||
getUserWalletUseCase.invokeFlow(walletId)
|
||||
.transformLatest {
|
||||
it.fold(
|
||||
ifLeft = { emit(UserWalletItemUM.ImageState.Loading) },
|
||||
ifRight = { wallet -> emitAll(walletImage(wallet, size)) },
|
||||
)
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest { wallet -> walletImage(wallet, size) }
|
||||
emitAll(imagesFlow)
|
||||
}.distinctUntilChanged()
|
||||
|
||||
override fun walletImage(cardDTO: CardDTO, size: ArtworkSize): Flow<UserWalletItemUM.ImageState> =
|
||||
internalGetCardImage(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue