@@ -42,6 +42,7 @@ import to.bitkit.ui.shared.util.gradientBackground
4242import to.bitkit.ui.theme.AppThemeSurface
4343import to.bitkit.ui.theme.Colors
4444import to.bitkit.viewmodels.CurrencyUiState
45+ import to.bitkit.viewmodels.CurrencyViewModel
4546import to.bitkit.viewmodels.MainUiState
4647import to.bitkit.viewmodels.SendEvent
4748import to.bitkit.viewmodels.SendMethod
@@ -57,143 +58,209 @@ fun SendAmountScreen(
5758 onEvent : (SendEvent ) -> Unit ,
5859) {
5960 val currencyVM = currencyViewModel ? : return
60-
6161 var input: String by remember { mutableStateOf(" " ) }
6262
63- LaunchedEffect (currencyUiState.primaryDisplay) {
64- input = when (currencyUiState.primaryDisplay) {
65- PrimaryDisplay .BITCOIN -> {
66- val amountLong = currencyVM.convertFiatToSats(input.toDoubleOrNull() ? : 0.0 ) ? : 0
67- if (amountLong > 0.0 ) amountLong.toString() else " "
68- }
63+ AmountInputHandler (
64+ input = input,
65+ primaryDisplay = currencyUiState.primaryDisplay,
66+ displayUnit = currencyUiState.displayUnit,
67+ onInputChanged = { newInput -> input = newInput },
68+ onAmountCalculated = { sats -> onEvent(SendEvent .AmountChange (value = sats)) },
69+ currencyVM = currencyVM
70+ )
6971
70- PrimaryDisplay .FIAT -> {
71- val convertedAmount = currencyVM.convert(input.toLongOrDefault(0L ))
72- if ((convertedAmount?.value ? : BigDecimal (0 )) > BigDecimal (0 )) convertedAmount?.formatted.toString() else " "
73- }
72+ Column (
73+ modifier = Modifier
74+ .fillMaxSize()
75+ .gradientBackground()
76+ ) {
77+ SheetTopBar (stringResource(R .string.title_send_amount)) {
78+ onEvent(SendEvent .AmountReset )
79+ onBack()
7480 }
75- }
7681
77- LaunchedEffect (input) {
78- val sats: String = when (currencyUiState.primaryDisplay) {
79- PrimaryDisplay .BITCOIN -> {
80- if (currencyUiState.displayUnit == BitcoinDisplayUnit .MODERN ) input else (input.toLongOrDefault(0L ) * 100_000_000 ).toString()
82+ when (walletUiState.nodeLifecycleState) {
83+ is NodeLifecycleState .Running -> {
84+ SendAmountContent (
85+ input = input,
86+ uiState = uiState,
87+ currencyUiState = currencyUiState,
88+ onInputChanged = { input = it },
89+ onEvent = onEvent
90+ )
8191 }
82-
83- PrimaryDisplay .FIAT -> {
84- val convertedAmount = currencyVM.convertFiatToSats(input.toDoubleOrNull() ? : 0.0 ) ? : 0L
85- convertedAmount.toString()
92+ else -> {
93+ SyncNodeView (
94+ modifier = Modifier
95+ .fillMaxWidth()
96+ .weight(1f )
97+ )
8698 }
8799 }
88- onEvent(SendEvent .AmountChange (value = sats))
100+ }
101+ }
102+
103+ @Composable
104+ private fun SendAmountContent (
105+ input : String ,
106+ uiState : SendUiState ,
107+ currencyUiState : CurrencyUiState ,
108+ onInputChanged : (String ) -> Unit ,
109+ onEvent : (SendEvent ) -> Unit ,
110+ ) {
111+ val balances = LocalBalances .current
112+ val availableAmount = when (uiState.payMethod) {
113+ SendMethod .ONCHAIN -> balances.totalOnchainSats.toLong()
114+ SendMethod .LIGHTNING -> balances.totalLightningSats.toLong()
89115 }
90116
91117 Column (
92- modifier = Modifier
93- .fillMaxSize()
94- .gradientBackground()
118+ modifier = Modifier .padding(horizontal = 16 .dp)
95119 ) {
96- SheetTopBar (stringResource(R .string.title_send_amount)) {
97- onEvent(SendEvent .AmountReset )
98- onBack()
120+ Spacer (Modifier .height(16 .dp))
121+
122+ NumberPadTextField (input = input, modifier = Modifier .fillMaxWidth())
123+
124+ Spacer (modifier = Modifier .height(24 .dp))
125+ Spacer (modifier = Modifier .weight(1f ))
126+
127+ Text13Up (
128+ text = stringResource(R .string.wallet__send_available),
129+ color = Colors .White64 ,
130+ )
131+ Spacer (modifier = Modifier .height(4 .dp))
132+
133+ Row (
134+ verticalAlignment = Alignment .CenterVertically ,
135+ ) {
136+ MoneySSB (sats = availableAmount.toLong())
137+
138+ Spacer (modifier = Modifier .weight(1f ))
139+
140+ PaymentMethodButton (uiState = uiState, onEvent = onEvent)
141+ Spacer (modifier = Modifier .width(8 .dp))
142+ UnitButton (modifier = Modifier .height(28 .dp))
99143 }
100144
101- if (walletUiState.nodeLifecycleState is NodeLifecycleState .Running ) {
102- Spacer (Modifier .height(16 .dp))
145+ HorizontalDivider (modifier = Modifier .padding(vertical = 24 .dp))
103146
104- Column (
105- modifier = Modifier .padding(horizontal = 16 .dp)
106- ) {
107- NumberPadTextField (input = input, modifier = Modifier .fillMaxWidth())
147+ Keyboard (
148+ onClick = { number ->
149+ onInputChanged(if (input == " 0" ) number else input + number)
150+ },
151+ onClickBackspace = {
152+ onInputChanged(if (input.length > 1 ) input.dropLast(1 ) else " 0" )
153+ },
154+ isDecimal = currencyUiState.primaryDisplay == PrimaryDisplay .FIAT ,
155+ modifier = Modifier .fillMaxWidth(),
156+ )
108157
109- Spacer (modifier = Modifier .height(24 .dp))
110- Spacer (modifier = Modifier .weight(1f ))
158+ Spacer (modifier = Modifier .height(41 .dp))
111159
112- Text13Up (
113- text = stringResource(R .string.wallet__send_available),
114- color = Colors .White64 ,
115- )
116- Spacer (modifier = Modifier .height(4 .dp))
117-
118- Row (
119- verticalAlignment = Alignment .CenterVertically ,
120- ) {
121- val balances = LocalBalances .current
122- val availableAmount = when (uiState.payMethod) {
123- SendMethod .ONCHAIN -> balances.totalOnchainSats.toLong()
124- SendMethod .LIGHTNING -> balances.totalLightningSats.toLong()
125- }
126- MoneySSB (sats = availableAmount.toLong())
127-
128- Spacer (modifier = Modifier .weight(1f ))
129-
130- OutlinedColorButton (
131- onClick = { onEvent(SendEvent .PaymentMethodSwitch ) },
132- enabled = uiState.isUnified,
133- color = when (uiState.payMethod) {
134- SendMethod .ONCHAIN -> Colors .Brand
135- SendMethod .LIGHTNING -> Colors .Purple
136- },
137- modifier = Modifier .height(28 .dp)
138- ) {
139- Text13Up (
140- text = when (uiState.payMethod) {
141- SendMethod .ONCHAIN -> stringResource(R .string.savings)
142- SendMethod .LIGHTNING -> stringResource(R .string.spending)
143- },
144- color = when (uiState.payMethod) {
145- SendMethod .ONCHAIN -> Colors .Brand
146- SendMethod .LIGHTNING -> Colors .Purple
147- }
148- )
149- }
150- Spacer (modifier = Modifier .width(8 .dp))
151- UnitButton (
152- modifier = Modifier .height(28 .dp)
153- )
154- }
155-
156- HorizontalDivider (modifier = Modifier .padding(vertical = 24 .dp))
157-
158- Keyboard (
159- onClick = { number ->
160- if (input == " 0" ) input = number else input+ = number
161- },
162- onClickBackspace = {
163- input = if (input.length > 1 ) input.dropLast(1 ) else " 0"
164- },
165- isDecimal = currencyUiState.primaryDisplay == PrimaryDisplay .FIAT ,
166- modifier = Modifier .fillMaxWidth(),
167- )
160+ PrimaryButton (
161+ text = stringResource(R .string.continue_button),
162+ enabled = uiState.isAmountInputValid,
163+ onClick = { onEvent(SendEvent .AmountContinue (uiState.amountInput)) },
164+ )
168165
169- Spacer (modifier = Modifier .height(41 .dp))
166+ Spacer (modifier = Modifier .height(16 .dp))
167+ }
168+ }
170169
171- PrimaryButton (
172- text = stringResource(R .string.continue_button),
173- enabled = uiState.isAmountInputValid,
174- onClick = { onEvent(SendEvent .AmountContinue (uiState.amountInput)) },
175- )
170+ @Composable
171+ private fun PaymentMethodButton (
172+ uiState : SendUiState ,
173+ onEvent : (SendEvent ) -> Unit ,
174+ ) {
175+ OutlinedColorButton (
176+ onClick = { onEvent(SendEvent .PaymentMethodSwitch ) },
177+ enabled = uiState.isUnified,
178+ color = when (uiState.payMethod) {
179+ SendMethod .ONCHAIN -> Colors .Brand
180+ SendMethod .LIGHTNING -> Colors .Purple
181+ },
182+ modifier = Modifier .height(28 .dp)
183+ ) {
184+ Text13Up (
185+ text = when (uiState.payMethod) {
186+ SendMethod .ONCHAIN -> stringResource(R .string.savings)
187+ SendMethod .LIGHTNING -> stringResource(R .string.spending)
188+ },
189+ color = when (uiState.payMethod) {
190+ SendMethod .ONCHAIN -> Colors .Brand
191+ SendMethod .LIGHTNING -> Colors .Purple
192+ }
193+ )
194+ }
195+ }
196+
197+ @Composable
198+ private fun AmountInputHandler (
199+ input : String ,
200+ primaryDisplay : PrimaryDisplay ,
201+ displayUnit : BitcoinDisplayUnit ,
202+ onInputChanged : (String ) -> Unit ,
203+ onAmountCalculated : (String ) -> Unit ,
204+ currencyVM : CurrencyViewModel
205+ ) {
206+ LaunchedEffect (primaryDisplay) {
207+ val newInput = when (primaryDisplay) {
208+ PrimaryDisplay .BITCOIN -> {
209+ val amountLong = currencyVM.convertFiatToSats(input.toDoubleOrNull() ? : 0.0 ) ? : 0
210+ if (amountLong > 0.0 ) amountLong.toString() else " "
211+ }
212+ PrimaryDisplay .FIAT -> {
213+ val convertedAmount = currencyVM.convert(input.toLongOrDefault(0L ))
214+ if ((convertedAmount?.value ? : BigDecimal (0 )) > BigDecimal (0 )) convertedAmount?.formatted.toString() else " "
215+ }
216+ }
217+ onInputChanged(newInput)
218+ }
176219
177- Spacer (modifier = Modifier .height(16 .dp))
220+ LaunchedEffect (input) {
221+ val sats = when (primaryDisplay) {
222+ PrimaryDisplay .BITCOIN -> {
223+ if (displayUnit == BitcoinDisplayUnit .MODERN ) input else (input.toLongOrDefault(0L ) * 100_000_000 ).toString()
224+ }
225+ PrimaryDisplay .FIAT -> {
226+ val convertedAmount = currencyVM.convertFiatToSats(input.toDoubleOrNull() ? : 0.0 ) ? : 0L
227+ convertedAmount.toString()
178228 }
179- } else {
180- SyncNodeView (
181- modifier = Modifier
182- .fillMaxWidth()
183- .weight(1f )
184- )
185229 }
230+ onAmountCalculated(sats)
186231 }
187232}
188233
189- @Preview(showBackground = true )
234+ @Preview(showBackground = true , name = " Running - Lightning " )
190235@Composable
191- private fun Preview1 () {
236+ private fun PreviewRunningLightning () {
192237 AppThemeSurface {
193238 SendAmountScreen (
194239 uiState = SendUiState (
195240 payMethod = SendMethod .LIGHTNING ,
196- amountInput = " 100"
241+ amountInput = " 100" ,
242+ isAmountInputValid = true ,
243+ isUnified = true
244+ ),
245+ walletUiState = MainUiState (
246+ nodeLifecycleState = NodeLifecycleState .Running
247+ ),
248+ onBack = {},
249+ onEvent = {},
250+ )
251+ }
252+ }
253+
254+ @Preview(showBackground = true , name = " Running - Onchain" )
255+ @Composable
256+ private fun PreviewRunningOnchain () {
257+ AppThemeSurface {
258+ SendAmountScreen (
259+ uiState = SendUiState (
260+ payMethod = SendMethod .ONCHAIN ,
261+ amountInput = " 5000" ,
262+ isAmountInputValid = true ,
263+ isUnified = true
197264 ),
198265 walletUiState = MainUiState (
199266 nodeLifecycleState = NodeLifecycleState .Running
@@ -204,9 +271,9 @@ private fun Preview1() {
204271 }
205272}
206273
207- @Preview(showBackground = true )
274+ @Preview(showBackground = true , name = " Initializing " )
208275@Composable
209- private fun Preview2 () {
276+ private fun PreviewInitializing () {
210277 AppThemeSurface {
211278 SendAmountScreen (
212279 uiState = SendUiState (
0 commit comments