fix: resolve race condition in ButtonAction using a generation counter for safety
All checks were successful
Build MIPS Binary / build (push) Successful in 1m52s
All checks were successful
Build MIPS Binary / build (push) Successful in 1m52s
This commit is contained in:
@@ -11,16 +11,22 @@ pub fn ButtonAction(
|
|||||||
#[prop(default = ButtonVariant::Default)] variant: ButtonVariant,
|
#[prop(default = ButtonVariant::Default)] variant: ButtonVariant,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
let is_holding = RwSignal::new(false);
|
let is_holding = RwSignal::new(false);
|
||||||
|
let generation = StoredValue::new(0u64);
|
||||||
|
|
||||||
|
let on_down = move |_| {
|
||||||
|
generation.update_value(|g| *g += 1);
|
||||||
|
is_holding.set(true);
|
||||||
|
};
|
||||||
|
|
||||||
// Explicitly define handlers to avoid type mismatches between Mouse and Touch events
|
|
||||||
let on_down = move |_| is_holding.set(true);
|
|
||||||
let on_up = move |_| is_holding.set(false);
|
let on_up = move |_| is_holding.set(false);
|
||||||
|
|
||||||
Effect::new(move |_| {
|
Effect::new(move |_| {
|
||||||
if is_holding.get() {
|
if is_holding.get() {
|
||||||
|
let current_gen = generation.get_value();
|
||||||
leptos::task::spawn_local(async move {
|
leptos::task::spawn_local(async move {
|
||||||
gloo_timers::future::TimeoutFuture::new(hold_duration as u32).await;
|
gloo_timers::future::TimeoutFuture::new(hold_duration as u32).await;
|
||||||
if is_holding.get_untracked() {
|
// Double validation: Is user still holding AND is it the SAME hold attempt?
|
||||||
|
if is_holding.get_untracked() && generation.get_value() == current_gen {
|
||||||
on_action.run(());
|
on_action.run(());
|
||||||
is_holding.set(false);
|
is_holding.set(false);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user