@@ -5,51 +5,69 @@ import androidx.compose.foundation.layout.Column
55import androidx.compose.foundation.layout.Row
66import androidx.compose.foundation.layout.Spacer
77import androidx.compose.foundation.layout.fillMaxSize
8+ import androidx.compose.foundation.layout.fillMaxWidth
89import androidx.compose.foundation.layout.height
9- import androidx.compose.foundation.layout.imePadding
1010import androidx.compose.foundation.layout.padding
1111import androidx.compose.material3.HorizontalDivider
1212import androidx.compose.runtime.Composable
13+ import androidx.compose.runtime.LaunchedEffect
1314import androidx.compose.runtime.getValue
1415import androidx.compose.ui.Alignment
1516import androidx.compose.ui.Modifier
1617import androidx.compose.ui.platform.testTag
1718import androidx.compose.ui.res.stringResource
19+ import androidx.compose.ui.tooling.preview.Devices.NEXUS_5
1820import androidx.compose.ui.tooling.preview.Preview
1921import androidx.compose.ui.unit.dp
22+ import androidx.hilt.navigation.compose.hiltViewModel
2023import androidx.lifecycle.compose.collectAsStateWithLifecycle
2124import to.bitkit.R
25+ import to.bitkit.repositories.CurrencyState
2226import to.bitkit.ui.LocalBalances
2327import to.bitkit.ui.LocalCurrencies
24- import to.bitkit.ui.components.AmountInput
2528import to.bitkit.ui.components.Display
29+ import to.bitkit.ui.components.FillHeight
30+ import to.bitkit.ui.components.FillWidth
2631import to.bitkit.ui.components.MoneySSB
32+ import to.bitkit.ui.components.NumberPad
2733import to.bitkit.ui.components.NumberPadActionButton
34+ import to.bitkit.ui.components.NumberPadTextField
2835import to.bitkit.ui.components.PrimaryButton
2936import to.bitkit.ui.components.Text13Up
3037import to.bitkit.ui.components.UnitButton
38+ import to.bitkit.ui.components.VerticalSpacer
3139import to.bitkit.ui.scaffold.AppTopBar
3240import to.bitkit.ui.scaffold.CloseNavIcon
3341import to.bitkit.ui.scaffold.ScreenColumn
3442import to.bitkit.ui.theme.AppThemeSurface
3543import to.bitkit.ui.theme.Colors
3644import to.bitkit.ui.utils.withAccent
45+ import to.bitkit.viewmodels.AmountInputViewModel
46+ import to.bitkit.viewmodels.previewAmountInputViewModel
3747import kotlin.math.min
3848import kotlin.math.roundToLong
3949
50+ @Suppress(" ViewModelForwarding" )
4051@Composable
4152fun ExternalAmountScreen (
4253 viewModel : ExternalNodeViewModel ,
4354 onContinue : () -> Unit ,
4455 onBackClick : () -> Unit ,
4556 onCloseClick : () -> Unit ,
57+ amountInputViewModel : AmountInputViewModel = hiltViewModel(),
58+ currencies : CurrencyState = LocalCurrencies .current,
4659) {
4760 val uiState by viewModel.uiState.collectAsStateWithLifecycle()
61+ val amountUiState by amountInputViewModel.uiState.collectAsStateWithLifecycle()
62+
63+ LaunchedEffect (amountUiState.sats) {
64+ viewModel.onAmountChange(amountUiState.sats)
65+ }
4866
4967 Content (
68+ amountInputViewModel = amountInputViewModel,
5069 amountState = uiState.amount,
51- onAmountChange = { sats -> viewModel.onAmountChange(sats) },
52- onAmountOverride = { sats -> viewModel.onAmountOverride(sats) },
70+ currencies = currencies,
5371 onContinueClick = {
5472 viewModel.onAmountContinue()
5573 onContinue()
@@ -59,11 +77,12 @@ fun ExternalAmountScreen(
5977 )
6078}
6179
80+ @Suppress(" ViewModelForwarding" )
6281@Composable
6382private fun Content (
83+ amountInputViewModel : AmountInputViewModel ,
6484 amountState : ExternalNodeContract .UiState .Amount = ExternalNodeContract .UiState .Amount (),
65- onAmountChange : (Long ) -> Unit = {},
66- onAmountOverride : (Long ) -> Unit = {},
85+ currencies : CurrencyState = LocalCurrencies .current,
6786 onContinueClick : () -> Unit = {},
6887 onBackClick : () -> Unit = {},
6988 onCloseClick : () -> Unit = {},
@@ -78,23 +97,25 @@ private fun Content(
7897 modifier = Modifier
7998 .padding(horizontal = 16 .dp)
8099 .fillMaxSize()
81- .imePadding()
82100 .testTag(" ExternalAmount" )
83101 ) {
84102 val totalOnchainSats = LocalBalances .current.totalOnchainSats
103+ val amountUiState by amountInputViewModel.uiState.collectAsStateWithLifecycle()
85104
86- Spacer (modifier = Modifier .height( 16 .dp) )
105+ VerticalSpacer ( 16 .dp)
87106 Display (stringResource(R .string.lightning__external_amount__title).withAccent(accentColor = Colors .Purple ))
88- Spacer (modifier = Modifier .height( 32 .dp) )
107+ VerticalSpacer (minHeight = 16 .dp, maxHeight = 32 .dp)
89108
90- AmountInput (
91- primaryDisplay = LocalCurrencies .current.primaryDisplay,
92- overrideSats = amountState.overrideSats,
93- ) { sats ->
94- onAmountChange(sats)
95- }
109+ NumberPadTextField (
110+ viewModel = amountInputViewModel,
111+ currencies = currencies,
112+ showSecondaryField = false ,
113+ modifier = Modifier
114+ .fillMaxWidth()
115+ .testTag(" ExternalAmountNumberField" )
116+ )
96117
97- Spacer (modifier = Modifier .weight( 1f ) )
118+ FillHeight ( )
98119
99120 // Actions Row
100121 Row (
@@ -108,40 +129,49 @@ private fun Content(
108129 color = Colors .White64 ,
109130 )
110131 Spacer (modifier = Modifier .height(8 .dp))
111- MoneySSB (sats = amountState.max)
132+ MoneySSB (sats = amountState.max, showSymbol = true )
112133 }
113- Spacer (modifier = Modifier .weight(1f ))
114- UnitButton (color = Colors .Purple )
115- // 25% Button
134+ FillWidth ()
135+ UnitButton (
136+ color = Colors .Purple ,
137+ onClick = { amountInputViewModel.switchUnit(currencies) },
138+ modifier = Modifier .testTag(" ExternalNumberPadUnit" )
139+ )
116140 NumberPadActionButton (
117141 text = stringResource(R .string.lightning__spending_amount__quarter),
118142 color = Colors .Purple ,
119143 onClick = {
120- val quarterOfTotal = (totalOnchainSats.toDouble() / 4.0 ).roundToLong()
121- val cappedQuarter = min(quarterOfTotal, amountState.max)
122- onAmountOverride(cappedQuarter)
144+ val cappedQuarter = min(
145+ (totalOnchainSats.toDouble() * 0.25 ).roundToLong(),
146+ amountState.max,
147+ )
148+ amountInputViewModel.setSats(cappedQuarter, currencies)
123149 },
150+ modifier = Modifier .testTag(" ExternalAmountQuarter" )
124151 )
125- // Max Button
126152 NumberPadActionButton (
127153 text = stringResource(R .string.common__max),
128154 color = Colors .Purple ,
129155 onClick = {
130- onAmountOverride (amountState.max)
156+ amountInputViewModel.setSats (amountState.max, currencies )
131157 },
158+ modifier = Modifier .testTag(" ExternalAmountMax" )
132159 )
133160 }
161+
134162 HorizontalDivider ()
135- Spacer (modifier = Modifier .height(16 .dp))
163+ VerticalSpacer (16 .dp)
164+
165+ NumberPad (viewModel = amountInputViewModel)
136166
137167 PrimaryButton (
138168 text = stringResource(R .string.common__continue),
139169 onClick = { onContinueClick() },
140- enabled = amountState .sats != 0L ,
170+ enabled = amountUiState .sats != 0L ,
141171 modifier = Modifier .testTag(" ExternalAmountContinue" )
142172 )
143173
144- Spacer (modifier = Modifier .height( 16 .dp) )
174+ VerticalSpacer ( 16 .dp)
145175 }
146176 }
147177}
@@ -150,6 +180,20 @@ private fun Content(
150180@Composable
151181private fun Preview () {
152182 AppThemeSurface {
153- Content ()
183+ Content (
184+ amountState = ExternalNodeContract .UiState .Amount (max = 429_327 ),
185+ amountInputViewModel = previewAmountInputViewModel(),
186+ )
187+ }
188+ }
189+
190+ @Preview(showSystemUi = true , device = NEXUS_5 )
191+ @Composable
192+ private fun PreviewSmall () {
193+ AppThemeSurface {
194+ Content (
195+ amountState = ExternalNodeContract .UiState .Amount (max = 429_327 ),
196+ amountInputViewModel = previewAmountInputViewModel(),
197+ )
154198 }
155199}
0 commit comments