diff --git a/app/src/main/java/app/musikus/core/presentation/components/NumberInput.kt b/app/src/main/java/app/musikus/core/presentation/components/NumberInput.kt index 22536a77..4a0e7fd8 100644 --- a/app/src/main/java/app/musikus/core/presentation/components/NumberInput.kt +++ b/app/src/main/java/app/musikus/core/presentation/components/NumberInput.kt @@ -49,6 +49,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.BaselineShift import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.TextUnit @@ -163,7 +164,10 @@ class NumberInputState ( require(initialValue in minValue..maxValue) { "initialValue not in allowed range" } } } - var currentValue = mutableStateOf(initialValue) + val currentValue = mutableStateOf(TextFieldValue(initialValue?.toString() ?: "")) + + val numericValue: Int + get() = currentValue.value.text.toIntOrNull() ?: minValue companion object { /** @@ -179,7 +183,7 @@ class NumberInputState ( }, restore = { NumberInputState( - initialValue = it[0] as Int?, + initialValue = (it[0] as TextFieldValue).text.toIntOrNull(), minValue = it[1] as Int, maxValue = it[2] as Int ) @@ -227,11 +231,6 @@ fun NumberInput( MaterialTheme.colorScheme.primaryContainer } val maxLength = state.maxValue.toString().length - val displayValue = if (focused || !padStart) { - state.currentValue.value?.toString() ?: "" - } else { - (state.currentValue.value?.toString() ?: "").padStart(maxLength, '0') - } Row { BasicTextField( @@ -241,13 +240,35 @@ fun NumberInput( .height(IntrinsicSize.Min) .padding(MaterialTheme.spacing.extraSmall) .focusRequester(focusRequester) - .onFocusChanged { focused = it.isFocused }, - value = displayValue, + .onFocusChanged { + if(it.isFocused) { + state.currentValue.value = state.currentValue.value.copy( + text = state.currentValue.value.text.trimStart('0') + ) + } else { + if (state.currentValue.value.text.isEmpty()) + state.currentValue.value = TextFieldValue(state.minValue.toString()) + if(padStart) + state.currentValue.value = state.currentValue.value.copy( + state.currentValue.value.text.padStart(maxLength, '0') + ) + } + focused = it.isFocused + }, + value = state.currentValue.value, textStyle = textStyle.copy(color = MaterialTheme.colorScheme.onSurface), onValueChange = { newValue -> - val number = newValue.toIntOrNull() - if (number in state.minValue..state.maxValue || number == null) { - state.currentValue.value = number + var newValueOnlyNumbers = newValue.text.filter { it.isDigit() } + if (newValueOnlyNumbers.length > maxLength) { + if(newValue.selection.collapsed && newValue.selection.start == 0) { + newValueOnlyNumbers = newValueOnlyNumbers.take(1) + } else { + return@BasicTextField + } + } + val number = newValueOnlyNumbers.toIntOrNull() ?: state.minValue + if (number in state.minValue..state.maxValue) { + state.currentValue.value = newValue.copy(newValueOnlyNumbers) onValueChanged(number) } }, diff --git a/app/src/main/java/app/musikus/goals/presentation/GoalsUiEvent.kt b/app/src/main/java/app/musikus/goals/presentation/GoalsUiEvent.kt index 17b79f81..9d13e83a 100644 --- a/app/src/main/java/app/musikus/goals/presentation/GoalsUiEvent.kt +++ b/app/src/main/java/app/musikus/goals/presentation/GoalsUiEvent.kt @@ -45,8 +45,8 @@ sealed class GoalsUiEvent { } sealed class GoalDialogUiEvent { - data class HourTargetChanged(val hours: Int?) : GoalDialogUiEvent() - data class MinuteTargetChanged(val minutes: Int?) : GoalDialogUiEvent() + data class HourTargetChanged(val hours: Int) : GoalDialogUiEvent() + data class MinuteTargetChanged(val minutes: Int) : GoalDialogUiEvent() data class PeriodChanged(val period: Int) : GoalDialogUiEvent() data class PeriodUnitChanged(val periodUnit: GoalPeriodUnit) : GoalDialogUiEvent() data class GoalTypeChanged(val goalType: GoalType) : GoalDialogUiEvent() diff --git a/app/src/main/java/app/musikus/goals/presentation/GoalsViewModel.kt b/app/src/main/java/app/musikus/goals/presentation/GoalsViewModel.kt index 9f0fd469..87cf4470 100644 --- a/app/src/main/java/app/musikus/goals/presentation/GoalsViewModel.kt +++ b/app/src/main/java/app/musikus/goals/presentation/GoalsViewModel.kt @@ -41,9 +41,10 @@ import kotlin.time.Duration.Companion.seconds data class GoalDialogData( - val targetHours: Int? = null, - val targetMinutes: Int? = null, - val periodInPeriodUnits: Int? = null, + val targetHours: Int = 0, + val targetMinutes: Int = 0, + val periodInPeriodUnits: Int = 0, + val target: Duration = 0.seconds, val periodUnit: GoalPeriodUnit = GoalPeriodUnit.DEFAULT, val goalType: GoalType = GoalType.DEFAULT, val oneShot: Boolean = false, @@ -412,11 +413,11 @@ class GoalsViewModel @Inject constructor( } } - private fun onHoursChanged(hours: Int?) { + private fun onHoursChanged(hours: Int) { _dialogData.update { it?.copy(targetHours = hours) } } - private fun onMinutesChanged(minutes: Int?) { + private fun onMinutesChanged(minutes: Int) { _dialogData.update { it?.copy(targetMinutes = minutes) } }