From 7fa4474191430dced0c74dfc7ede6ab83d4300bc Mon Sep 17 00:00:00 2001 From: Maximilian Keppeler Date: Sun, 19 Feb 2023 21:06:24 +0100 Subject: [PATCH] (Clock) Fix simultaneous clicks leading to crash #28 --- .../maxkeppeler/sheets/clock/ClockState.kt | 25 +++++++++++------- .../sheets/clock/utils/Constants.kt | 2 ++ .../sheets/core/models/base/Debouncer.kt | 26 +++++++++++++++++++ 3 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 core/src/main/java/com/maxkeppeker/sheets/core/models/base/Debouncer.kt diff --git a/clock/src/main/java/com/maxkeppeler/sheets/clock/ClockState.kt b/clock/src/main/java/com/maxkeppeler/sheets/clock/ClockState.kt index d521e64f..c9ed6eab 100644 --- a/clock/src/main/java/com/maxkeppeler/sheets/clock/ClockState.kt +++ b/clock/src/main/java/com/maxkeppeler/sheets/clock/ClockState.kt @@ -23,6 +23,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.Saver import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import com.maxkeppeker.sheets.core.models.base.Debouncer import com.maxkeppeker.sheets.core.views.BaseTypeState import com.maxkeppeler.sheets.clock.models.ClockConfig import com.maxkeppeler.sheets.clock.models.ClockSelection @@ -55,6 +56,8 @@ internal class ClockState( var disabledKeys by mutableStateOf(getCurrentDisabledKeys()) var valid by mutableStateOf(isValid()) + private val debouncer = Debouncer(Constants.DEBOUNCE_KEY_CLICK_DURATION) + private fun isValid(): Boolean = config.boundary?.let { time in it } ?: true private fun isInit24HourFormat(): Boolean { @@ -110,16 +113,18 @@ internal class ClockState( } fun onEnterValue(value: Int) { - timeTextValues = inputValue( - timeValues = timeTextValues, - is24hourFormat = is24HourFormat, - currentIndex = valueIndex, - groupIndex = groupIndex, - newValue = value, - onNextIndex = this::onNextAction - ) - refreshDisabledKeys() - refreshTimeValue() + debouncer.debounce { // https://github.com/maxkeppeler/sheets-compose-dialogs/issues/28 + timeTextValues = inputValue( + timeValues = timeTextValues, + is24hourFormat = is24HourFormat, + currentIndex = valueIndex, + groupIndex = groupIndex, + newValue = value, + onNextIndex = this::onNextAction + ) + refreshDisabledKeys() + refreshTimeValue() + } } fun onPrevAction() { diff --git a/clock/src/main/java/com/maxkeppeler/sheets/clock/utils/Constants.kt b/clock/src/main/java/com/maxkeppeler/sheets/clock/utils/Constants.kt index b4665ab1..cefa5943 100644 --- a/clock/src/main/java/com/maxkeppeler/sheets/clock/utils/Constants.kt +++ b/clock/src/main/java/com/maxkeppeler/sheets/clock/utils/Constants.kt @@ -35,4 +35,6 @@ internal object Constants { const val KEYBOARD_ALPHA_ITEM_DISABLED = 0.3f const val KEYBOARD_ACTION_BACKGROUND_SURFACE_ALPHA = 0.3f + + const val DEBOUNCE_KEY_CLICK_DURATION = 100L } \ No newline at end of file diff --git a/core/src/main/java/com/maxkeppeker/sheets/core/models/base/Debouncer.kt b/core/src/main/java/com/maxkeppeker/sheets/core/models/base/Debouncer.kt new file mode 100644 index 00000000..a65f5850 --- /dev/null +++ b/core/src/main/java/com/maxkeppeker/sheets/core/models/base/Debouncer.kt @@ -0,0 +1,26 @@ +package com.maxkeppeker.sheets.core.models.base + +/** + * A class for time-based debouncing. + * + * @param delay The delay time in milliseconds for debouncing. + */ +class Debouncer(private val delay: Long) { + + private var lastTime = 0L + + private val currentTime: Long + get() = System.currentTimeMillis() + + /** + * Debounces the given action by delaying its execution for the specified delay time. + * If the action is called before the delay time has passed since the last call, the action is not executed. + * + * @param action The action to be executed after the delay has passed. + */ + fun debounce(action: () -> Unit) { + if (currentTime - lastTime < delay) return + lastTime = currentTime + action.invoke() + } +} \ No newline at end of file