diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 85b539e159..c17cd6b366 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -226,6 +226,8 @@ dependencies { implementation(projects.features.kyc.impl) implementation(projects.features.welcome.api) implementation(projects.features.welcome.impl) + implementation(projects.features.createWalletSelection.api) + implementation(projects.features.createWalletSelection.impl) /** AndroidX libraries */ implementation(deps.androidx.core.ktx) diff --git a/app/src/main/java/com/tangem/tap/features/home/HomeModel.kt b/app/src/main/java/com/tangem/tap/features/home/HomeModel.kt index 8936e89b41..3c580e42fd 100644 --- a/app/src/main/java/com/tangem/tap/features/home/HomeModel.kt +++ b/app/src/main/java/com/tangem/tap/features/home/HomeModel.kt @@ -11,6 +11,7 @@ import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.Basic import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.navigation.Router import com.tangem.core.navigation.url.UrlOpener import com.tangem.domain.card.ScanCardProcessor import com.tangem.domain.card.repository.CardSdkConfigRepository @@ -54,6 +55,7 @@ internal class HomeModel @Inject constructor( private val urlOpener: UrlOpener, private val analyticsEventHandler: AnalyticsEventHandler, private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory, + private val router: Router, getUserCountryUseCase: GetUserCountryUseCase, ) : Model() { @@ -72,11 +74,11 @@ internal class HomeModel @Inject constructor( } fun onCreateNewWalletScreen() { - // TODO implement navigation to create new wallet + router.push(AppRoute.CreateWalletSelection) } fun onAddExistingWalletScreen() { - // TODO implement navigation to add existing wallet + router.push(AppRoute.AddExistingWallet) } fun onScanClick() { 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 4c5089eeb5..825a388842 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,8 +8,11 @@ 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.createwalletselection.CreateWalletSelectionComponent import com.tangem.features.details.component.DetailsComponent import com.tangem.features.disclaimer.api.components.DisclaimerComponent +import com.tangem.features.hotwallet.AddExistingWalletComponent +import com.tangem.features.hotwallet.CreateMobileWalletComponent import com.tangem.features.managetokens.component.ChooseManagedTokensComponent import com.tangem.features.managetokens.component.ManageTokensComponent import com.tangem.features.managetokens.component.ManageTokensSource @@ -80,6 +83,9 @@ internal class ChildFactory @Inject constructor( private val nftSendComponentFactory: NFTSendComponent.Factory, private val usedeskComponentFactory: UsedeskComponent.Factory, private val chooseManagedTokensComponentFactory: ChooseManagedTokensComponent.Factory, + private val createWalletSelectionComponentFactory: CreateWalletSelectionComponent.Factory, + private val createMobileWalletComponentFactory: CreateMobileWalletComponent.Factory, + private val addExistingWalletComponentFactory: AddExistingWalletComponent.Factory, private val testerRouter: TesterRouter, private val walletConnectFeatureToggles: WalletConnectFeatureToggles, ) { @@ -420,6 +426,27 @@ internal class ChildFactory @Inject constructor( componentFactory = chooseManagedTokensComponentFactory, ) } + is AppRoute.CreateWalletSelection -> { + createComponentChild( + context = context, + params = Unit, + componentFactory = createWalletSelectionComponentFactory, + ) + } + is AppRoute.CreateMobileWallet -> { + createComponentChild( + context = context, + params = Unit, + componentFactory = createMobileWalletComponentFactory, + ) + } + is AppRoute.AddExistingWallet -> { + createComponentChild( + context = context, + params = Unit, + componentFactory = addExistingWalletComponentFactory, + ) + } } } } \ No newline at end of file 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 bfa14feda5..410b01ee6d 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 @@ -286,4 +286,13 @@ sealed class AppRoute(val path: String) : Route { val nftAsset: NFTAsset, val nftCollectionName: String, ) : AppRoute(path = "/send/nft/${userWalletId.stringValue}/$nftCollectionName/${nftAsset.id}") + + @Serializable + object CreateWalletSelection : AppRoute(path = "/create_wallet_selection") + + @Serializable + object CreateMobileWallet : AppRoute(path = "/create_mobile_wallet") + + @Serializable + object AddExistingWallet : AppRoute(path = "/add_existing_wallet") } \ No newline at end of file diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index fc05ef9a38..28efd231b8 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -119,6 +119,7 @@ Claim Claim rewards Close + Coming Soon Confirm Contact Tangem Support Contact Visa Support @@ -154,6 +155,7 @@ Slow Speed and fee Finish + Free Synchronize addresses Go to provider Go to token @@ -387,6 +389,19 @@ Scan Tangem to %s On %s network + Recover an existing wallet stored in your iCloud backup + iCloud backup + Go to backup + To secure your wallet with a Access Code, complete the backup first. + Finish Backup First + No backup + Physical cards that securely store your crypto offline. + Recovery phrase + Get notified of incoming transactions + Keys are stored in the app + Stay up to date with the latest features and news + Seed phrase backup + Create Mobile Wallet This information was generated with AI.\nTap here, if you find any errors. To change the access code tap the card or ring as shown above and do not remove until the end of the operation To change the passcode tap the card as shown above and do not remove until the end of the operation @@ -1246,6 +1261,29 @@ Connect to dApps WalletConnect Connecting may take a few seconds + From %s + Buy Tangem Wallet — physical cards that securely store your crypto offline. + Hardware Wallet + A secure wallet is created on your phone in seconds. + Mobile Wallet + What to choose? + Do you already have Tangem Wallet? + Scan Now + Choose how you want to create your wallet + Want to purchase a Tangem Wallet? + Buy Now + Recover an existing wallet stored in your Google Drive backup + Import from Google Drive + Add existing wallet + Physical cards that securely store your crypto offline. + Scan a Tangem Wallet + Your seed phrase to recover your wallet + Import wallet + Import a recovery phrase + You successfully backed up your wallet. + Import wallet + Import Completed + Import wallet %s Market Price last 24h %s network diff --git a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionModel.kt b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionModel.kt index 0299618954..242046b568 100644 --- a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionModel.kt +++ b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionModel.kt @@ -1,7 +1,9 @@ package com.tangem.features.createwalletselection +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.navigation.Router import com.tangem.features.createwalletselection.entity.CreateWalletSelectionUM import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow @@ -11,12 +13,13 @@ import javax.inject.Inject @ModelScoped internal class CreateWalletSelectionModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, + private val router: Router, ) : Model() { internal val uiState: StateFlow field = MutableStateFlow( CreateWalletSelectionUM( - onBackClick = { /* [REDACTED_TODO_COMMENT] */ }, + onBackClick = { router.pop() }, onMobileWalletClick = ::onMobileWalletClick, onHardwareWalletClick = ::onHardwareWalletClick, onScanClick = ::onScanClick, @@ -24,7 +27,7 @@ internal class CreateWalletSelectionModel @Inject constructor( ) private fun onMobileWalletClick() { - // TODO navigate to mobile wallet creation + router.push(AppRoute.CreateMobileWallet) } private fun onHardwareWalletClick() { diff --git a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionFeatureModule.kt b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/di/CreateWalletSelectionModule.kt similarity index 64% rename from features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionFeatureModule.kt rename to features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/di/CreateWalletSelectionModule.kt index a810f1ba9f..239fcfe4ad 100644 --- a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/CreateWalletSelectionFeatureModule.kt +++ b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/di/CreateWalletSelectionModule.kt @@ -1,6 +1,9 @@ -package com.tangem.features.createwalletselection +package com.tangem.features.createwalletselection.di import com.tangem.core.decompose.model.Model +import com.tangem.features.createwalletselection.CreateWalletSelectionComponent +import com.tangem.features.createwalletselection.CreateWalletSelectionModel +import com.tangem.features.createwalletselection.DefaultCreateWalletSelectionComponent import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -11,11 +14,11 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) -internal object CreateWalletSelectionFeatureModule +internal object CreateWalletSelectionModule @Module @InstallIn(SingletonComponent::class) -internal interface CreateWalletSelectionFeatureModuleBinds { +internal interface CreateWalletSelectionModuleBinds { @Binds @Singleton diff --git a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/entity/CreateWalletSelectionUM.kt b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/entity/CreateWalletSelectionUM.kt index 70c95a5b38..38affd1226 100644 --- a/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/entity/CreateWalletSelectionUM.kt +++ b/features/create-wallet-selection/impl/src/main/kotlin/com/tangem/features/createwalletselection/entity/CreateWalletSelectionUM.kt @@ -2,6 +2,7 @@ package com.tangem.features.createwalletselection.entity internal data class CreateWalletSelectionUM( val isScanInProgress: Boolean = false, + val hardwareWalletPrice: String = "$54.90", val onBackClick: () -> Unit, val onMobileWalletClick: () -> Unit, val onHardwareWalletClick: () -> Unit, 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 e5ffea8e68..6e412c985b 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 @@ -8,6 +8,7 @@ import androidx.compose.material3.* 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.text.style.TextOverflow @@ -17,6 +18,7 @@ import com.tangem.core.ui.components.buttons.common.TangemButton import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition import com.tangem.core.ui.components.buttons.common.TangemButtonSize import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults +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.createwalletselection.entity.CreateWalletSelectionUM @@ -27,13 +29,13 @@ import com.tangem.features.createwalletselection.impl.R @Composable internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifier: Modifier = Modifier) { Column( - modifier = Modifier + modifier = modifier .background(TangemTheme.colors.background.primary) .fillMaxSize() .systemBarsPadding(), ) { TopAppBar( - modifier = modifier + modifier = Modifier .statusBarsPadding(), colors = TopAppBarDefaults.topAppBarColors( containerColor = TangemTheme.colors.background.primary, @@ -52,8 +54,7 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi Text( modifier = Modifier .padding(16.dp), - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "What to choose?", + text = stringResourceSafe(R.string.wallet_create_nav_info_title), style = TangemTheme.typography.body1, color = TangemTheme.colors.text.primary1, maxLines = 1, @@ -74,8 +75,7 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp), - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "Choose how you want to create your wallet", + text = stringResourceSafe(R.string.wallet_create_title), style = TangemTheme.typography.h2, color = TangemTheme.colors.text.primary1, textAlign = TextAlign.Center, @@ -83,10 +83,8 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi WalletBlock( modifier = Modifier .padding(top = 24.dp), - // TODO [REDACTED_TASK_KEY] update and extract this string - title = "Mobile Wallet", - // TODO [REDACTED_TASK_KEY] update and extract this string - description = "A secure wallet is created on your phone in seconds.", + title = stringResourceSafe(R.string.wallet_create_mobile_title), + description = stringResourceSafe(R.string.wallet_create_mobile_description), badge = { Box( modifier = Modifier @@ -97,8 +95,7 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi .padding(horizontal = 8.dp, vertical = 4.dp), ) { Text( - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "Free", + text = stringResourceSafe(R.string.common_free), style = TangemTheme.typography.caption1, color = TangemTheme.colors.text.secondary, ) @@ -107,10 +104,8 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi onClick = state.onMobileWalletClick, ) WalletBlock( - // TODO [REDACTED_TASK_KEY] update and extract this string - title = "Hardware Wallet", - // TODO [REDACTED_TASK_KEY] update and extract this string - description = "Buy Tangem Wallet — physical cards that securely store your crypto offline.", + title = stringResourceSafe(R.string.wallet_create_hardware_title), + description = stringResourceSafe(R.string.wallet_create_hardware_description), badge = { Box( modifier = Modifier @@ -121,8 +116,7 @@ internal fun CreateWalletSelectionContent(state: CreateWalletSelectionUM, modifi .padding(horizontal = 8.dp, vertical = 4.dp), ) { Text( - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "From $54.90", + text = stringResourceSafe(R.string.wallet_create_hardware_badge, state.hardwareWalletPrice), style = TangemTheme.typography.caption1, color = TangemTheme.colors.text.accent, ) @@ -150,12 +144,13 @@ private fun WalletBlock( modifier = modifier .fillMaxWidth() .padding(top = 8.dp) + .clip(TangemTheme.shapes.roundedCornersXMedium) .background( color = TangemTheme.colors.background.secondary, shape = TangemTheme.shapes.roundedCornersXMedium, ) - .padding(16.dp) - .clickable(onClick = onClick), + .clickable(onClick = onClick) + .padding(16.dp), ) { Row { Text( @@ -202,16 +197,14 @@ private fun AlreadyHaveTangemWalletBlock( modifier = Modifier .weight(1f) .padding(end = 16.dp), - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "Do you already have Tangem Wallet?", + text = stringResourceSafe(R.string.wallet_create_scan_question), style = TangemTheme.typography.button, color = TangemTheme.colors.text.primary1, ) TangemButton( modifier = Modifier .wrapContentWidth(), - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "Scan Now", + text = stringResourceSafe(R.string.wallet_create_scan_title), onClick = onScanClick, icon = TangemButtonIconPosition.End(iconResId = R.drawable.ic_tangem_24), size = TangemButtonSize.RoundedAction, diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/AddExistingWalletImportComponent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/AddExistingWalletImportComponent.kt new file mode 100644 index 0000000000..a29db42a78 --- /dev/null +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/AddExistingWalletImportComponent.kt @@ -0,0 +1,36 @@ +package com.tangem.features.hotwallet.addexistingwallet.im.port + +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.core.ui.decompose.ComposableContentComponent +import com.tangem.features.hotwallet.addexistingwallet.im.port.ui.AddExistingWalletImportContent +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject + +internal class AddExistingWalletImportComponent @AssistedInject constructor( + @Assisted private val context: AppComponentContext, + @Assisted private val params: Params, +) : ComposableContentComponent, AppComponentContext by context { + private val model: AddExistingWalletImportModel = getOrCreateModel(params) + + @Composable + override fun Content(modifier: Modifier) { + val state by model.uiState.collectAsStateWithLifecycle() + AddExistingWalletImportContent( + state = state, + modifier = modifier, + ) + } + + interface ModelCallbacks { + fun onBackClick() + } + + data class Params( + val callbacks: ModelCallbacks, + ) +} \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/AddExistingWalletImportModel.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/AddExistingWalletImportModel.kt new file mode 100644 index 0000000000..7f39c0e85a --- /dev/null +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/AddExistingWalletImportModel.kt @@ -0,0 +1,26 @@ +package com.tangem.features.hotwallet.addexistingwallet.im.port + +import com.tangem.core.decompose.di.ModelScoped +import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.model.ParamsContainer +import com.tangem.features.hotwallet.addexistingwallet.im.port.entity.AddExistingWalletImportUM +import com.tangem.utils.coroutines.CoroutineDispatcherProvider +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import javax.inject.Inject + +@ModelScoped +internal class AddExistingWalletImportModel @Inject constructor( + paramsContainer: ParamsContainer, + override val dispatchers: CoroutineDispatcherProvider, +) : Model() { + + private val params: AddExistingWalletImportComponent.Params = paramsContainer.require() + + internal val uiState: StateFlow + field = MutableStateFlow( + AddExistingWalletImportUM( + onBackClick = params.callbacks::onBackClick, + ), + ) +} \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/entity/AddExistingWalletImportUM.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/entity/AddExistingWalletImportUM.kt new file mode 100644 index 0000000000..5daf5de360 --- /dev/null +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/entity/AddExistingWalletImportUM.kt @@ -0,0 +1,5 @@ +package com.tangem.features.hotwallet.addexistingwallet.im.port.entity + +internal data class AddExistingWalletImportUM( + val onBackClick: () -> Unit, +) \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/ui/AddExistingWalletImportContent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/ui/AddExistingWalletImportContent.kt new file mode 100644 index 0000000000..4e3fc2638a --- /dev/null +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/im/port/ui/AddExistingWalletImportContent.kt @@ -0,0 +1,47 @@ +package com.tangem.features.hotwallet.addexistingwallet.im.port.ui + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.tangem.core.ui.components.appbar.TangemTopAppBar +import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM +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.im.port.entity.AddExistingWalletImportUM +import com.tangem.core.ui.R + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun AddExistingWalletImportContent(state: AddExistingWalletImportUM, modifier: Modifier = Modifier) { + Column( + modifier = modifier + .background(TangemTheme.colors.background.primary) + .fillMaxSize() + .systemBarsPadding(), + ) { + TangemTopAppBar( + modifier = Modifier + .statusBarsPadding(), + startButton = TopAppBarButtonUM.Back(state.onBackClick), + title = stringResourceSafe(R.string.wallet_import_title), + ) + } +} + +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun PreviewAddExistingWalletImportContent() { + TangemThemePreview { + AddExistingWalletImportContent( + state = AddExistingWalletImportUM( + onBackClick = {}, + ), + ) + } +} \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/AddExistingWalletModel.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/AddExistingWalletModel.kt index abbb917a03..dd9a7da008 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/AddExistingWalletModel.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/AddExistingWalletModel.kt @@ -1,25 +1,41 @@ package com.tangem.features.hotwallet.addexistingwallet.root +import com.arkivanov.decompose.router.stack.StackNavigation +import com.arkivanov.decompose.router.stack.pop +import com.arkivanov.decompose.router.stack.push import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.navigation.Router import com.tangem.features.hotwallet.addexistingwallet.start.AddExistingWalletStartComponent +import com.tangem.features.hotwallet.addexistingwallet.im.port.AddExistingWalletImportComponent +import com.tangem.features.hotwallet.addexistingwallet.root.routing.AddExistingWalletRoute import com.tangem.utils.coroutines.CoroutineDispatcherProvider import javax.inject.Inject @ModelScoped internal class AddExistingWalletModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, + private val router: Router, ) : Model() { val addExistingWalletStartModelCallbacks = AddExistingWalletStartModelCallbacks() + val addExistingWalletImportModelCallbacks = AddExistingWalletImportModelCallbacks() + + val stackNavigation = StackNavigation() inner class AddExistingWalletStartModelCallbacks : AddExistingWalletStartComponent.ModelCallbacks { override fun onBackClick() { - // TODO implement in [REDACTED_TASK_KEY] + router.pop() } override fun onImportPhraseClick() { - // TODO implement in [REDACTED_TASK_KEY] + stackNavigation.push(AddExistingWalletRoute.Import) + } + } + + inner class AddExistingWalletImportModelCallbacks : AddExistingWalletImportComponent.ModelCallbacks { + override fun onBackClick() { + stackNavigation.pop() } } } \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/DefaultAddExistingWalletComponent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/DefaultAddExistingWalletComponent.kt index 4ef6395750..104d2582c2 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/DefaultAddExistingWalletComponent.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/DefaultAddExistingWalletComponent.kt @@ -5,7 +5,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import com.arkivanov.decompose.extensions.compose.subscribeAsState -import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.router.stack.pop import com.tangem.core.decompose.context.AppComponentContext @@ -27,12 +26,11 @@ internal class DefaultAddExistingWalletComponent @AssistedInject constructor( private val model: AddExistingWalletModel = getOrCreateModel(params) - private val stackNavigation = StackNavigation() private val startRoute = AddExistingWalletRoute.Start private val innerStack = childStack( key = "addExistingWalletInnerStack", - source = stackNavigation, + source = model.stackNavigation, serializer = null, initialConfiguration = startRoute, handleBackButton = true, @@ -61,7 +59,7 @@ internal class DefaultAddExistingWalletComponent @AssistedInject constructor( if (isEmptyStack) { router.pop() } else { - stackNavigation.pop() + model.stackNavigation.pop() } } diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/di/AddExistingWalletModule.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/di/AddExistingWalletModule.kt new file mode 100644 index 0000000000..d2019f9f33 --- /dev/null +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/di/AddExistingWalletModule.kt @@ -0,0 +1,45 @@ +package com.tangem.features.hotwallet.addexistingwallet.root.di + +import com.tangem.core.decompose.model.Model +import com.tangem.features.hotwallet.AddExistingWalletComponent +import com.tangem.features.hotwallet.addexistingwallet.root.AddExistingWalletModel +import com.tangem.features.hotwallet.addexistingwallet.root.DefaultAddExistingWalletComponent +import com.tangem.features.hotwallet.addexistingwallet.start.AddExistingWalletStartModel +import com.tangem.features.hotwallet.addexistingwallet.im.port.AddExistingWalletImportModel +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 AddExistingWalletModule + +@Module +@InstallIn(SingletonComponent::class) +internal interface AddExistingWalletModuleBinds { + + @Binds + @Singleton + fun bindAddExistingWalletComponentFactory( + impl: DefaultAddExistingWalletComponent.Factory, + ): AddExistingWalletComponent.Factory + + @Binds + @IntoMap + @ClassKey(AddExistingWalletModel::class) + fun bindAddExistingWalletModel(model: AddExistingWalletModel): Model + + @Binds + @IntoMap + @ClassKey(AddExistingWalletStartModel::class) + fun bindAddExistingWalletStartModel(model: AddExistingWalletStartModel): Model + + @Binds + @IntoMap + @ClassKey(AddExistingWalletImportModel::class) + fun bindAddExistingWalletImportModel(model: AddExistingWalletImportModel): Model +} \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/routing/AddExistingWalletChildFactory.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/routing/AddExistingWalletChildFactory.kt index b9079208c6..4c1e57c968 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/routing/AddExistingWalletChildFactory.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/routing/AddExistingWalletChildFactory.kt @@ -4,6 +4,7 @@ import com.tangem.core.decompose.context.AppComponentContext import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.features.hotwallet.addexistingwallet.root.AddExistingWalletModel import com.tangem.features.hotwallet.addexistingwallet.start.AddExistingWalletStartComponent +import com.tangem.features.hotwallet.addexistingwallet.im.port.AddExistingWalletImportComponent import javax.inject.Inject internal class AddExistingWalletChildFactory @Inject constructor() { @@ -20,6 +21,12 @@ internal class AddExistingWalletChildFactory @Inject constructor() { callbacks = model.addExistingWalletStartModelCallbacks, ), ) + is AddExistingWalletRoute.Import -> AddExistingWalletImportComponent( + context = childContext, + params = AddExistingWalletImportComponent.Params( + callbacks = model.addExistingWalletImportModelCallbacks, + ), + ) } } } \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/routing/AddExistingWalletRoute.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/routing/AddExistingWalletRoute.kt index 56ca941809..1566d1bc74 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/routing/AddExistingWalletRoute.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/routing/AddExistingWalletRoute.kt @@ -7,4 +7,7 @@ internal sealed class AddExistingWalletRoute : Route { @Serializable object Start : AddExistingWalletRoute() + + @Serializable + object Import : AddExistingWalletRoute() } \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/ui/AddExistingWalletContent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/ui/AddExistingWalletContent.kt index 9d3367cbc7..bc43867900 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/ui/AddExistingWalletContent.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/addexistingwallet/root/ui/AddExistingWalletContent.kt @@ -1,12 +1,10 @@ package com.tangem.features.hotwallet.addexistingwallet.root.ui import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import com.arkivanov.decompose.extensions.compose.stack.Children import com.arkivanov.decompose.extensions.compose.stack.animation.slide @@ -18,20 +16,15 @@ import com.tangem.features.hotwallet.addexistingwallet.root.routing.AddExistingW @Composable internal fun AddExistingWalletContent(stackState: ChildStack) { - Column( - modifier = Modifier.Companion + Children( + stack = stackState, + animation = stackAnimation(slide()), + modifier = Modifier .background(color = TangemTheme.colors.background.primary) .fillMaxSize() .imePadding() .systemBarsPadding(), - horizontalAlignment = Alignment.Companion.CenterHorizontally, ) { - Children( - stack = stackState, - animation = stackAnimation(slide()), - modifier = Modifier.weight(1f), - ) { - it.instance.Content(Modifier.weight(1f)) - } + it.instance.Content(Modifier.fillMaxSize()) } } \ 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 a0a2ea6abe..66e907f5d8 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 @@ -7,6 +7,8 @@ import androidx.compose.material3.* 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 @@ -20,19 +22,21 @@ import com.tangem.core.ui.extensions.conditional 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 @Suppress("LongMethod") @OptIn(ExperimentalMaterial3Api::class) @Composable internal fun AddExistingWalletStartContent(state: AddExistingWalletStartUM, modifier: Modifier = Modifier) { Column( - modifier = Modifier + modifier = modifier .background(TangemTheme.colors.background.primary) .fillMaxSize() .systemBarsPadding(), ) { TangemTopAppBar( - modifier = modifier + modifier = Modifier .statusBarsPadding(), startButton = TopAppBarButtonUM.Back(state.onBackClick), title = "Add existing wallet", @@ -50,8 +54,7 @@ internal fun AddExistingWalletStartContent(state: AddExistingWalletStartUM, modi modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp), - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "Import wallet", + text = stringResourceSafe(R.string.wallet_import_seed_navtitle), style = TangemTheme.typography.h2, color = TangemTheme.colors.text.primary1, textAlign = TextAlign.Center, @@ -59,31 +62,35 @@ internal fun AddExistingWalletStartContent(state: AddExistingWalletStartUM, modi OptionBlock( modifier = Modifier .padding(top = 24.dp), - // TODO [REDACTED_TASK_KEY] update and extract this string - title = "Import a recovery phrase", - // TODO [REDACTED_TASK_KEY] update and extract this string - description = "Your 12-word seed phrase to recover your wallet", + title = stringResourceSafe(R.string.wallet_import_seed_title), + description = stringResourceSafe(R.string.wallet_import_seed_description), badge = null, onClick = state.onImportPhraseClick, enabled = true, ) OptionBlock( - // TODO [REDACTED_TASK_KEY] update and extract this string - title = "Scan a Tangem Wallet", - // TODO [REDACTED_TASK_KEY] update and extract this string - description = "Physical cards that securely store your crypto offline.", - badge = null, + title = stringResourceSafe(R.string.wallet_import_scan_title), + description = stringResourceSafe(R.string.wallet_import_scan_description), + badge = { + Icon( + modifier = Modifier + .padding(top = 2.dp) + .size(20.dp), + painter = painterResource(R.drawable.ic_tangem_24), + contentDescription = null, + tint = TangemTheme.colors.icon.secondary, + ) + }, onClick = state.onScanCardClick, enabled = true, ) OptionBlock( - // TODO [REDACTED_TASK_KEY] update and extract this string - title = "Import from Google Drive", - // TODO [REDACTED_TASK_KEY] update and extract this string - description = "Recover an existing wallet stored in your Google Drive backup", + title = stringResourceSafe(R.string.wallet_import_google_drive_title), + description = stringResourceSafe(R.string.wallet_import_google_drive_description), badge = { Box( modifier = Modifier + .padding(horizontal = 4.dp) .background( color = TangemTheme.colors.field.focused, shape = TangemTheme.shapes.roundedCorners8, @@ -91,8 +98,7 @@ internal fun AddExistingWalletStartContent(state: AddExistingWalletStartUM, modi .padding(horizontal = 8.dp, vertical = 4.dp), ) { Text( - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "Coming Soon", + text = stringResourceSafe(R.string.common_coming_soon), style = TangemTheme.typography.caption1, color = TangemTheme.colors.text.tertiary, ) @@ -121,20 +127,21 @@ private fun OptionBlock( modifier = modifier .fillMaxWidth() .padding(top = 8.dp) + .clip(TangemTheme.shapes.roundedCornersXMedium) .background( color = TangemTheme.colors.background.secondary, shape = TangemTheme.shapes.roundedCornersXMedium, ) - .padding(16.dp) .conditional(onClick != null) { onClick?.let { clickableSingle(onClick = it) } ?: Modifier - }, + } + .padding(16.dp), ) { Row { Text( modifier = Modifier - .weight(1f) - .padding(end = 8.dp), + .weight(1f, fill = false) + .padding(end = 4.dp), text = title, style = TangemTheme.typography.subtitle1, color = if (enabled) { @@ -179,16 +186,14 @@ private fun BuyTangemWalletBlock(onScanClick: () -> Unit, modifier: Modifier = M modifier = Modifier .weight(1f) .padding(end = 16.dp), - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "Want to purchase a Tangem Wallet?", + text = stringResourceSafe(R.string.wallet_import_buy_question), style = TangemTheme.typography.button, color = TangemTheme.colors.text.primary1, ) PrimaryButton( modifier = Modifier .wrapContentWidth(), - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "Buy Now", + text = stringResourceSafe(R.string.wallet_import_buy_title), onClick = onScanClick, size = TangemButtonSize.RoundedAction, colors = TangemButtonsDefaults.secondaryButtonColors, diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt index 629e6c0a74..6491acb916 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/CreateMobileWalletModel.kt @@ -2,6 +2,7 @@ package com.tangem.features.hotwallet.createmobilewallet import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model +import com.tangem.core.decompose.navigation.Router import com.tangem.features.hotwallet.createmobilewallet.entity.CreateMobileWalletUM import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.flow.MutableStateFlow @@ -11,12 +12,13 @@ import javax.inject.Inject @ModelScoped internal class CreateMobileWalletModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, + private val router: Router, ) : Model() { internal val uiState: StateFlow field = MutableStateFlow( CreateMobileWalletUM( - onBackClick = { /* [REDACTED_TODO_COMMENT] */ }, + onBackClick = { router.pop() }, onCreateClick = ::onCreateClick, ), ) diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/di/CreateMobileWalletModule.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/di/CreateMobileWalletModule.kt new file mode 100644 index 0000000000..d34f94f439 --- /dev/null +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/di/CreateMobileWalletModule.kt @@ -0,0 +1,33 @@ +package com.tangem.features.hotwallet.createmobilewallet.di + +import com.tangem.core.decompose.model.Model +import com.tangem.features.hotwallet.CreateMobileWalletComponent +import com.tangem.features.hotwallet.createmobilewallet.CreateMobileWalletModel +import com.tangem.features.hotwallet.createmobilewallet.DefaultCreateMobileWalletComponent +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 CreateMobileWalletModule + +@Module +@InstallIn(SingletonComponent::class) +internal interface CreateMobileWalletModuleBinds { + + @Binds + @Singleton + fun bindCreateMobileWalletComponentFactory( + impl: DefaultCreateMobileWalletComponent.Factory, + ): CreateMobileWalletComponent.Factory + + @Binds + @IntoMap + @ClassKey(CreateMobileWalletModel::class) + fun bindCreateMobileWalletModel(model: CreateMobileWalletModel): Model +} \ No newline at end of file diff --git a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt index 6f3a77c019..5de3f84a92 100644 --- a/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt +++ b/features/hot-wallet/impl/src/main/kotlin/com/tangem/features/hotwallet/createmobilewallet/ui/CreateMobileWalletContent.kt @@ -15,6 +15,7 @@ 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.extensions.TextReference +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.createmobilewallet.entity.CreateMobileWalletUM @@ -24,13 +25,13 @@ import com.tangem.features.hotwallet.createmobilewallet.entity.CreateMobileWalle @Composable internal fun CreateMobileWalletContent(state: CreateMobileWalletUM, modifier: Modifier = Modifier) { Column( - modifier = Modifier + modifier = modifier .background(TangemTheme.colors.background.primary) .fillMaxSize() .systemBarsPadding(), ) { TangemTopAppBar( - modifier = modifier + modifier = Modifier .statusBarsPadding(), startButton = TopAppBarButtonUM.Back(state.onBackClick), title = TextReference.EMPTY, @@ -59,8 +60,7 @@ internal fun CreateMobileWalletContent(state: CreateMobileWalletUM, modifier: Mo top = 20.dp, end = 16.dp, ), - // TODO [REDACTED_TASK_KEY] update and extract this string - text = "Create Mobile Wallet", + text = stringResourceSafe(R.string.hw_create_title), style = TangemTheme.typography.h2, color = TangemTheme.colors.text.primary1, textAlign = TextAlign.Center, @@ -68,19 +68,15 @@ internal fun CreateMobileWalletContent(state: CreateMobileWalletUM, modifier: Mo FeatureBlock( modifier = Modifier .padding(top = 32.dp), - // TODO [REDACTED_TASK_KEY] update and extract this string - title = "Keys are stored in the app", - // TODO [REDACTED_TASK_KEY] update and extract this string - description = "Get notified of incoming transactions", + title = stringResourceSafe(R.string.hw_create_keys_title), + description = stringResourceSafe(R.string.hw_create_keys_description), iconRes = R.drawable.ic_lock_24, ) FeatureBlock( modifier = Modifier .padding(top = 24.dp), - // TODO [REDACTED_TASK_KEY] update and extract this string - title = "Seed phrase backup", - // TODO [REDACTED_TASK_KEY] update and extract this string - description = "Stay up to date with the latest features and news", + title = stringResourceSafe(R.string.hw_create_seed_title), + description = stringResourceSafe(R.string.hw_create_seed_description), iconRes = R.drawable.ic_settings_24, ) }