tauri_store_utils/time/
debounce.rs1use crate::manager::ManagerExt;
2use crate::task::{OptionalAbortHandle, RemoteCallable};
3use parking_lot::Mutex;
4use std::future::Future;
5use std::sync::{Arc, Weak};
6use std::time::Duration;
7use tauri::{AppHandle, Runtime};
8use tokio::select;
9use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
10use tokio::task::AbortHandle;
11use tokio::time::sleep;
12
13type DebouncedFn<R, Fut> = dyn Fn(AppHandle<R>) -> Fut + Send + Sync + 'static;
14
15pub struct Debounce<R, T, Fut>
17where
18 R: Runtime,
19 T: Send + 'static,
20 Fut: Future<Output = T> + Send + 'static,
21{
22 inner: Arc<DebouncedFn<R, Fut>>,
23 sender: Arc<OptionalSender>,
24 abort_handle: Arc<OptionalAbortHandle>,
25 duration: Duration,
26}
27
28impl<R, T, Fut> Debounce<R, T, Fut>
29where
30 R: Runtime,
31 T: Send + 'static,
32 Fut: Future<Output = T> + Send + 'static,
33{
34 pub fn new<F>(duration: Duration, f: F) -> Self
35 where
36 F: Fn(AppHandle<R>) -> Fut + Send + Sync + 'static,
37 {
38 Self {
39 inner: Arc::new(f),
40 sender: Arc::new(OptionalSender::default()),
41 abort_handle: Arc::new(OptionalAbortHandle::default()),
42 duration,
43 }
44 }
45
46 pub fn call(&self, app: &AppHandle<R>) {
47 if self.sender.send() {
48 return;
49 }
50
51 let (tx, rx) = unbounded_channel();
52 let actor = Actor {
53 function: Arc::downgrade(&self.inner),
54 receiver: rx,
55 duration: self.duration,
56 };
57
58 self.sender.inner.lock().replace(tx);
59 self.abort_handle.replace(actor.run(app));
60 }
61
62 pub fn abort(&self) {
63 self.sender.inner.lock().take();
64 self.abort_handle.abort();
65 }
66}
67
68impl<R, T, Fut> RemoteCallable<AppHandle<R>> for Debounce<R, T, Fut>
69where
70 R: Runtime,
71 T: Send + 'static,
72 Fut: Future<Output = T> + Send + 'static,
73{
74 fn call(&self, app: &AppHandle<R>) {
75 self.call(app);
76 }
77
78 fn abort(&self) {
79 self.abort();
80 }
81}
82
83impl<R, T, Fut> Drop for Debounce<R, T, Fut>
84where
85 R: Runtime,
86 T: Send + 'static,
87 Fut: Future<Output = T> + Send + 'static,
88{
89 fn drop(&mut self) {
90 self.abort();
91 }
92}
93
94struct Actor<R, T, Fut>
95where
96 R: Runtime,
97 T: Send + 'static,
98 Fut: Future<Output = T> + Send + 'static,
99{
100 function: Weak<DebouncedFn<R, Fut>>,
101 receiver: UnboundedReceiver<Message>,
102 duration: Duration,
103}
104
105impl<R, T, Fut> Actor<R, T, Fut>
106where
107 R: Runtime,
108 T: Send + 'static,
109 Fut: Future<Output = T> + Send + 'static,
110{
111 fn run(mut self, app: &AppHandle<R>) -> AbortHandle {
112 app.spawn(move |app| async move {
113 loop {
114 select! {
115 message = self.receiver.recv() => {
116 if message.is_none() { break }
117 }
118 () = sleep(self.duration) => {
119 self.receiver.close();
120 if let Some(f) = self.function.upgrade() {
121 (f)(app).await;
122 }
123
124 break;
125 }
126 }
127 }
128 })
129 }
130}
131
132#[derive(Default)]
133pub(super) struct OptionalSender {
134 pub(super) inner: Mutex<Option<UnboundedSender<Message>>>,
135}
136
137impl OptionalSender {
138 pub(super) fn send(&self) -> bool {
139 self
140 .inner
141 .lock()
142 .as_ref()
143 .map(|it| it.send(Message::Call).is_ok())
144 .unwrap_or(false)
145 }
146}
147
148pub(super) enum Message {
149 Call,
150}