From f0c6ab722f5bd6a27c097c096e6625672932730a Mon Sep 17 00:00:00 2001 From: lilbonekit Date: Wed, 14 Jan 2026 20:51:27 +0200 Subject: [PATCH 1/4] chore: remove duplicate resources (#282) --- common/src/commonMain/composeResources/values-cs/strings.xml | 1 - common/src/commonMain/composeResources/values-de/strings.xml | 1 - common/src/commonMain/composeResources/values-es/strings.xml | 1 - common/src/commonMain/composeResources/values-fr/strings.xml | 1 - common/src/commonMain/composeResources/values-he/strings.xml | 1 - common/src/commonMain/composeResources/values-it/strings.xml | 1 - common/src/commonMain/composeResources/values-ja/strings.xml | 1 - common/src/commonMain/composeResources/values-ko/strings.xml | 1 - common/src/commonMain/composeResources/values-nl/strings.xml | 1 - .../src/commonMain/composeResources/values-pt-rBR/strings.xml | 1 - common/src/commonMain/composeResources/values-ro/strings.xml | 1 - common/src/commonMain/composeResources/values-ru/strings.xml | 1 - common/src/commonMain/composeResources/values-uk/strings.xml | 1 - common/src/commonMain/composeResources/values-vi/strings.xml | 1 - common/src/commonMain/composeResources/values-zh/strings.xml | 1 - common/src/commonMain/composeResources/values/strings.xml | 3 +-- 16 files changed, 1 insertion(+), 17 deletions(-) diff --git a/common/src/commonMain/composeResources/values-cs/strings.xml b/common/src/commonMain/composeResources/values-cs/strings.xml index 895e83ea7..27143b90d 100644 --- a/common/src/commonMain/composeResources/values-cs/strings.xml +++ b/common/src/commonMain/composeResources/values-cs/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support Své mince uvidíte zde You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. Než budete moci odesílat nebo přijímat peníze, budete si muset zálohovat frázi pro obnovení, ale peněženku si zatím můžete vyzkoušet. K přihlášení do peněženky budete potřebovat PIN. Tento PIN zajišťuje peněženku pouze na tomto zařízení. K obnovení této peněženky budete potřebovat frázi pro obnovení. diff --git a/common/src/commonMain/composeResources/values-de/strings.xml b/common/src/commonMain/composeResources/values-de/strings.xml index 5aa3b5908..62f05c97b 100644 --- a/common/src/commonMain/composeResources/values-de/strings.xml +++ b/common/src/commonMain/composeResources/values-de/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support Deine Coins wirst du hier sehen You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. Du wirst deine PIN benötigen, um dich in deinem Wallet anzumelden. Diese PIN sichert dein Wallet nur auf diesem Gerät. Du wirst deine Wiederherstellungs-Phrase benötigen, um dieses Wallet wiederherstellen zu können diff --git a/common/src/commonMain/composeResources/values-es/strings.xml b/common/src/commonMain/composeResources/values-es/strings.xml index 15b6266ad..2231d2436 100644 --- a/common/src/commonMain/composeResources/values-es/strings.xml +++ b/common/src/commonMain/composeResources/values-es/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support Verá sus monedas aquí You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. Necesitará su PIN para iniciar sesión en su cartera. Dicho PIN protege la cartera únicamente en este dispositivo. Necesitará su frase de recuperación para restaurar esta cartera. diff --git a/common/src/commonMain/composeResources/values-fr/strings.xml b/common/src/commonMain/composeResources/values-fr/strings.xml index c0055d32c..69cddf77a 100644 --- a/common/src/commonMain/composeResources/values-fr/strings.xml +++ b/common/src/commonMain/composeResources/values-fr/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support Vous verrez vos pièces ici You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. Vous aurez besoin de votre code PIN pour vous connecter à votre portefeuille. Ce code PIN sécurise le portefeuille sur cet appareil uniquement. Vous aurez besoin de votre phrase de récupération pour restaurer ce portefeuille. diff --git a/common/src/commonMain/composeResources/values-he/strings.xml b/common/src/commonMain/composeResources/values-he/strings.xml index 89d734fc9..89cad9545 100644 --- a/common/src/commonMain/composeResources/values-he/strings.xml +++ b/common/src/commonMain/composeResources/values-he/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support You will see your coins here You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. You'll need your PIN to log in to your wallet. This PIN secures the wallet on this device only. You'll need your recovery phrase to restore this wallet diff --git a/common/src/commonMain/composeResources/values-it/strings.xml b/common/src/commonMain/composeResources/values-it/strings.xml index 94ee0e691..61c7c375d 100644 --- a/common/src/commonMain/composeResources/values-it/strings.xml +++ b/common/src/commonMain/composeResources/values-it/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support I tuoi coin appariranno qui You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. Avrai bisogno del tuo PIN per accedere al wallet. Questo PIN protegge il tuo wallet solo su questo dispositivo. Avrai bisogno della tua recovery phrase per ripristinare il wallet diff --git a/common/src/commonMain/composeResources/values-ja/strings.xml b/common/src/commonMain/composeResources/values-ja/strings.xml index 4a2056d4e..2edec6622 100644 --- a/common/src/commonMain/composeResources/values-ja/strings.xml +++ b/common/src/commonMain/composeResources/values-ja/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support コインがここに表示されます You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. 送受信を行う前にリカバリーフレーズのバックアップが必要ですが、ウォレットの中身をいま確認することはできます。 PINがないとウォレットにログインできません。設定したPINはこのデバイス上でのみウォレットを保護します。 このウォレットの復元にはリカバリーフレーズが必要です diff --git a/common/src/commonMain/composeResources/values-ko/strings.xml b/common/src/commonMain/composeResources/values-ko/strings.xml index 86ef30a14..50d286580 100644 --- a/common/src/commonMain/composeResources/values-ko/strings.xml +++ b/common/src/commonMain/composeResources/values-ko/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support 여기에서 코인을 볼 수 있습니다. You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. 지갑에 로그인하려면 PIN이 필요합니다. 이 PIN은 이 기기에서만 지갑을 보호합니다. 이 지갑을 복구하려면 복구 문구가 필요합니다. diff --git a/common/src/commonMain/composeResources/values-nl/strings.xml b/common/src/commonMain/composeResources/values-nl/strings.xml index e80b747a4..3c63a713f 100644 --- a/common/src/commonMain/composeResources/values-nl/strings.xml +++ b/common/src/commonMain/composeResources/values-nl/strings.xml @@ -1788,7 +1788,6 @@ You will receive an email from Blockstream support Je munten verschijnen hier You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. Je PIN is nodig om in te loggen op je wallet. Deze PIN beveiligt de wallet alleen op dit apparaat. Je hebt je herstelzin nodig om deze wallet te herstellen diff --git a/common/src/commonMain/composeResources/values-pt-rBR/strings.xml b/common/src/commonMain/composeResources/values-pt-rBR/strings.xml index 651da7722..c34f2c390 100644 --- a/common/src/commonMain/composeResources/values-pt-rBR/strings.xml +++ b/common/src/commonMain/composeResources/values-pt-rBR/strings.xml @@ -1789,7 +1789,6 @@ Você receberá um e-mail do suporte da Blockstream Suas moedas aparecerão aqui Você deixará de receber notificações push para esta conta Lightning, porém, elas são necessárias para que sua conta Lightning receba e envie de forma confiável. - Você ainda não tem nenhum ativo. Para enviar ou receber fundos é necessário antes realizar o backup da sua carteira. O PIN é necessário para você acessar sua carteira. Este PIN protege a carteira somente neste dispositivo. Você vai precisar da sua frase de recuperação para restaurar esta carteira diff --git a/common/src/commonMain/composeResources/values-ro/strings.xml b/common/src/commonMain/composeResources/values-ro/strings.xml index de3d8a954..1d0263f94 100644 --- a/common/src/commonMain/composeResources/values-ro/strings.xml +++ b/common/src/commonMain/composeResources/values-ro/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support You will see your coins here You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. Va trebui să setați un PIN pentru a vă loga in portofel. PIN-ul este valabil doar pentru acest dispozitiv. You'll need your recovery phrase to restore this wallet diff --git a/common/src/commonMain/composeResources/values-ru/strings.xml b/common/src/commonMain/composeResources/values-ru/strings.xml index 6cad57584..ddfd08c79 100644 --- a/common/src/commonMain/composeResources/values-ru/strings.xml +++ b/common/src/commonMain/composeResources/values-ru/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support Здесь вы увидите свои монеты You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. Вам понадобится PIN-код, чтобы войти в свой кошелек. Этот PIN-код защищает кошелек только на этом устройстве. Вам понадобится фраза восстановления, чтобы восстановить этот кошелек diff --git a/common/src/commonMain/composeResources/values-uk/strings.xml b/common/src/commonMain/composeResources/values-uk/strings.xml index 08a02ae6a..a44d8050a 100644 --- a/common/src/commonMain/composeResources/values-uk/strings.xml +++ b/common/src/commonMain/composeResources/values-uk/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support Ви побачите свої монети тут You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. Вам знадобиться PIN-код, щоб увійти в свій гаманець. Цей PIN-код захищає гаманець тільки на цьому пристрої. Вам знадобиться фраза відновлення, щоб відновити цей гаманець diff --git a/common/src/commonMain/composeResources/values-vi/strings.xml b/common/src/commonMain/composeResources/values-vi/strings.xml index 4b41af4a9..f574ac9a1 100644 --- a/common/src/commonMain/composeResources/values-vi/strings.xml +++ b/common/src/commonMain/composeResources/values-vi/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support You will see your coins here You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. You'll need your PIN to log in to your wallet. This PIN secures the wallet on this device only. You'll need your recovery phrase to restore this wallet diff --git a/common/src/commonMain/composeResources/values-zh/strings.xml b/common/src/commonMain/composeResources/values-zh/strings.xml index 5472b96a7..0430ac4bd 100644 --- a/common/src/commonMain/composeResources/values-zh/strings.xml +++ b/common/src/commonMain/composeResources/values-zh/strings.xml @@ -1789,7 +1789,6 @@ You will receive an email from Blockstream support 您会在这里看到您的代币 You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. 您需要PIN才能登录钱包。该PIN仅用于保护此设备上的钱包。 您需要助记词才能恢复此钱包 diff --git a/common/src/commonMain/composeResources/values/strings.xml b/common/src/commonMain/composeResources/values/strings.xml index 1c68bf528..933eef822 100644 --- a/common/src/commonMain/composeResources/values/strings.xml +++ b/common/src/commonMain/composeResources/values/strings.xml @@ -1800,7 +1800,6 @@ You will receive an email from Blockstream support You will see your coins here You will stop receiving push notifications for this lightning account, but they are necessary for your lightning account to receive and send reliably. - You you don't have any assets yet. You'll need to back up your recovery phrase before you can send or receive funds, but you can still check out the wallet for now. You'll need your PIN to log in to your wallet. This PIN secures the wallet on this device only. You'll need your recovery phrase to restore this wallet @@ -1877,7 +1876,7 @@ Enable push notifications for seamless lightning payments. No need to keep your app open to receive. By using Blockstream App, you agree to the Terms of Service and Privacy Policy Setup Mobile Wallet - Setup Hardware Wallet + Setup Hardware Wallet Security Level %1$s Transfer your funds Transfer your funds from your old wallet to your new Jade wallet for maximum security. From 68c5b2a0077ed93d002a335524ae4165ca34a6b0 Mon Sep 17 00:00:00 2001 From: lilbonekit Date: Wed, 14 Jan 2026 20:52:57 +0200 Subject: [PATCH 2/4] fix: add scroll for small screens in security level screen (#272) --- .../blockstream/compose/sheets/SecurityLevelBottomSheet.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compose/src/commonMain/kotlin/com/blockstream/compose/sheets/SecurityLevelBottomSheet.kt b/compose/src/commonMain/kotlin/com/blockstream/compose/sheets/SecurityLevelBottomSheet.kt index 4dd0f74f6..a2ab5f6a2 100644 --- a/compose/src/commonMain/kotlin/com/blockstream/compose/sheets/SecurityLevelBottomSheet.kt +++ b/compose/src/commonMain/kotlin/com/blockstream/compose/sheets/SecurityLevelBottomSheet.kt @@ -7,6 +7,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.SegmentedButton @@ -111,7 +113,10 @@ fun SecurityLevelBottomSheet( GreenColumn( padding = 0, space = 32, - modifier = Modifier.padding(horizontal = 16.dp).fillMaxWidth(), + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally, ) { From 79d164012415e45a3ceae2e159d1190a6fb2ea29 Mon Sep 17 00:00:00 2001 From: lilbonekit Date: Wed, 14 Jan 2026 20:55:19 +0200 Subject: [PATCH 3/4] fix: enforce PIN setup after manual backup (#291) --- .../models/recovery/RecoveryCheckViewModel.kt | 19 ++++- .../settings/WalletSettingsViewModel.kt | 12 ++- .../common/navigation/Destinations.kt | 5 +- .../recovery/RecoverySuccessScreen.android.kt | 15 ++++ .../blockstream/compose/navigation/Router.kt | 19 ++++- .../screens/recovery/RecoverySuccessScreen.kt | 80 +++++++++++++++++++ 6 files changed, 142 insertions(+), 8 deletions(-) create mode 100644 compose/src/androidMain/kotlin/com/blockstream/compose/screens/recovery/RecoverySuccessScreen.android.kt create mode 100644 compose/src/commonMain/kotlin/com/blockstream/compose/screens/recovery/RecoverySuccessScreen.kt diff --git a/common/src/commonMain/kotlin/com/blockstream/common/models/recovery/RecoveryCheckViewModel.kt b/common/src/commonMain/kotlin/com/blockstream/common/models/recovery/RecoveryCheckViewModel.kt index b30c6e716..abe947856 100644 --- a/common/src/commonMain/kotlin/com/blockstream/common/models/recovery/RecoveryCheckViewModel.kt +++ b/common/src/commonMain/kotlin/com/blockstream/common/models/recovery/RecoveryCheckViewModel.kt @@ -93,7 +93,19 @@ class RecoveryCheckViewModel(setupArgs: SetupArgs) : RecoveryCheckViewModelAbstr if (setupArgs.greenWallet == null) { postSideEffect(SideEffects.NavigateTo(NavigateDestinations.SetPin(setupArgs = setupArgs.pageOne()))) } else if (setupArgs.greenWallet.isRecoveryConfirmed == false) { - recoveryConfirmed() + recoveryConfirmed { + // Clear navigation stack so ChangePin doesn't go back to RecoveryCheck + postSideEffect(SideEffects.NavigateToRoot()) + + postSideEffect( + SideEffects.NavigateTo( + NavigateDestinations.ChangePin( + greenWallet = greenWallet, + isRecoveryConfirmation = true + ) + ) + ) + } } else { postSideEffect( SideEffects.NavigateTo( @@ -120,15 +132,16 @@ class RecoveryCheckViewModel(setupArgs: SetupArgs) : RecoveryCheckViewModelAbstr } } - private fun recoveryConfirmed() { + private fun recoveryConfirmed(onSuccess: () -> Unit) { doAsync({ greenWallet.isRecoveryConfirmed = true database.updateWallet(greenWallet) }, onSuccess = { - postSideEffect(SideEffects.NavigateToRoot()) + onSuccess() }) } + companion object : Loggable() { const val RecoveryPhraseChecks = 4 const val WORDS_PER_PAGE = 6 diff --git a/common/src/commonMain/kotlin/com/blockstream/common/models/settings/WalletSettingsViewModel.kt b/common/src/commonMain/kotlin/com/blockstream/common/models/settings/WalletSettingsViewModel.kt index d0136f091..62f89cf27 100644 --- a/common/src/commonMain/kotlin/com/blockstream/common/models/settings/WalletSettingsViewModel.kt +++ b/common/src/commonMain/kotlin/com/blockstream/common/models/settings/WalletSettingsViewModel.kt @@ -102,6 +102,7 @@ enum class WalletSettingsSection { abstract class WalletSettingsViewModelAbstract( greenWallet: GreenWallet, val section: WalletSettingsSection, + val isRecoveryConfirmation: Boolean = false ) : GreenViewModel(greenWalletOrNull = greenWallet) { override fun screenName(): String = when (section) { @@ -118,8 +119,9 @@ abstract class WalletSettingsViewModelAbstract( class WalletSettingsViewModel( greenWallet: GreenWallet, section: WalletSettingsSection, - private val network: Network? = null -) : WalletSettingsViewModelAbstract(greenWallet = greenWallet, section = section) { + private val network: Network? = null, + isRecoveryConfirmation: Boolean = false +) : WalletSettingsViewModelAbstract(greenWallet = greenWallet, section = section, isRecoveryConfirmation = isRecoveryConfirmation) { private val createAccountUseCase: CreateAccountUseCase by inject() private val setBiometricsUseCase: SetBiometricsUseCase by inject() private val setPinUseCase: SetPinUseCase by inject() @@ -879,7 +881,11 @@ class WalletSettingsViewModel( wallet = greenWallet ) }, onSuccess = { - postSideEffect(SideEffects.NavigateBack()) + if (isRecoveryConfirmation) { + postSideEffect(SideEffects.NavigateTo(NavigateDestinations.RecoverySuccess(greenWallet = greenWallet, isRecoveryConfirmation = true))) + } else { + postSideEffect(SideEffects.NavigateBack()) + } }) } diff --git a/common/src/commonMain/kotlin/com/blockstream/common/navigation/Destinations.kt b/common/src/commonMain/kotlin/com/blockstream/common/navigation/Destinations.kt index 7bd2e3095..fac347733 100644 --- a/common/src/commonMain/kotlin/com/blockstream/common/navigation/Destinations.kt +++ b/common/src/commonMain/kotlin/com/blockstream/common/navigation/Destinations.kt @@ -110,6 +110,9 @@ sealed class NavigateDestinations : NavigateDestination() { @Serializable data class RecoveryCheck(val setupArgs: SetupArgs) : NavigateDestination() + @Serializable + data class RecoverySuccess(val greenWallet: GreenWallet, val isRecoveryConfirmation: Boolean = false) : NavigateDestination() + @Serializable data class SetPin(val setupArgs: SetupArgs) : NavigateDestination() @@ -258,7 +261,7 @@ sealed class NavigateDestinations : NavigateDestination() { data class WatchOnly(val greenWallet: GreenWallet) : NavigateDestination() @Serializable - data class ChangePin(val greenWallet: GreenWallet) : NavigateDestination() + data class ChangePin(val greenWallet: GreenWallet, val isRecoveryConfirmation: Boolean = false) : NavigateDestination() @Serializable data class SystemMessage(val greenWallet: GreenWallet, val network: Network, val message: String) : NavigateDestination() diff --git a/compose/src/androidMain/kotlin/com/blockstream/compose/screens/recovery/RecoverySuccessScreen.android.kt b/compose/src/androidMain/kotlin/com/blockstream/compose/screens/recovery/RecoverySuccessScreen.android.kt new file mode 100644 index 000000000..759c51b6b --- /dev/null +++ b/compose/src/androidMain/kotlin/com/blockstream/compose/screens/recovery/RecoverySuccessScreen.android.kt @@ -0,0 +1,15 @@ +package com.blockstream.compose.screens.recovery + +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import com.blockstream.common.extensions.previewWallet +import com.blockstream.compose.GreenAndroidPreview + +@Composable +@Preview +fun RecoverySuccessScreenPreview() { + GreenAndroidPreview { + RecoverySuccessScreen(greenWallet = previewWallet(), onDone = {}) + } +} + diff --git a/compose/src/commonMain/kotlin/com/blockstream/compose/navigation/Router.kt b/compose/src/commonMain/kotlin/com/blockstream/compose/navigation/Router.kt index 1dbef45d0..e54da18d5 100644 --- a/compose/src/commonMain/kotlin/com/blockstream/compose/navigation/Router.kt +++ b/compose/src/commonMain/kotlin/com/blockstream/compose/navigation/Router.kt @@ -146,6 +146,7 @@ import com.blockstream.compose.screens.receive.ReceiveScreen import com.blockstream.compose.screens.recovery.RecoveryCheckScreen import com.blockstream.compose.screens.recovery.RecoveryIntroScreen import com.blockstream.compose.screens.recovery.RecoveryPhraseScreen +import com.blockstream.compose.screens.recovery.RecoverySuccessScreen import com.blockstream.compose.screens.recovery.RecoveryWordsScreen import com.blockstream.compose.screens.send.BumpScreen import com.blockstream.compose.screens.send.RedepositScreen @@ -299,6 +300,21 @@ fun Router( ) }) } + appComposable { + val args = it.toRoute() + RecoverySuccessScreen( + greenWallet = args.greenWallet, + onDone = { + if (args.isRecoveryConfirmation) { + navController.navigate(NavigateDestinations.WalletOverview(greenWallet = args.greenWallet)) { + popUpTo(0) { inclusive = true } + } + } else { + navController.navigate(NavigateDestinations.Home) + } + } + ) + } appComposable { val args = it.toRoute() PinScreen(viewModel { PinViewModel(setupArgs = args.setupArgs) }) @@ -430,7 +446,8 @@ fun Router( WalletSettingsViewModel( greenWallet = args.greenWallet, section = WalletSettingsSection.ChangePin, - network = null + network = null, + isRecoveryConfirmation = args.isRecoveryConfirmation ) }) } diff --git a/compose/src/commonMain/kotlin/com/blockstream/compose/screens/recovery/RecoverySuccessScreen.kt b/compose/src/commonMain/kotlin/com/blockstream/compose/screens/recovery/RecoverySuccessScreen.kt new file mode 100644 index 000000000..5efa7a3ca --- /dev/null +++ b/compose/src/commonMain/kotlin/com/blockstream/compose/screens/recovery/RecoverySuccessScreen.kt @@ -0,0 +1,80 @@ +package com.blockstream.compose.screens.recovery + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import blockstream_green.common.generated.resources.Res +import blockstream_green.common.generated.resources.id_done +import blockstream_green.common.generated.resources.id_great_you_successfully_backed +import blockstream_green.common.generated.resources.id_keep_your_recovery_phrase_fully +import com.blockstream.common.data.GreenWallet +import com.blockstream.compose.components.GreenButton +import com.blockstream.compose.components.GreenButtonSize +import com.blockstream.compose.components.Rive +import com.blockstream.compose.components.RiveAnimation +import org.jetbrains.compose.resources.stringResource + +@Composable +fun RecoverySuccessScreen( + greenWallet: GreenWallet, + onDone: () -> Unit +) { + Column( + modifier = Modifier + .fillMaxSize() + .systemBarsPadding() + .padding(horizontal = 24.dp), + verticalArrangement = Arrangement.SpaceBetween, + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(Modifier.height(32.dp)) + + Column( + modifier = Modifier.weight(1f), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Rive( + riveAnimation = RiveAnimation.ROCKET, + ) + + Spacer(Modifier.height(24.dp)) + + Text( + text = stringResource(Res.string.id_great_you_successfully_backed), + style = MaterialTheme.typography.titleLarge, + textAlign = TextAlign.Center + ) + + Spacer(Modifier.height(12.dp)) + + Text( + text = stringResource(Res.string.id_keep_your_recovery_phrase_fully), + style = MaterialTheme.typography.bodyLarge, + textAlign = TextAlign.Center + ) + } + + GreenButton( + text = stringResource(Res.string.id_done), + size = GreenButtonSize.BIG, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 16.dp), + onClick = onDone + ) + } +} + From c77875ea0933d0ed53173626f2300af67c9aba09 Mon Sep 17 00:00:00 2001 From: lilbonekit Date: Thu, 15 Jan 2026 11:30:23 +0200 Subject: [PATCH 4/4] fix: refactor recovery check navigation logic for clarity --- .../models/recovery/RecoveryCheckViewModel.kt | 95 ++++++++++++------- 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/common/src/commonMain/kotlin/com/blockstream/common/models/recovery/RecoveryCheckViewModel.kt b/common/src/commonMain/kotlin/com/blockstream/common/models/recovery/RecoveryCheckViewModel.kt index abe947856..2a5c46796 100644 --- a/common/src/commonMain/kotlin/com/blockstream/common/models/recovery/RecoveryCheckViewModel.kt +++ b/common/src/commonMain/kotlin/com/blockstream/common/models/recovery/RecoveryCheckViewModel.kt @@ -87,47 +87,71 @@ class RecoveryCheckViewModel(setupArgs: SetupArgs) : RecoveryCheckViewModelAbstr override suspend fun handleEvent(event: Event) { super.handleEvent(event) - if (event is LocalEvents.SelectWord) { - if (correctWord == event.word) { - if (isLastPage) { - if (setupArgs.greenWallet == null) { - postSideEffect(SideEffects.NavigateTo(NavigateDestinations.SetPin(setupArgs = setupArgs.pageOne()))) - } else if (setupArgs.greenWallet.isRecoveryConfirmed == false) { - recoveryConfirmed { - // Clear navigation stack so ChangePin doesn't go back to RecoveryCheck - postSideEffect(SideEffects.NavigateToRoot()) - - postSideEffect( - SideEffects.NavigateTo( - NavigateDestinations.ChangePin( - greenWallet = greenWallet, - isRecoveryConfirmation = true - ) - ) - ) - } - } else { - postSideEffect( - SideEffects.NavigateTo( - NavigateDestinations.ReviewAddAccount( - setupArgs = setupArgs.pageOne() - ) - ) - ) - } - } else { + + if (event !is LocalEvents.SelectWord) return + + if (correctWord != event.word) { + handleIncorrectWord() + return + } + + if (!isLastPage) { + navigateToNextPage() + return + } + + handleLastPageNavigation() + } + + private fun handleIncorrectWord() { + countly.recoveryPhraseCheckFailed(page = setupArgs.page) + postSideEffect(SideEffects.Snackbar(StringHolder.create(Res.string.id_wrong_choice_check_your))) + postSideEffect(SideEffects.NavigateBack()) + } + + private fun navigateToNextPage() { + postSideEffect( + SideEffects.NavigateTo( + NavigateDestinations.RecoveryCheck( + setupArgs = setupArgs.nextPage() + ) + ) + ) + } + + private fun handleLastPageNavigation() { + when { + setupArgs.greenWallet == null -> { + postSideEffect( + SideEffects.NavigateTo( + NavigateDestinations.SetPin(setupArgs = setupArgs.pageOne()) + ) + ) + } + + !setupArgs.greenWallet.isRecoveryConfirmed -> { + recoveryConfirmed { + // Clear navigation stack so ChangePin doesn't go back to RecoveryCheck + postSideEffect(SideEffects.NavigateToRoot()) postSideEffect( SideEffects.NavigateTo( - NavigateDestinations.RecoveryCheck( - setupArgs = setupArgs.nextPage() + NavigateDestinations.ChangePin( + greenWallet = greenWallet, + isRecoveryConfirmation = true ) ) ) } - } else { - countly.recoveryPhraseCheckFailed(page = setupArgs.page) - postSideEffect(SideEffects.Snackbar(StringHolder.create(Res.string.id_wrong_choice_check_your))) - postSideEffect(SideEffects.NavigateBack()) + } + + else -> { + postSideEffect( + SideEffects.NavigateTo( + NavigateDestinations.ReviewAddAccount( + setupArgs = setupArgs.pageOne() + ) + ) + ) } } } @@ -141,7 +165,6 @@ class RecoveryCheckViewModel(setupArgs: SetupArgs) : RecoveryCheckViewModelAbstr }) } - companion object : Loggable() { const val RecoveryPhraseChecks = 4 const val WORDS_PER_PAGE = 6