sql_cli/utils/debouncer.rs
1use std::time::{Duration, Instant};
2
3/// A simple debouncer that tracks when an action should be triggered
4/// after a period of inactivity
5#[derive(Debug, Clone)]
6pub struct Debouncer {
7 /// The duration to wait after the last event before triggering
8 delay: Duration,
9 /// When the last event occurred
10 last_event: Option<Instant>,
11 /// Whether we have a pending trigger
12 pending: bool,
13}
14
15impl Debouncer {
16 /// Create a new debouncer with the specified delay in milliseconds
17 pub fn new(delay_ms: u64) -> Self {
18 Self {
19 delay: Duration::from_millis(delay_ms),
20 last_event: None,
21 pending: false,
22 }
23 }
24
25 /// Register that an event occurred
26 pub fn trigger(&mut self) {
27 self.last_event = Some(Instant::now());
28 self.pending = true;
29 }
30
31 /// Check if enough time has passed to execute the debounced action
32 /// Returns true if the action should be executed
33 pub fn should_execute(&mut self) -> bool {
34 if !self.pending {
35 return false;
36 }
37
38 if let Some(last) = self.last_event {
39 if last.elapsed() >= self.delay {
40 self.pending = false;
41 self.last_event = None;
42 return true;
43 }
44 }
45 false
46 }
47
48 /// Get the time remaining before the action will trigger
49 /// Returns None if no action is pending
50 pub fn time_remaining(&self) -> Option<Duration> {
51 if !self.pending {
52 return None;
53 }
54
55 self.last_event.map(|last| {
56 let elapsed = last.elapsed();
57 if elapsed >= self.delay {
58 Duration::from_millis(0)
59 } else {
60 self.delay - elapsed
61 }
62 })
63 }
64
65 /// Reset the debouncer, canceling any pending action
66 pub fn reset(&mut self) {
67 self.last_event = None;
68 self.pending = false;
69 }
70
71 /// Check if there's a pending action
72 pub fn is_pending(&self) -> bool {
73 self.pending
74 }
75}
76
77/// Trait for widgets that support debounced input
78pub trait DebouncedInput {
79 /// Called when input changes but should be debounced
80 fn on_input_changed(&mut self);
81
82 /// Called when the debounce timer expires and action should be taken
83 fn on_debounced_execute(&mut self);
84
85 /// Check if debouncing should trigger execution
86 fn check_debounce(&mut self) -> bool;
87}