diff --git a/app/src/main/java/to/bitkit/ui/components/NumberPadTextField.kt b/app/src/main/java/to/bitkit/ui/components/NumberPadTextField.kt index 98b0e17f7..b269ad742 100644 --- a/app/src/main/java/to/bitkit/ui/components/NumberPadTextField.kt +++ b/app/src/main/java/to/bitkit/ui/components/NumberPadTextField.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel import to.bitkit.ext.removeSpaces import to.bitkit.ext.toLongOrDefault import to.bitkit.models.BITCOIN_SYMBOL @@ -39,6 +40,7 @@ fun NumberPadTextField( displayUnit: BitcoinDisplayUnit, primaryDisplay: PrimaryDisplay, modifier: Modifier = Modifier, + showSecondaryField: Boolean = true, ) { val isPreview = LocalInspectionMode.current if (isPreview) { @@ -48,6 +50,7 @@ fun NumberPadTextField( unit = primaryDisplay, placeholder = "", showPlaceholder = true, + showSecondaryField = showSecondaryField, satoshis = 0, currencySymbol = if (primaryDisplay == PrimaryDisplay.BITCOIN) BITCOIN_SYMBOL else "$" ) @@ -129,6 +132,7 @@ fun NumberPadTextField( value = value, unit = primaryDisplay, placeholder = placeholder, + showSecondaryField = showSecondaryField, showPlaceholder = true, satoshis = satoshis.toLongOrNull() ?: 0, currencySymbol = currency.getCurrencySymbol() @@ -142,7 +146,7 @@ fun AmountInputHandler( displayUnit: BitcoinDisplayUnit, onInputChanged: (String) -> Unit, onAmountCalculated: (String) -> Unit, - currencyVM: CurrencyViewModel, + currencyVM: CurrencyViewModel = hiltViewModel(), overrideSats: Long? = null, ) { var lastDisplay by rememberSaveable { mutableStateOf(primaryDisplay) } @@ -219,14 +223,17 @@ fun MoneyAmount( showPlaceholder: Boolean, satoshis: Long, currencySymbol: String, + showSecondaryField: Boolean = true, ) { Column( modifier = modifier.semantics { contentDescription = value }, horizontalAlignment = Alignment.Start ) { - MoneySSB(sats = satoshis, unit = unit.not(), color = Colors.White64) + if (showSecondaryField) { + MoneySSB(sats = satoshis, unit = unit.not(), color = Colors.White64) - Spacer(modifier = Modifier.height(12.dp)) + Spacer(modifier = Modifier.height(12.dp)) + } Row( verticalAlignment = Alignment.CenterVertically diff --git a/app/src/main/java/to/bitkit/ui/components/Text.kt b/app/src/main/java/to/bitkit/ui/components/Text.kt index bdc5c415b..b98610c3c 100644 --- a/app/src/main/java/to/bitkit/ui/components/Text.kt +++ b/app/src/main/java/to/bitkit/ui/components/Text.kt @@ -87,10 +87,14 @@ fun Title( text: String, modifier: Modifier = Modifier, color: Color = MaterialTheme.colorScheme.primary, + maxLines: Int = Int.MAX_VALUE, + overflow: TextOverflow = TextOverflow.Ellipsis, textAlign: TextAlign = TextAlign.Unspecified, ) { Text( text = text, + maxLines = maxLines, + overflow = overflow, style = AppTextStyles.Title.merge( color = color, textAlign = textAlign, diff --git a/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt b/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt index e82a5f430..a0cad7558 100644 --- a/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt +++ b/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt @@ -58,7 +58,7 @@ fun AppTopBar( .size(32.dp) ) } - Title(text = titleText) + Title(text = titleText, maxLines = 1) } } }, diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt index 8db335193..62638cb1e 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row 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.imePadding import androidx.compose.foundation.layout.padding @@ -16,17 +17,22 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Devices.NEXUS_5 import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle +import okhttp3.internal.toLongOrDefault import to.bitkit.R +import to.bitkit.models.PrimaryDisplay import to.bitkit.ui.LocalCurrencies -import to.bitkit.ui.components.AmountInput +import to.bitkit.ui.components.AmountInputHandler import to.bitkit.ui.components.Display import to.bitkit.ui.components.FillHeight import to.bitkit.ui.components.FillWidth +import to.bitkit.ui.components.Keyboard import to.bitkit.ui.components.MoneySSB import to.bitkit.ui.components.NumberPadActionButton +import to.bitkit.ui.components.NumberPadTextField import to.bitkit.ui.components.PrimaryButton import to.bitkit.ui.components.Text13Up import to.bitkit.ui.components.UnitButton @@ -68,6 +74,17 @@ fun SpendingAmountScreen( } } + AmountInputHandler( + input = uiState.input, + overrideSats = uiState.overrideSats, + primaryDisplay = currencies.primaryDisplay, + displayUnit = currencies.displayUnit, + onInputChanged = viewModel::onInputChanged, + onAmountCalculated = { sats -> + viewModel.handleCalculatedAmount(sats.toLongOrDefault(0)) + }, + ) + Content( uiState = uiState, currencies = currencies, @@ -76,7 +93,7 @@ fun SpendingAmountScreen( onClickQuarter = viewModel::onClickQuarter, onClickMaxAmount = viewModel::onClickMaxAmount, onConfirmAmount = viewModel::onConfirmAmount, - onAmountChanged = viewModel::onAmountChanged + onInputChange = viewModel::onInputChanged, ) } @@ -89,7 +106,7 @@ private fun Content( onClickQuarter: () -> Unit, onClickMaxAmount: () -> Unit, onConfirmAmount: () -> Unit, - onAmountChanged: (Long) -> Unit, + onInputChange: (String) -> Unit, ) { ScreenColumn { AppTopBar( @@ -104,34 +121,39 @@ private fun Content( .imePadding() .testTag("SpendingAmount") ) { - VerticalSpacer(32.dp) + VerticalSpacer(16.dp) Display( text = stringResource(R.string.lightning__spending_amount__title) .withAccent(accentColor = Colors.Purple) ) - VerticalSpacer(32.dp) - AmountInput( + NumberPadTextField( + input = uiState.input, + displayUnit = currencies.displayUnit, + showSecondaryField = false, primaryDisplay = currencies.primaryDisplay, - overrideSats = uiState.overrideSats, - onSatsChange = onAmountChanged, + modifier = Modifier + .fillMaxWidth() + .testTag("SpendingAmountNumberField") ) FillHeight() - // Actions Row( verticalAlignment = Alignment.Bottom, horizontalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.padding(vertical = 8.dp) + modifier = Modifier + .padding(vertical = 8.dp) + .testTag("SendAmountNumberPad") ) { Column { Text13Up( text = stringResource(R.string.wallet__send_available), color = Colors.White64, + modifier = Modifier.testTag("SpendingAmountAvailable") ) Spacer(modifier = Modifier.height(8.dp)) - MoneySSB(sats = uiState.balanceAfterFee) + MoneySSB(sats = uiState.balanceAfterFee, modifier = Modifier.testTag("SpendingAmountUnit")) } FillWidth() UnitButton(color = Colors.Purple) @@ -151,8 +173,23 @@ private fun Content( ) } HorizontalDivider() + VerticalSpacer(16.dp) + Keyboard( + onClick = { number -> + onInputChange(if (uiState.input == "0") number else uiState.input + number) + }, + onClickBackspace = { + onInputChange(if (uiState.input.length > 1) uiState.input.dropLast(1) else "0") + }, + isDecimal = currencies.primaryDisplay == PrimaryDisplay.FIAT, + modifier = Modifier + .fillMaxWidth() + ) + + VerticalSpacer(8.dp) + PrimaryButton( text = stringResource(R.string.common__continue), onClick = onConfirmAmount, @@ -171,14 +208,31 @@ private fun Content( private fun Preview() { AppThemeSurface { Content( - uiState = TransferToSpendingUiState(), + uiState = TransferToSpendingUiState(input = "5 000"), + currencies = CurrencyUiState(), + onBackClick = {}, + onCloseClick = {}, + onClickQuarter = {}, + onClickMaxAmount = {}, + onConfirmAmount = {}, + onInputChange = {}, + ) + } +} + +@Preview(showBackground = true, device = NEXUS_5) +@Composable +private fun Preview2() { + AppThemeSurface { + Content( + uiState = TransferToSpendingUiState(input = "5 000"), currencies = CurrencyUiState(), onBackClick = {}, onCloseClick = {}, onClickQuarter = {}, onClickMaxAmount = {}, onConfirmAmount = {}, - onAmountChanged = {}, + onInputChange = {}, ) } } diff --git a/app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt index d76f07ec3..d07517886 100644 --- a/app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt @@ -152,7 +152,11 @@ class TransferViewModel @Inject constructor( } } - fun onAmountChanged(sats: Long) { + fun onInputChanged(newInput: String) { + _spendingUiState.update { it.copy(input = newInput) } + } + + fun handleCalculatedAmount(sats: Long) { if (sats > _spendingUiState.value.maxAllowedToSend) { setTransferEffect( TransferEffect.ToastError( @@ -545,6 +549,7 @@ data class TransferToSpendingUiState( val maxAllowedToSend: Long = 0, val balanceAfterFee: Long = 0, val isLoading: Boolean = false, + val input: String = "", ) data class TransferValues(