From 1b796a1e8ad6507f2a9e4e864adb589eaa3fbbb7 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Thu, 2 Apr 2026 14:09:25 -0300 Subject: [PATCH 01/12] feat: add transfer from savings button on empty spending screen --- app/src/main/java/to/bitkit/ui/ContentView.kt | 8 ++++ .../screens/wallets/SpendingWalletScreen.kt | 46 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/app/src/main/java/to/bitkit/ui/ContentView.kt b/app/src/main/java/to/bitkit/ui/ContentView.kt index 073fb1767..11d9ab25c 100644 --- a/app/src/main/java/to/bitkit/ui/ContentView.kt +++ b/app/src/main/java/to/bitkit/ui/ContentView.kt @@ -815,6 +815,7 @@ private fun NavGraphBuilder.home( } composableWithDefaultTransitions { val hasSeenSavingsIntro by settingsViewModel.hasSeenSavingsIntro.collectAsStateWithLifecycle() + val hasSeenSpendingIntro by settingsViewModel.hasSeenSpendingIntro.collectAsStateWithLifecycle() val lightningState by walletViewModel.lightningState.collectAsStateWithLifecycle() val lightningActivities by activityListViewModel.lightningActivities.collectAsStateWithLifecycle() @@ -831,6 +832,13 @@ private fun NavGraphBuilder.home( navController.navigateToTransferSavingsAvailability() } }, + onTransferFromSavingsClick = { + if (!hasSeenSpendingIntro) { + navController.navigateToTransferSpendingIntro() + } else { + navController.navigateToTransferSpendingAmount() + } + }, onBackClick = { navController.popBackStack() }, ) } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index b10954e85..05d946078 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -56,6 +56,7 @@ fun SpendingWalletScreen( onActivityItemClick: (String) -> Unit, onEmptyActivityRowClick: () -> Unit, onTransferToSavingsClick: () -> Unit, + onTransferFromSavingsClick: () -> Unit, onBackClick: () -> Unit, balances: BalanceState = LocalBalances.current, ) { @@ -69,6 +70,9 @@ fun SpendingWalletScreen( val hasChannels = channels.isNotEmpty() mutableStateOf(hasLnBalance && hasChannels) } + val canTransferFromSavings by remember(showEmptyState, balances.totalOnchainSats) { + mutableStateOf(showEmptyState && balances.totalOnchainSats > 0uL) + } Box( modifier = Modifier @@ -112,6 +116,23 @@ fun SpendingWalletScreen( ) } + if (canTransferFromSavings) { + Spacer(modifier = Modifier.height(32.dp)) + + SecondaryButton( + onClick = onTransferFromSavingsClick, + text = stringResource(R.string.lightning__funding__button1), + icon = { + Icon( + painter = painterResource(R.drawable.ic_transfer), + contentDescription = null, + modifier = Modifier.size(16.dp), + ) + }, + modifier = Modifier.testTag("TransferFromSavings") + ) + } + if (!showEmptyState) { Spacer(modifier = Modifier.height(32.dp)) @@ -163,6 +184,7 @@ private fun Preview() { onActivityItemClick = {}, onEmptyActivityRowClick = {}, onTransferToSavingsClick = {}, + onTransferFromSavingsClick = {}, onBackClick = {}, balances = BalanceState(totalLightningSats = 50_000u), ) @@ -183,6 +205,7 @@ private fun PreviewTransfer() { onActivityItemClick = {}, onEmptyActivityRowClick = {}, onTransferToSavingsClick = {}, + onTransferFromSavingsClick = {}, onBackClick = {}, balances = BalanceState( totalLightningSats = 50_000u, @@ -206,6 +229,7 @@ private fun PreviewNoActivity() { onActivityItemClick = {}, onEmptyActivityRowClick = {}, onTransferToSavingsClick = {}, + onTransferFromSavingsClick = {}, onBackClick = {}, balances = BalanceState(totalLightningSats = 50_000u), ) @@ -226,7 +250,29 @@ private fun PreviewEmpty() { onActivityItemClick = {}, onEmptyActivityRowClick = {}, onTransferToSavingsClick = {}, + onTransferFromSavingsClick = {}, + onBackClick = {}, + ) + TabBar() + } + } +} + +@Preview(showSystemUi = true) +@Composable +private fun PreviewEmptyWithSavings() { + AppThemeSurface { + Box { + SpendingWalletScreen( + channels = persistentListOf(), + lightningActivities = persistentListOf(), + onAllActivityButtonClick = {}, + onActivityItemClick = {}, + onEmptyActivityRowClick = {}, + onTransferToSavingsClick = {}, + onTransferFromSavingsClick = {}, onBackClick = {}, + balances = BalanceState(totalOnchainSats = 100_000u), ) TabBar() } From 3f35635cb09e60edf2a9334c67af06d55998f002 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Thu, 2 Apr 2026 14:11:08 -0300 Subject: [PATCH 02/12] doc: add changelog entry Co-Authored-By: Claude Opus 4.6 (1M context) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a8286507..2b547d43f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Show loading state on Spending tab when node is not running #875 ### Added +- Transfer from Savings button on empty Spending screen when savings balance exists - Connection issues overlay with connectivity fixes across Send, Receive, and Transfer flows #878 - Lightning Connections empty state with onboarding screen #857 - Unified PIN management screen (enable/disable/change in one place) #857 From 7942b5289abc9548b79bb13d6c21a2f2e85354c1 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Thu, 2 Apr 2026 14:11:48 -0300 Subject: [PATCH 03/12] chore: backfill changelog pr number Co-Authored-By: Claude Opus 4.6 (1M context) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b547d43f..970270691 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Show loading state on Spending tab when node is not running #875 ### Added -- Transfer from Savings button on empty Spending screen when savings balance exists +- Transfer from Savings button on empty Spending screen when savings balance exists #882 - Connection issues overlay with connectivity fixes across Send, Receive, and Transfer flows #878 - Lightning Connections empty state with onboarding screen #857 - Unified PIN management screen (enable/disable/change in one place) #857 From 99cf1231193e2e60e9f5ee4b076a21f8b4dfa82a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Sena?= Date: Thu, 2 Apr 2026 14:42:19 -0300 Subject: [PATCH 04/12] Update app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> --- .../java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index 05d946078..d3054b3e3 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -126,7 +126,7 @@ fun SpendingWalletScreen( Icon( painter = painterResource(R.drawable.ic_transfer), contentDescription = null, - modifier = Modifier.size(16.dp), + modifier = Modifier.size(16.dp) ) }, modifier = Modifier.testTag("TransferFromSavings") From e0b12fd3cc0a2916e02dc1ba7a424a61634e9d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Sena?= Date: Thu, 2 Apr 2026 14:42:32 -0300 Subject: [PATCH 05/12] Update app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> --- .../java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index d3054b3e3..65e42a606 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -117,7 +117,7 @@ fun SpendingWalletScreen( } if (canTransferFromSavings) { - Spacer(modifier = Modifier.height(32.dp)) + VerticalSpacer(32.dp) SecondaryButton( onClick = onTransferFromSavingsClick, From c032a4dff5dfc20b9424b4a1e058c83aaeaede3a Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 6 Apr 2026 08:18:36 -0300 Subject: [PATCH 06/12] fix: import --- .../java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index 65e42a606..48baa4731 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -38,6 +38,7 @@ import to.bitkit.ui.components.EmptyStateView import to.bitkit.ui.components.IncomingTransfer import to.bitkit.ui.components.SecondaryButton import to.bitkit.ui.components.TabBar +import to.bitkit.ui.components.VerticalSpacer import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.DrawerNavIcon import to.bitkit.ui.scaffold.ScreenColumn From 5392a89ec03730ab3a281338064767d68aa532bd Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 6 Apr 2026 09:39:34 -0300 Subject: [PATCH 07/12] chore: lint --- .../java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index 48baa4731..359f256cc 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -135,7 +135,7 @@ fun SpendingWalletScreen( } if (!showEmptyState) { - Spacer(modifier = Modifier.height(32.dp)) + VerticalSpacer(32.dp) if (canTransfer) { SecondaryButton( @@ -145,7 +145,7 @@ fun SpendingWalletScreen( Icon( painter = painterResource(R.drawable.ic_transfer), contentDescription = null, - modifier = Modifier.size(16.dp), + modifier = Modifier.size(16.dp) ) }, modifier = Modifier.testTag("TransferToSavings") From dc6a27a592812f541e39fde6cee5a3a45727c218 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 6 Apr 2026 09:41:47 -0300 Subject: [PATCH 08/12] chore: lint --- .../java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index 359f256cc..4c76c0b36 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -4,10 +4,8 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box 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.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size From 2d9d0d358402818328dfb61858d8045fc046e196 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 6 Apr 2026 20:39:45 +0200 Subject: [PATCH 09/12] chore: rm unused import --- .../java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index ff6bc27a0..09c722dab 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -4,7 +4,6 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxSize From fd8f672de507663440333c118fc3c74eff90cd45 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 6 Apr 2026 20:41:01 +0200 Subject: [PATCH 10/12] fix: add bg blur to transfer from savings button --- .../java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index 09c722dab..39838aed6 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -144,6 +144,7 @@ fun SpendingWalletScreen( modifier = Modifier.size(16.dp) ) }, + hazeState = hazeState, modifier = Modifier.testTag("TransferFromSavings") ) } From 2780cc539cd8ee4592c338fcd929c647919f0e0c Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 6 Apr 2026 21:12:26 +0200 Subject: [PATCH 11/12] fix: secondary button weight layout regression --- .../java/to/bitkit/ui/components/Button.kt | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/Button.kt b/app/src/main/java/to/bitkit/ui/components/Button.kt index dc91fb4f8..58a5529ec 100644 --- a/app/src/main/java/to/bitkit/ui/components/Button.kt +++ b/app/src/main/java/to/bitkit/ui/components/Button.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredHeight @@ -83,6 +82,7 @@ enum class ButtonSize { Small -> 8.dp Large -> 6.dp } + fun secondaryBorder(enabled: Boolean): BorderStroke = when (this) { Large -> BorderStroke(2.dp, if (enabled) Colors.Gray4 else Color.Transparent) Small -> BorderStroke(1.dp, if (enabled) Colors.White16 else Color.Transparent) @@ -183,6 +183,7 @@ fun SecondaryButton( // and AFTER size modifiers (Haze needs to know dimensions) val buttonShape = MaterialTheme.shapes.extraLarge Box( + propagateMinConstraints = true, modifier = modifier .then(if (fullWidth) Modifier.fillMaxWidth() else Modifier) .requiredHeight(size.height) @@ -200,7 +201,7 @@ fun SecondaryButton( } else { Modifier } - ) + ), ) { OutlinedButton( onClick = rememberDebouncedClick(onClick = onClick), @@ -208,7 +209,6 @@ fun SecondaryButton( colors = AppButtonDefaults.secondaryColors.copy(contentColor = contentColor), contentPadding = contentPadding, border = border, - modifier = if (fullWidth) Modifier.fillMaxSize() else Modifier, ) { if (isLoading) { GradientCircularProgressIndicator( @@ -488,6 +488,25 @@ private fun SecondaryButtonPreview() { ) }, ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + SecondaryButton( + text = "Secondary", + fullWidth = false, + hazeState = hazeState, + onClick = {}, + modifier = Modifier.weight(1f) + ) + SecondaryButton( + text = "Secondary", + fullWidth = false, + hazeState = hazeState, + onClick = {}, + modifier = Modifier.weight(1f) + ) + } SecondaryButton( text = "Secondary Small", size = ButtonSize.Small, @@ -588,6 +607,23 @@ private fun TertiaryButtonPreview() { }, onClick = {} ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + TertiaryButton( + text = "Tertiary", + fullWidth = false, + onClick = {}, + modifier = Modifier.weight(1f) + ) + TertiaryButton( + text = "Tertiary", + fullWidth = false, + onClick = {}, + modifier = Modifier.weight(1f) + ) + } TertiaryButton( text = "Tertiary Small", size = ButtonSize.Small, From ced3109313098b994c28ad2750788942e2b560a9 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 6 Apr 2026 21:27:51 +0200 Subject: [PATCH 12/12] chore: rm modifier arg trailing comma --- app/src/main/java/to/bitkit/ui/components/Button.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/ui/components/Button.kt b/app/src/main/java/to/bitkit/ui/components/Button.kt index 58a5529ec..6887ed3a3 100644 --- a/app/src/main/java/to/bitkit/ui/components/Button.kt +++ b/app/src/main/java/to/bitkit/ui/components/Button.kt @@ -201,7 +201,7 @@ fun SecondaryButton( } else { Modifier } - ), + ) ) { OutlinedButton( onClick = rememberDebouncedClick(onClick = onClick),