Disable mutliple click (parallel or serial) on a room (#4683)
* Disable mutliple click (parallel or serial) on a room (Fixes #4619) * Rename method from FirstThrottler * Move check to the Compose and add unit test on it.
This commit is contained in:
parent
c9ec26f87c
commit
f6cbca4a82
4 changed files with 84 additions and 27 deletions
|
|
@ -6,36 +6,29 @@
|
|||
*/
|
||||
package io.element.android.libraries.androidutils.throttler
|
||||
|
||||
import android.os.SystemClock
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* Simple ThrottleFirst
|
||||
* See https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/throttleFirst.png
|
||||
*/
|
||||
class FirstThrottler(private val minimumInterval: Long = 800) {
|
||||
private var lastDate = 0L
|
||||
class FirstThrottler(
|
||||
private val minimumInterval: Long = 800,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
) {
|
||||
private val canHandle = AtomicBoolean(true)
|
||||
|
||||
sealed interface CanHandleResult {
|
||||
data object Yes : CanHandleResult
|
||||
data class No(val shouldWaitMillis: Long) : CanHandleResult
|
||||
|
||||
fun waitMillis(): Long {
|
||||
return when (this) {
|
||||
Yes -> 0
|
||||
is No -> shouldWaitMillis
|
||||
fun canHandle(): Boolean {
|
||||
return canHandle.getAndSet(false).also { result ->
|
||||
if (result) {
|
||||
coroutineScope.launch {
|
||||
delay(minimumInterval)
|
||||
canHandle.set(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun canHandle(): CanHandleResult {
|
||||
val now = SystemClock.elapsedRealtime()
|
||||
val delaySinceLast = now - lastDate
|
||||
if (delaySinceLast > minimumInterval) {
|
||||
lastDate = now
|
||||
return CanHandleResult.Yes
|
||||
}
|
||||
|
||||
// Too early
|
||||
return CanHandleResult.No(minimumInterval - delaySinceLast)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
||||
package io.element.android.libraries.androidutils.throttler
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.advanceTimeBy
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class FirstThrottlerTest {
|
||||
@Test
|
||||
fun `throttle canHandle returns the expected result`() = runTest {
|
||||
val throttler = FirstThrottler(
|
||||
minimumInterval = 300,
|
||||
coroutineScope = backgroundScope,
|
||||
)
|
||||
assertThat(throttler.canHandle()).isTrue()
|
||||
assertThat(throttler.canHandle()).isFalse()
|
||||
advanceTimeBy(200)
|
||||
assertThat(throttler.canHandle()).isFalse()
|
||||
advanceTimeBy(110)
|
||||
assertThat(throttler.canHandle()).isTrue()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue