Skip to content

Commit be55333

Browse files
authored
Merge pull request #306 from synonymdev/feat/transfer-keyboard
Transfer keyboard
2 parents 7301a2f + b8ffe68 commit be55333

File tree

5 files changed

+88
-18
lines changed

5 files changed

+88
-18
lines changed

app/src/main/java/to/bitkit/ui/components/NumberPadTextField.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import androidx.compose.ui.semantics.contentDescription
1919
import androidx.compose.ui.semantics.semantics
2020
import androidx.compose.ui.tooling.preview.Preview
2121
import androidx.compose.ui.unit.dp
22+
import androidx.hilt.navigation.compose.hiltViewModel
2223
import to.bitkit.ext.removeSpaces
2324
import to.bitkit.ext.toLongOrDefault
2425
import to.bitkit.models.BITCOIN_SYMBOL
@@ -39,6 +40,7 @@ fun NumberPadTextField(
3940
displayUnit: BitcoinDisplayUnit,
4041
primaryDisplay: PrimaryDisplay,
4142
modifier: Modifier = Modifier,
43+
showSecondaryField: Boolean = true,
4244
) {
4345
val isPreview = LocalInspectionMode.current
4446
if (isPreview) {
@@ -48,6 +50,7 @@ fun NumberPadTextField(
4850
unit = primaryDisplay,
4951
placeholder = "",
5052
showPlaceholder = true,
53+
showSecondaryField = showSecondaryField,
5154
satoshis = 0,
5255
currencySymbol = if (primaryDisplay == PrimaryDisplay.BITCOIN) BITCOIN_SYMBOL else "$"
5356
)
@@ -129,6 +132,7 @@ fun NumberPadTextField(
129132
value = value,
130133
unit = primaryDisplay,
131134
placeholder = placeholder,
135+
showSecondaryField = showSecondaryField,
132136
showPlaceholder = true,
133137
satoshis = satoshis.toLongOrNull() ?: 0,
134138
currencySymbol = currency.getCurrencySymbol()
@@ -142,7 +146,7 @@ fun AmountInputHandler(
142146
displayUnit: BitcoinDisplayUnit,
143147
onInputChanged: (String) -> Unit,
144148
onAmountCalculated: (String) -> Unit,
145-
currencyVM: CurrencyViewModel,
149+
currencyVM: CurrencyViewModel = hiltViewModel(),
146150
overrideSats: Long? = null,
147151
) {
148152
var lastDisplay by rememberSaveable { mutableStateOf(primaryDisplay) }
@@ -219,14 +223,17 @@ fun MoneyAmount(
219223
showPlaceholder: Boolean,
220224
satoshis: Long,
221225
currencySymbol: String,
226+
showSecondaryField: Boolean = true,
222227
) {
223228
Column(
224229
modifier = modifier.semantics { contentDescription = value },
225230
horizontalAlignment = Alignment.Start
226231
) {
227-
MoneySSB(sats = satoshis, unit = unit.not(), color = Colors.White64)
232+
if (showSecondaryField) {
233+
MoneySSB(sats = satoshis, unit = unit.not(), color = Colors.White64)
228234

229-
Spacer(modifier = Modifier.height(12.dp))
235+
Spacer(modifier = Modifier.height(12.dp))
236+
}
230237

231238
Row(
232239
verticalAlignment = Alignment.CenterVertically

app/src/main/java/to/bitkit/ui/components/Text.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,14 @@ fun Title(
8787
text: String,
8888
modifier: Modifier = Modifier,
8989
color: Color = MaterialTheme.colorScheme.primary,
90+
maxLines: Int = Int.MAX_VALUE,
91+
overflow: TextOverflow = TextOverflow.Ellipsis,
9092
textAlign: TextAlign = TextAlign.Unspecified,
9193
) {
9294
Text(
9395
text = text,
96+
maxLines = maxLines,
97+
overflow = overflow,
9498
style = AppTextStyles.Title.merge(
9599
color = color,
96100
textAlign = textAlign,

app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ fun AppTopBar(
5858
.size(32.dp)
5959
)
6060
}
61-
Title(text = titleText)
61+
Title(text = titleText, maxLines = 1)
6262
}
6363
}
6464
},

app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
55
import androidx.compose.foundation.layout.Row
66
import androidx.compose.foundation.layout.Spacer
77
import androidx.compose.foundation.layout.fillMaxSize
8+
import androidx.compose.foundation.layout.fillMaxWidth
89
import androidx.compose.foundation.layout.height
910
import androidx.compose.foundation.layout.imePadding
1011
import androidx.compose.foundation.layout.padding
@@ -16,17 +17,22 @@ import androidx.compose.ui.Alignment
1617
import androidx.compose.ui.Modifier
1718
import androidx.compose.ui.platform.testTag
1819
import androidx.compose.ui.res.stringResource
20+
import androidx.compose.ui.tooling.preview.Devices.NEXUS_5
1921
import androidx.compose.ui.tooling.preview.Preview
2022
import androidx.compose.ui.unit.dp
2123
import androidx.lifecycle.compose.collectAsStateWithLifecycle
24+
import okhttp3.internal.toLongOrDefault
2225
import to.bitkit.R
26+
import to.bitkit.models.PrimaryDisplay
2327
import to.bitkit.ui.LocalCurrencies
24-
import to.bitkit.ui.components.AmountInput
28+
import to.bitkit.ui.components.AmountInputHandler
2529
import to.bitkit.ui.components.Display
2630
import to.bitkit.ui.components.FillHeight
2731
import to.bitkit.ui.components.FillWidth
32+
import to.bitkit.ui.components.Keyboard
2833
import to.bitkit.ui.components.MoneySSB
2934
import to.bitkit.ui.components.NumberPadActionButton
35+
import to.bitkit.ui.components.NumberPadTextField
3036
import to.bitkit.ui.components.PrimaryButton
3137
import to.bitkit.ui.components.Text13Up
3238
import to.bitkit.ui.components.UnitButton
@@ -68,6 +74,17 @@ fun SpendingAmountScreen(
6874
}
6975
}
7076

77+
AmountInputHandler(
78+
input = uiState.input,
79+
overrideSats = uiState.overrideSats,
80+
primaryDisplay = currencies.primaryDisplay,
81+
displayUnit = currencies.displayUnit,
82+
onInputChanged = viewModel::onInputChanged,
83+
onAmountCalculated = { sats ->
84+
viewModel.handleCalculatedAmount(sats.toLongOrDefault(0))
85+
},
86+
)
87+
7188
Content(
7289
uiState = uiState,
7390
currencies = currencies,
@@ -76,7 +93,7 @@ fun SpendingAmountScreen(
7693
onClickQuarter = viewModel::onClickQuarter,
7794
onClickMaxAmount = viewModel::onClickMaxAmount,
7895
onConfirmAmount = viewModel::onConfirmAmount,
79-
onAmountChanged = viewModel::onAmountChanged
96+
onInputChange = viewModel::onInputChanged,
8097
)
8198
}
8299

@@ -89,7 +106,7 @@ private fun Content(
89106
onClickQuarter: () -> Unit,
90107
onClickMaxAmount: () -> Unit,
91108
onConfirmAmount: () -> Unit,
92-
onAmountChanged: (Long) -> Unit,
109+
onInputChange: (String) -> Unit,
93110
) {
94111
ScreenColumn {
95112
AppTopBar(
@@ -104,34 +121,39 @@ private fun Content(
104121
.imePadding()
105122
.testTag("SpendingAmount")
106123
) {
107-
VerticalSpacer(32.dp)
124+
VerticalSpacer(16.dp)
108125
Display(
109126
text = stringResource(R.string.lightning__spending_amount__title)
110127
.withAccent(accentColor = Colors.Purple)
111128
)
112-
VerticalSpacer(32.dp)
113129

114-
AmountInput(
130+
NumberPadTextField(
131+
input = uiState.input,
132+
displayUnit = currencies.displayUnit,
133+
showSecondaryField = false,
115134
primaryDisplay = currencies.primaryDisplay,
116-
overrideSats = uiState.overrideSats,
117-
onSatsChange = onAmountChanged,
135+
modifier = Modifier
136+
.fillMaxWidth()
137+
.testTag("SpendingAmountNumberField")
118138
)
119139

120140
FillHeight()
121141

122-
// Actions
123142
Row(
124143
verticalAlignment = Alignment.Bottom,
125144
horizontalArrangement = Arrangement.spacedBy(8.dp),
126-
modifier = Modifier.padding(vertical = 8.dp)
145+
modifier = Modifier
146+
.padding(vertical = 8.dp)
147+
.testTag("SendAmountNumberPad")
127148
) {
128149
Column {
129150
Text13Up(
130151
text = stringResource(R.string.wallet__send_available),
131152
color = Colors.White64,
153+
modifier = Modifier.testTag("SpendingAmountAvailable")
132154
)
133155
Spacer(modifier = Modifier.height(8.dp))
134-
MoneySSB(sats = uiState.balanceAfterFee)
156+
MoneySSB(sats = uiState.balanceAfterFee, modifier = Modifier.testTag("SpendingAmountUnit"))
135157
}
136158
FillWidth()
137159
UnitButton(color = Colors.Purple)
@@ -151,8 +173,23 @@ private fun Content(
151173
)
152174
}
153175
HorizontalDivider()
176+
154177
VerticalSpacer(16.dp)
155178

179+
Keyboard(
180+
onClick = { number ->
181+
onInputChange(if (uiState.input == "0") number else uiState.input + number)
182+
},
183+
onClickBackspace = {
184+
onInputChange(if (uiState.input.length > 1) uiState.input.dropLast(1) else "0")
185+
},
186+
isDecimal = currencies.primaryDisplay == PrimaryDisplay.FIAT,
187+
modifier = Modifier
188+
.fillMaxWidth()
189+
)
190+
191+
VerticalSpacer(8.dp)
192+
156193
PrimaryButton(
157194
text = stringResource(R.string.common__continue),
158195
onClick = onConfirmAmount,
@@ -171,14 +208,31 @@ private fun Content(
171208
private fun Preview() {
172209
AppThemeSurface {
173210
Content(
174-
uiState = TransferToSpendingUiState(),
211+
uiState = TransferToSpendingUiState(input = "5 000"),
212+
currencies = CurrencyUiState(),
213+
onBackClick = {},
214+
onCloseClick = {},
215+
onClickQuarter = {},
216+
onClickMaxAmount = {},
217+
onConfirmAmount = {},
218+
onInputChange = {},
219+
)
220+
}
221+
}
222+
223+
@Preview(showBackground = true, device = NEXUS_5)
224+
@Composable
225+
private fun Preview2() {
226+
AppThemeSurface {
227+
Content(
228+
uiState = TransferToSpendingUiState(input = "5 000"),
175229
currencies = CurrencyUiState(),
176230
onBackClick = {},
177231
onCloseClick = {},
178232
onClickQuarter = {},
179233
onClickMaxAmount = {},
180234
onConfirmAmount = {},
181-
onAmountChanged = {},
235+
onInputChange = {},
182236
)
183237
}
184238
}

app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ class TransferViewModel @Inject constructor(
152152
}
153153
}
154154

155-
fun onAmountChanged(sats: Long) {
155+
fun onInputChanged(newInput: String) {
156+
_spendingUiState.update { it.copy(input = newInput) }
157+
}
158+
159+
fun handleCalculatedAmount(sats: Long) {
156160
if (sats > _spendingUiState.value.maxAllowedToSend) {
157161
setTransferEffect(
158162
TransferEffect.ToastError(
@@ -545,6 +549,7 @@ data class TransferToSpendingUiState(
545549
val maxAllowedToSend: Long = 0,
546550
val balanceAfterFee: Long = 0,
547551
val isLoading: Boolean = false,
552+
val input: String = "",
548553
)
549554

550555
data class TransferValues(

0 commit comments

Comments
 (0)