Skip to content

Commit

Permalink
revision: debounce
Browse files Browse the repository at this point in the history
  • Loading branch information
DogeDark committed Apr 27, 2024
1 parent 9aefd59 commit 1207b3c
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 34 deletions.
7 changes: 4 additions & 3 deletions examples/timing/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ fn app() -> Element {
count += 1;
});

let mut debounce = use_debounce(Duration::from_millis(2000));
let mut debounce = use_debounce(Duration::from_millis(2000), move || count.set(0));

rsx! {
p { "{count}" },
button {
onclick: move |_| {
debounce.action(|| println!("debounce ran!"));
// Reset the counter after 2 seconds pass since the last click.
debounce.action();
},
"Click!"
"Reset the counter! (2 second debounce)"
}
}
}
4 changes: 2 additions & 2 deletions sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ dioxus-signals = { version = "0.5.0-alpha.2", features = [
yazi = { version = "0.1.4", optional = true }
tracing = "0.1.40"

# Used by: interval
# Used by: timing
gloo-timers = { version = "0.3.0", optional = true }

# Used by: interval & storage
# Used by: timing & storage
tokio = { version = "1.33.0", optional = true }

# # # # # # # # #
Expand Down
52 changes: 23 additions & 29 deletions sdk/src/utils/timing/debounce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,27 @@ use futures::{
channel::mpsc::{self, UnboundedSender as Sender},
StreamExt,
};
use std::time::{Duration, Instant};

type DebounceCallback = Box<dyn FnOnce()>;
use std::time::Duration;

/// The interface for calling a debounce.
///
/// See [`use_debounce`] for more information.
#[derive(Clone, Copy, PartialEq)]
pub struct UseDebounce {
sender: Signal<Sender<DebounceCallback>>,
sender: Signal<Sender<bool>>,
}

impl UseDebounce {
/// Will run the provided function if the debounce period has passed.
pub fn action(&mut self, cb: impl FnOnce() + 'static) {
self.sender.write().unbounded_send(Box::new(cb)).ok();
/// Will start the debounce countdown, resetting it if already started.
pub fn action(&mut self) {
self.sender.write().unbounded_send(true).ok();
}
}

/// A hook for allowing a function to be called only after a provided [`Duration`] has passed.
///
/// This hook only checks if the callback can be ran when the [`UseDebounce::action`] method is called.
/// It will not queue function calls.
/// Once the [`UseDebounce::action`] method is called, a timer will start counting down until
/// the callback is ran. If the [`UseDebounce::action`] method is called again, the timer will restart.
///
/// # Example
///
Expand All @@ -35,46 +33,42 @@ impl UseDebounce {
/// use std::time::Duration;
///
/// fn App() -> Element {
/// let mut debounce = use_debounce(Duration::from_millis(2000));
/// let mut debounce = use_debounce(Duration::from_millis(2000), || println!("ran"));
///
/// rsx! {
/// button {
/// onclick: move |_| {
/// debounce.action(|| println!("ran"));
/// debounce.action();
/// },
/// "Click!"
/// }
/// }
/// }
/// ```
pub fn use_debounce(wait_period: Duration) -> UseDebounce {
pub fn use_debounce(time: Duration, cb: impl FnOnce() + Copy + 'static) -> UseDebounce {
use_hook(|| {
let (sender, mut receiver) = mpsc::unbounded::<DebounceCallback>();
let (sender, mut receiver) = mpsc::unbounded();
let debouncer = UseDebounce {
sender: Signal::new(sender),
};

spawn(async move {
let mut last_called = None;
let mut current_task: Option<Task> = None;

loop {
if let Some(cb) = receiver.next().await {
let now = Instant::now();
if let Some(_) = receiver.next().await {
if let Some(task) = current_task {
task.cancel();
}

// Check if enough time has passed to run the callback.
if let Some(last) = last_called {
if now.duration_since(last) >= wait_period {
last_called = Some(now);
cb();
}
} else {
// Callback hasn't been ran yet.
last_called = Some(now);
current_task = Some(spawn(async move {
tokio::time::sleep(time).await;
cb();
}
}));
}
}
});

UseDebounce {
sender: Signal::new(sender),
}
debouncer
})
}

0 comments on commit 1207b3c

Please sign in to comment.