debounced_delay.rs

 1use futures::{channel::oneshot, FutureExt};
 2use gpui::{ModelContext, Task};
 3use std::{marker::PhantomData, time::Duration};
 4
 5pub struct DebouncedDelay<E: 'static> {
 6    task: Option<Task<()>>,
 7    cancel_channel: Option<oneshot::Sender<()>>,
 8    _phantom_data: PhantomData<E>,
 9}
10
11impl<E: 'static> DebouncedDelay<E> {
12    pub fn new() -> Self {
13        Self {
14            task: None,
15            cancel_channel: None,
16            _phantom_data: PhantomData,
17        }
18    }
19
20    pub fn fire_new<F>(&mut self, delay: Duration, cx: &mut ModelContext<E>, func: F)
21    where
22        F: 'static + Send + FnOnce(&mut E, &mut ModelContext<E>) -> Task<()>,
23    {
24        if let Some(channel) = self.cancel_channel.take() {
25            _ = channel.send(());
26        }
27
28        let (sender, mut receiver) = oneshot::channel::<()>();
29        self.cancel_channel = Some(sender);
30
31        let previous_task = self.task.take();
32        self.task = Some(cx.spawn(move |model, mut cx| async move {
33            let mut timer = cx.background_executor().timer(delay).fuse();
34            if let Some(previous_task) = previous_task {
35                previous_task.await;
36            }
37
38            futures::select_biased! {
39                _ = receiver => return,
40                _ = timer => {}
41            }
42
43            if let Ok(task) = model.update(&mut cx, |project, cx| (func)(project, cx)) {
44                task.await;
45            }
46        }));
47    }
48}