From 8b47cd5aba7f58e7512bc9fc3a544ba365c1b606 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 12 May 2025 19:25:43 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/core/ui/extensions/ModifierExt.kt | 30 +++++++++++++++++++ .../core/ui/utils/MultipleClickPreventer.kt | 10 ++++++- .../v2/common/ui/SendNavigationButtons.kt | 19 ++++++++---- 3 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 core/ui/src/main/java/com/tangem/core/ui/extensions/ModifierExt.kt diff --git a/core/ui/src/main/java/com/tangem/core/ui/extensions/ModifierExt.kt b/core/ui/src/main/java/com/tangem/core/ui/extensions/ModifierExt.kt new file mode 100644 index 0000000000..469e048635 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/extensions/ModifierExt.kt @@ -0,0 +1,30 @@ +package com.tangem.core.ui.extensions + +import androidx.compose.foundation.LocalIndication +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import androidx.compose.ui.semantics.Role +import com.tangem.core.ui.utils.MultipleClickPreventer + +/** + * Clickable modifier with debounce multiple click in a short period of time + */ +fun Modifier.clickableSingle( + enabled: Boolean = true, + onClickLabel: String? = null, + role: Role? = null, + onClick: () -> Unit, +) = composed { + val multipleEventsCutter = remember { MultipleClickPreventer.get() } + Modifier.clickable( + enabled = enabled, + onClickLabel = onClickLabel, + onClick = { multipleEventsCutter.processEvent { onClick() } }, + role = role, + indication = LocalIndication.current, + interactionSource = remember { MutableInteractionSource() }, + ) +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/utils/MultipleClickPreventer.kt b/core/ui/src/main/java/com/tangem/core/ui/utils/MultipleClickPreventer.kt index 15ede204ae..767e1ada4d 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/utils/MultipleClickPreventer.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/utils/MultipleClickPreventer.kt @@ -2,6 +2,9 @@ package com.tangem.core.ui.utils import android.os.SystemClock +/** + * Debounce multiple events (e.i. clicks, etc) in a short period of time + */ interface MultipleClickPreventer { fun processEvent(event: () -> Unit) @@ -24,4 +27,9 @@ private class DefaultMultipleClickPreventer : MultipleClickPreventer { companion object { private const val TIME_BETWEEN_CLICK_IN_MS = 500L } -} \ No newline at end of file +} + +/** + * Debounce multiple events (e.i. clicks, etc) in a short period of time + */ +fun singleEvent(event: () -> Unit) = MultipleClickPreventer.get().processEvent(event) \ No newline at end of file diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/ui/SendNavigationButtons.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/ui/SendNavigationButtons.kt index 581e14ba92..70d852dff8 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/ui/SendNavigationButtons.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/common/ui/SendNavigationButtons.kt @@ -2,7 +2,6 @@ package com.tangem.features.send.v2.common.ui import androidx.compose.animation.* import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth @@ -26,10 +25,12 @@ import com.tangem.core.ui.components.SpacerW12 import com.tangem.core.ui.components.buttons.common.TangemButton import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults -import com.tangem.features.send.v2.send.ui.state.ButtonsUM +import com.tangem.core.ui.extensions.clickableSingle import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.utils.singleEvent import com.tangem.features.send.v2.common.ui.state.NavigationUM +import com.tangem.features.send.v2.send.ui.state.ButtonsUM @Composable internal fun SendNavigationButtons(navigationUM: NavigationUM, modifier: Modifier = Modifier) { @@ -70,7 +71,7 @@ private fun SendNavigationButton(navigationUM: NavigationUM, modifier: Modifier modifier = Modifier .clip(RoundedCornerShape(16.dp)) .background(TangemTheme.colors.button.secondary) - .clickable(onClick = wrappedNavigationUM.onClick) + .clickableSingle(onClick = wrappedNavigationUM.onClick) .padding(12.dp), ) SpacerW12() @@ -110,7 +111,11 @@ private fun SendDoneButtons(pairButtonsUM: ButtonsUM.SecondaryPairButtonsUM?, mo SecondaryButtonIconStart( text = wrappedPairButtonsUM.leftText.resolveReference(), iconResId = wrappedPairButtonsUM.leftIconResId!!, - onClick = wrappedPairButtonsUM.onLeftClick, + onClick = { + singleEvent { + wrappedPairButtonsUM.onLeftClick + } + }, modifier = Modifier.weight(1f), ) SpacerW12() @@ -118,8 +123,10 @@ private fun SendDoneButtons(pairButtonsUM: ButtonsUM.SecondaryPairButtonsUM?, mo text = wrappedPairButtonsUM.rightText.resolveReference(), iconResId = wrappedPairButtonsUM.rightIconResId!!, onClick = { - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - wrappedPairButtonsUM.onRightClick() + singleEvent { + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + wrappedPairButtonsUM.onRightClick() + } }, modifier = Modifier.weight(1f), )