diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
index 5bdb2476f6..e28474943c 100644
--- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
+++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
@@ -8,6 +8,7 @@ import com.tangem.feature.referral.api.ReferralComponent
import com.tangem.feature.stories.api.StoriesComponent
import com.tangem.feature.usedesk.api.UsedeskComponent
import com.tangem.feature.walletsettings.component.WalletSettingsComponent
+import com.tangem.features.hotwallet.WalletBackupComponent
import com.tangem.features.createwalletselection.CreateWalletSelectionComponent
import com.tangem.features.details.component.DetailsComponent
import com.tangem.features.disclaimer.api.components.DisclaimerComponent
@@ -51,6 +52,7 @@ import com.tangem.features.walletconnect.components.WalletConnectEntryComponent
internal class ChildFactory @Inject constructor(
private val detailsComponentFactory: DetailsComponent.Factory,
private val walletSettingsComponentFactory: WalletSettingsComponent.Factory,
+ private val walletBackupComponentFactory: WalletBackupComponent.Factory,
private val disclaimerComponentFactory: DisclaimerComponent.Factory,
private val manageTokensComponentFactory: ManageTokensComponent.Factory,
private val marketsTokenDetailsComponentFactory: MarketsTokenDetailsComponent.Factory,
@@ -141,6 +143,15 @@ internal class ChildFactory @Inject constructor(
componentFactory = walletSettingsComponentFactory,
)
}
+ is AppRoute.WalletBackup -> {
+ createComponentChild(
+ context = context,
+ params = WalletBackupComponent.Params(
+ userWalletId = route.userWalletId,
+ ),
+ componentFactory = walletBackupComponentFactory,
+ )
+ }
is AppRoute.MarketsTokenDetails -> {
createComponentChild(
context = context,
diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt
index d403d0800b..4f2fdceec3 100644
--- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt
+++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt
@@ -191,6 +191,11 @@ sealed class AppRoute(val path: String) : Route {
val userWalletId: UserWalletId,
) : AppRoute(path = "/wallet_settings/${userWalletId.stringValue}")
+ @Serializable
+ data class WalletBackup(
+ val userWalletId: UserWalletId,
+ ) : AppRoute(path = "/wallet_backup/${userWalletId.stringValue}")
+
@Serializable
data object Markets : AppRoute(path = "/markets")
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 1e513517d1..a2aa6ee2c6 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -425,8 +425,8 @@
To complete setup, back up your wallet and secure app access with a Access Code.
Finish Now
Finish Wallet Activation
- Recover an existing wallet stored in your iCloud backup
- iCloud backup
+ Recover an existing wallet stored in your Google Drive backup
+ Google Drive Backup
Go to backup
To secure your wallet with a Access Code, complete the backup first.
Finish Backup First
diff --git a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/ui/CreateWalletSelectionContent.kt b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/ui/CreateWalletSelectionContent.kt
index 6e412c985b..0c777f9a97 100644
--- a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/ui/CreateWalletSelectionContent.kt
+++ b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/ui/CreateWalletSelectionContent.kt
@@ -155,7 +155,7 @@ private fun WalletBlock(
Row {
Text(
modifier = Modifier
- .weight(1f)
+ .weight(1f, fill = false)
.padding(end = 8.dp),
text = title,
style = TangemTheme.typography.subtitle1,
diff --git a/features/hot-wallet/api/build.gradle.kts b/features/hot-wallet/api/build.gradle.kts
index 9b15221cb2..0b7e98f231 100644
--- a/features/hot-wallet/api/build.gradle.kts
+++ b/features/hot-wallet/api/build.gradle.kts
@@ -12,6 +12,7 @@ dependencies {
/* Project - Domain */
implementation(projects.domain.models)
+ implementation(projects.domain.wallets.models)
/* Project - Core */
implementation(projects.core.decompose)
diff --git a/features/hot-wallet/api/src/main/kotlin/com/tangem/features/hotwallet/WalletBackupComponent.kt b/features/hot-wallet/api/src/main/kotlin/com/tangem/features/hotwallet/WalletBackupComponent.kt
new file mode 100644
index 0000000000..a422db8dad
--- /dev/null
+++ b/features/hot-wallet/api/src/main/kotlin/com/tangem/features/hotwallet/WalletBackupComponent.kt
@@ -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.wallets.models.UserWalletId
+
+interface WalletBackupComponent : ComposableContentComponent {
+
+ data class Params(
+ val userWalletId: UserWalletId,
+ )
+
+ interface Factory : ComponentFactory
+}
\ No newline at end of file
diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/start/ui/AddExistingWalletStartContent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/start/ui/AddExistingWalletStartContent.kt
index 66e907f5d8..eef14e30c9 100644
--- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/start/ui/AddExistingWalletStartContent.kt
+++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/start/ui/AddExistingWalletStartContent.kt
@@ -3,27 +3,27 @@ package com.tangem.features.hotwallet.addexistingwallet.start.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.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import com.tangem.core.ui.R
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.components.buttons.common.TangemButtonSize
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
-import com.tangem.core.ui.extensions.clickableSingle
-import com.tangem.core.ui.extensions.conditional
+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.addexistingwallet.start.entity.AddExistingWalletStartUM
-import com.tangem.core.ui.R
-import com.tangem.core.ui.extensions.stringResourceSafe
+import com.tangem.features.hotwallet.common.ui.OptionBlock
@Suppress("LongMethod")
@OptIn(ExperimentalMaterial3Api::class)
@@ -62,6 +62,7 @@ internal fun AddExistingWalletStartContent(state: AddExistingWalletStartUM, modi
OptionBlock(
modifier = Modifier
.padding(top = 24.dp),
+ backgroundColor = TangemTheme.colors.background.secondary,
title = stringResourceSafe(R.string.wallet_import_seed_title),
description = stringResourceSafe(R.string.wallet_import_seed_description),
badge = null,
@@ -69,6 +70,7 @@ internal fun AddExistingWalletStartContent(state: AddExistingWalletStartUM, modi
enabled = true,
)
OptionBlock(
+ backgroundColor = TangemTheme.colors.background.secondary,
title = stringResourceSafe(R.string.wallet_import_scan_title),
description = stringResourceSafe(R.string.wallet_import_scan_description),
badge = {
@@ -85,6 +87,7 @@ internal fun AddExistingWalletStartContent(state: AddExistingWalletStartUM, modi
enabled = true,
)
OptionBlock(
+ backgroundColor = TangemTheme.colors.background.secondary,
title = stringResourceSafe(R.string.wallet_import_google_drive_title),
description = stringResourceSafe(R.string.wallet_import_google_drive_description),
badge = {
@@ -114,58 +117,6 @@ internal fun AddExistingWalletStartContent(state: AddExistingWalletStartUM, modi
}
}
-@Composable
-private fun OptionBlock(
- title: String,
- description: String,
- badge: (@Composable () -> Unit)?,
- onClick: (() -> Unit)?,
- enabled: Boolean,
- modifier: Modifier = Modifier,
-) {
- Column(
- modifier = modifier
- .fillMaxWidth()
- .padding(top = 8.dp)
- .clip(TangemTheme.shapes.roundedCornersXMedium)
- .background(
- color = TangemTheme.colors.background.secondary,
- shape = TangemTheme.shapes.roundedCornersXMedium,
- )
- .conditional(onClick != null) {
- onClick?.let { clickableSingle(onClick = it) } ?: Modifier
- }
- .padding(16.dp),
- ) {
- Row {
- Text(
- modifier = Modifier
- .weight(1f, fill = false)
- .padding(end = 4.dp),
- text = title,
- style = TangemTheme.typography.subtitle1,
- color = if (enabled) {
- TangemTheme.colors.text.primary1
- } else {
- TangemTheme.colors.text.secondary
- },
- )
- badge?.invoke()
- }
- Text(
- modifier = Modifier
- .padding(top = 4.dp),
- text = description,
- style = TangemTheme.typography.body2,
- color = if (enabled) {
- TangemTheme.colors.text.tertiary
- } else {
- TangemTheme.colors.text.disabled
- },
- )
- }
-}
-
@Composable
private fun BuyTangemWalletBlock(onScanClick: () -> Unit, modifier: Modifier = Modifier) {
Row(
diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/common/ui/OptionBlock.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/common/ui/OptionBlock.kt
new file mode 100644
index 0000000000..ad1d8637e1
--- /dev/null
+++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/common/ui/OptionBlock.kt
@@ -0,0 +1,88 @@
+package com.tangem.features.hotwallet.common.ui
+
+import androidx.compose.animation.animateColorAsState
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+import com.tangem.core.ui.extensions.clickableSingle
+import com.tangem.core.ui.extensions.conditional
+import com.tangem.core.ui.res.TangemTheme
+
+internal const val DISABLED_COLORS_ALPHA = 0.5f
+
+@Suppress("LongParameterList")
+@Composable
+internal fun OptionBlock(
+ title: String,
+ description: String,
+ badge: (@Composable () -> Unit)?,
+ onClick: (() -> Unit)?,
+ enabled: Boolean,
+ backgroundColor: Color,
+ modifier: Modifier = Modifier,
+) {
+ val backgroundColor by animateColorAsState(
+ targetValue = if (enabled) {
+ backgroundColor
+ } else {
+ backgroundColor.copy(alpha = DISABLED_COLORS_ALPHA)
+ },
+ )
+ val titleColor by animateColorAsState(
+ targetValue = if (enabled) {
+ TangemTheme.colors.text.primary1
+ } else {
+ TangemTheme.colors.text.primary1.copy(alpha = DISABLED_COLORS_ALPHA)
+ },
+ )
+ val descriptionColor by animateColorAsState(
+ targetValue = if (enabled) {
+ TangemTheme.colors.text.tertiary
+ } else {
+ TangemTheme.colors.text.tertiary.copy(alpha = DISABLED_COLORS_ALPHA)
+ },
+ )
+
+ Column(
+ modifier = modifier
+ .fillMaxWidth()
+ .padding(top = 8.dp)
+ .clip(TangemTheme.shapes.roundedCornersXMedium)
+ .background(
+ color = backgroundColor,
+ shape = TangemTheme.shapes.roundedCornersXMedium,
+ )
+ .conditional(onClick != null) {
+ onClick?.let { clickableSingle(onClick = it) } ?: Modifier
+ }
+ .padding(16.dp),
+ ) {
+ Row {
+ Text(
+ modifier = Modifier
+ .weight(1f, fill = false)
+ .padding(end = 4.dp),
+ text = title,
+ style = TangemTheme.typography.subtitle1,
+ color = titleColor,
+ )
+ badge?.invoke()
+ }
+ Text(
+ modifier = Modifier
+ .padding(top = 4.dp),
+ text = description,
+ style = TangemTheme.typography.body2,
+ color = descriptionColor,
+ )
+ }
+}
\ No newline at end of file
diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/component/DefaultWalletBackupComponent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/component/DefaultWalletBackupComponent.kt
new file mode 100644
index 0000000000..5c9921bdf6
--- /dev/null
+++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/component/DefaultWalletBackupComponent.kt
@@ -0,0 +1,39 @@
+package com.tangem.features.hotwallet.walletbackup.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.WalletBackupComponent
+import com.tangem.features.hotwallet.walletbackup.model.WalletBackupModel
+import com.tangem.features.hotwallet.walletbackup.ui.WalletBackupContent
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+
+internal class DefaultWalletBackupComponent @AssistedInject constructor(
+ @Assisted private val context: AppComponentContext,
+ @Assisted private val params: WalletBackupComponent.Params,
+) : WalletBackupComponent, AppComponentContext by context {
+
+ private val model: WalletBackupModel = getOrCreateModel(params)
+
+ @Composable
+ override fun Content(modifier: Modifier) {
+ val state by model.uiState.collectAsStateWithLifecycle()
+ WalletBackupContent(
+ state = state,
+ modifier = modifier,
+ )
+ }
+
+ @AssistedFactory
+ interface Factory : WalletBackupComponent.Factory {
+ override fun create(
+ context: AppComponentContext,
+ params: WalletBackupComponent.Params,
+ ): DefaultWalletBackupComponent
+ }
+}
\ No newline at end of file
diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/di/WalletBackupModule.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/di/WalletBackupModule.kt
new file mode 100644
index 0000000000..befb8e70c7
--- /dev/null
+++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/di/WalletBackupModule.kt
@@ -0,0 +1,27 @@
+package com.tangem.features.hotwallet.walletbackup.di
+
+import com.tangem.core.decompose.model.Model
+import com.tangem.features.hotwallet.WalletBackupComponent
+import com.tangem.features.hotwallet.walletbackup.component.DefaultWalletBackupComponent
+import com.tangem.features.hotwallet.walletbackup.model.WalletBackupModel
+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 interface WalletBackupModule {
+
+ @Binds
+ @IntoMap
+ @ClassKey(WalletBackupModel::class)
+ fun bindWalletBackupModel(model: WalletBackupModel): Model
+
+ @Binds
+ @Singleton
+ fun bindWalletBackupComponentFactory(factory: DefaultWalletBackupComponent.Factory): WalletBackupComponent.Factory
+}
\ No newline at end of file
diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/entity/WalletBackupUM.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/entity/WalletBackupUM.kt
new file mode 100644
index 0000000000..be22d8cd38
--- /dev/null
+++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/entity/WalletBackupUM.kt
@@ -0,0 +1,15 @@
+package com.tangem.features.hotwallet.walletbackup.entity
+
+internal data class WalletBackupUM(
+ val onBackClick: () -> Unit,
+ val recoveryPhraseStatus: BackupStatus,
+ val googleDriveStatus: BackupStatus,
+ val onRecoveryPhraseClick: () -> Unit,
+ val onGoogleDriveClick: () -> Unit,
+)
+
+internal sealed class BackupStatus {
+ object Done : BackupStatus()
+ object ComingSoon : BackupStatus()
+ object NoBackup : BackupStatus()
+}
\ No newline at end of file
diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/model/WalletBackupModel.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/model/WalletBackupModel.kt
new file mode 100644
index 0000000000..f85e281c17
--- /dev/null
+++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/model/WalletBackupModel.kt
@@ -0,0 +1,54 @@
+package com.tangem.features.hotwallet.walletbackup.model
+
+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.domain.wallets.usecase.GetUserWalletUseCase
+import com.tangem.features.hotwallet.WalletBackupComponent
+import com.tangem.features.hotwallet.walletbackup.entity.BackupStatus
+import com.tangem.features.hotwallet.walletbackup.entity.WalletBackupUM
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import kotlinx.coroutines.flow.*
+import javax.inject.Inject
+
+@ModelScoped
+internal class WalletBackupModel @Inject constructor(
+ paramsContainer: ParamsContainer,
+ getWalletUseCase: GetUserWalletUseCase,
+ private val router: Router,
+ override val dispatchers: CoroutineDispatcherProvider,
+) : Model() {
+
+ private val params: WalletBackupComponent.Params = paramsContainer.require()
+
+ val uiState: StateFlow
+ field = MutableStateFlow(
+ WalletBackupUM(
+ onBackClick = { router.pop() },
+ recoveryPhraseStatus = BackupStatus.NoBackup,
+ googleDriveStatus = BackupStatus.ComingSoon,
+ onRecoveryPhraseClick = { },
+ onGoogleDriveClick = { },
+ ),
+ )
+
+ init {
+ getWalletUseCase.invokeFlow(params.userWalletId)
+ .map { it.getOrNull() }
+ .distinctUntilChanged()
+ .onEach {
+ updateBackupStatuses()
+ }
+ .launchIn(modelScope)
+ }
+
+ private fun updateBackupStatuses() {
+ uiState.update { currentState ->
+ currentState.copy(
+ recoveryPhraseStatus = BackupStatus.NoBackup,
+ googleDriveStatus = BackupStatus.ComingSoon,
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/ui/WalletBackupContent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/ui/WalletBackupContent.kt
new file mode 100644
index 0000000000..7d5ac986a4
--- /dev/null
+++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/walletbackup/ui/WalletBackupContent.kt
@@ -0,0 +1,155 @@
+package com.tangem.features.hotwallet.walletbackup.ui
+
+import android.content.res.Configuration
+import androidx.compose.animation.AnimatedContent
+import androidx.compose.animation.animateColorAsState
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+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.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+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.features.hotwallet.common.ui.DISABLED_COLORS_ALPHA
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+internal fun WalletBackupContent(state: WalletBackupUM, modifier: Modifier = Modifier) {
+ Column(
+ modifier = modifier
+ .background(TangemTheme.colors.background.secondary)
+ .fillMaxSize()
+ .systemBarsPadding(),
+ ) {
+ AppBarWithBackButton(
+ text = stringResourceSafe(R.string.common_backup),
+ onBackClick = state.onBackClick,
+ )
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(horizontal = 16.dp),
+ ) {
+ OptionBlock(
+ modifier = Modifier.fillMaxWidth(),
+ title = stringResourceSafe(R.string.hw_backup_seed_title),
+ description = stringResourceSafe(R.string.hw_backup_seed_description),
+ badge = {
+ BackupStatusBadge(status = state.recoveryPhraseStatus)
+ },
+ onClick = state.onRecoveryPhraseClick,
+ enabled = true,
+ backgroundColor = TangemTheme.colors.background.primary,
+ )
+
+ OptionBlock(
+ modifier = Modifier.fillMaxWidth(),
+ title = stringResourceSafe(R.string.hw_backup_google_drive_title),
+ description = stringResourceSafe(R.string.hw_backup_google_drive_description),
+ badge = {
+ BackupStatusBadge(status = state.googleDriveStatus)
+ },
+ onClick = state.onGoogleDriveClick,
+ enabled = state.googleDriveStatus != BackupStatus.ComingSoon,
+ backgroundColor = TangemTheme.colors.background.primary,
+ )
+ }
+ }
+}
+
+@Composable
+private fun BackupStatusBadge(status: BackupStatus, modifier: Modifier = Modifier) {
+ val text = when (status) {
+ BackupStatus.Done -> stringResourceSafe(R.string.common_done)
+ BackupStatus.ComingSoon -> stringResourceSafe(R.string.common_coming_soon)
+ BackupStatus.NoBackup -> stringResourceSafe(R.string.hw_backup_no_backup)
+ }
+
+ val backgroundColor by animateColorAsState(
+ targetValue = when (status) {
+ BackupStatus.Done -> TangemTheme.colors.text.accent.copy(alpha = 0.1f)
+ BackupStatus.ComingSoon -> TangemTheme.colors.control.unchecked.copy(DISABLED_COLORS_ALPHA)
+ BackupStatus.NoBackup -> TangemTheme.colors.text.warning.copy(alpha = 0.1f)
+ },
+ )
+
+ val textColor by animateColorAsState(
+ targetValue = when (status) {
+ BackupStatus.Done -> TangemTheme.colors.text.accent
+ BackupStatus.ComingSoon -> TangemTheme.colors.text.secondary.copy(DISABLED_COLORS_ALPHA)
+ BackupStatus.NoBackup -> TangemTheme.colors.text.warning
+ },
+ )
+
+ AnimatedContent(targetState = text) { text ->
+ Box(
+ modifier = modifier
+ .padding(horizontal = 4.dp)
+ .background(
+ color = backgroundColor,
+ shape = TangemTheme.shapes.roundedCorners8,
+ )
+ .padding(horizontal = 8.dp, vertical = 4.dp),
+ ) {
+ Text(
+ text = text,
+ style = TangemTheme.typography.caption1,
+ color = textColor,
+ )
+ }
+ }
+}
+
+@Preview(showBackground = true, widthDp = 360)
+@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
+@Composable
+private fun WalletBackupContentPreview(@PreviewParameter(WalletBackupUMProvider::class) state: WalletBackupUM) {
+ TangemThemePreview {
+ WalletBackupContent(state)
+ }
+}
+
+private class WalletBackupUMProvider : CollectionPreviewParameterProvider(
+ collection = listOf(
+ WalletBackupUM(
+ recoveryPhraseStatus = BackupStatus.NoBackup,
+ googleDriveStatus = BackupStatus.ComingSoon,
+ onBackClick = {},
+ onRecoveryPhraseClick = {},
+ onGoogleDriveClick = {},
+ ),
+ WalletBackupUM(
+ recoveryPhraseStatus = BackupStatus.NoBackup,
+ googleDriveStatus = BackupStatus.NoBackup,
+ onBackClick = {},
+ onRecoveryPhraseClick = {},
+ onGoogleDriveClick = {},
+ ),
+ WalletBackupUM(
+ recoveryPhraseStatus = BackupStatus.Done,
+ googleDriveStatus = BackupStatus.Done,
+ onBackClick = {},
+ onRecoveryPhraseClick = {},
+ onGoogleDriveClick = {},
+ ),
+ ),
+)
\ No newline at end of file
diff --git a/features/wallet-settings/impl/build.gradle.kts b/features/wallet-settings/impl/build.gradle.kts
index 2de59a0dba..0adf247700 100644
--- a/features/wallet-settings/impl/build.gradle.kts
+++ b/features/wallet-settings/impl/build.gradle.kts
@@ -19,6 +19,7 @@ dependencies {
implementation(projects.features.nft.api)
implementation(projects.features.onboardingV2.api)
implementation(projects.features.pushNotifications.api)
+ implementation(projects.features.hotWallet.api)
/* Project - Core */
implementation(projects.core.decompose)
diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt
index 5e9614cd3a..023afb9685 100644
--- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt
+++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/component/preview/PreviewWalletSettingsComponent.kt
@@ -36,6 +36,7 @@ internal class PreviewWalletSettingsComponent : WalletSettingsComponent {
onCheckedNotificationsChanged = {},
onNotificationsDescriptionClick = {},
isNotificationsPermissionGranted = false,
+ isHotWalletEnabled = false,
),
requestPushNotificationsPermission = false,
onPushNotificationPermissionGranted = {},
diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt
index b6d2f0e7dd..f4ea875953 100644
--- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt
+++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt
@@ -41,6 +41,7 @@ import com.tangem.feature.walletsettings.entity.WalletSettingsItemUM
import com.tangem.feature.walletsettings.entity.WalletSettingsUM
import com.tangem.feature.walletsettings.impl.R
import com.tangem.feature.walletsettings.utils.ItemsBuilder
+import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnalyticEvents
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.PersistentList
@@ -72,6 +73,7 @@ internal class WalletSettingsModel @Inject constructor(
private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase,
private val settingsManager: SettingsManager,
private val permissionsRepository: PermissionRepository,
+ private val hotWalletFeatureToggles: HotWalletFeatureToggles,
) : Model() {
val params: WalletSettingsComponent.Params = paramsContainer.require()
@@ -105,6 +107,7 @@ internal class WalletSettingsModel @Inject constructor(
isNotificationsEnabled = notificationsEnabled,
isNotificationsFeatureEnabled = notificationsToggles.isNotificationsEnabled,
isNotificationsPermissionGranted = isNotificationsPermissionGranted(),
+ isHotWalletEnabled = hotWalletFeatureToggles.isHotWalletEnabled,
),
)
}
@@ -130,6 +133,7 @@ internal class WalletSettingsModel @Inject constructor(
isNotificationsFeatureEnabled: Boolean,
isNotificationsEnabled: Boolean,
isNotificationsPermissionGranted: Boolean,
+ isHotWalletEnabled: Boolean,
): PersistentList = itemsBuilder.buildItems(
userWalletId = userWallet.walletId,
userWalletName = userWallet.name,
@@ -167,6 +171,7 @@ internal class WalletSettingsModel @Inject constructor(
isNotificationsPermissionGranted = isNotificationsPermissionGranted,
onCheckedNotificationsChanged = ::onCheckedNotificationsChange,
onNotificationsDescriptionClick = ::onNotificationsDescriptionClick,
+ isHotWalletEnabled = isHotWalletEnabled,
)
private fun openRenameWalletDialog(userWallet: UserWallet, dialogNavigation: SlotNavigation) {
diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt
index 9a0c8c8971..1349f34906 100644
--- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt
+++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/ItemsBuilder.kt
@@ -43,6 +43,7 @@ internal class ItemsBuilder @Inject constructor(
renameWallet: () -> Unit,
onLinkMoreCardsClick: () -> Unit,
onReferralClick: () -> Unit,
+ isHotWalletEnabled: Boolean,
): PersistentList = persistentListOf()
.add(buildNameItem(userWalletName, isRenameWalletAvailable, renameWallet))
.run {
@@ -60,6 +61,7 @@ internal class ItemsBuilder @Inject constructor(
isManageTokensAvailable = isManageTokensAvailable,
onLinkMoreCardsClick = onLinkMoreCardsClick,
onReferralClick = onReferralClick,
+ isHotWalletEnabled = isHotWalletEnabled,
),
)
.addAll(
@@ -137,6 +139,7 @@ internal class ItemsBuilder @Inject constructor(
isManageTokensAvailable: Boolean,
onLinkMoreCardsClick: () -> Unit,
onReferralClick: () -> Unit,
+ isHotWalletEnabled: Boolean,
) = WalletSettingsItemUM.WithItems(
id = "card",
description = resourceReference(R.string.settings_card_settings_footer),
@@ -166,6 +169,14 @@ internal class ItemsBuilder @Inject constructor(
onClick = { router.push(AppRoute.CardSettings(userWalletId)) },
).let(::add)
+ if (isHotWalletEnabled) {
+ BlockUM(
+ text = resourceReference(R.string.common_backup),
+ iconRes = R.drawable.ic_more_cards_24,
+ onClick = { router.push(AppRoute.WalletBackup(userWalletId)) },
+ ).let(::add)
+ }
+
if (isReferralAvailable) {
BlockUM(
text = resourceReference(R.string.details_referral_title),