Ensure the picker waits for pending updates

Particularly in development builds (and in tests), when typing in the
command palette, I tend to hit enter before the suggestions have
settled.
This commit is contained in:
Conrad Irwin 2023-09-19 22:20:20 -06:00
parent ba5d84f7e8
commit e27b7d7812

View file

@ -25,7 +25,8 @@ pub struct Picker<D: PickerDelegate> {
max_size: Vector2F, max_size: Vector2F,
theme: Arc<Mutex<Box<dyn Fn(&theme::Theme) -> theme::Picker>>>, theme: Arc<Mutex<Box<dyn Fn(&theme::Theme) -> theme::Picker>>>,
confirmed: bool, confirmed: bool,
pending_update_matches: Task<Option<()>>, pending_update_matches: Option<Task<Option<()>>>,
confirm_on_update: Option<bool>,
has_focus: bool, has_focus: bool,
} }
@ -208,7 +209,8 @@ impl<D: PickerDelegate> Picker<D> {
max_size: vec2f(540., 420.), max_size: vec2f(540., 420.),
theme, theme,
confirmed: false, confirmed: false,
pending_update_matches: Task::ready(None), pending_update_matches: None,
confirm_on_update: None,
has_focus: false, has_focus: false,
}; };
this.update_matches(String::new(), cx); this.update_matches(String::new(), cx);
@ -263,11 +265,13 @@ impl<D: PickerDelegate> Picker<D> {
pub fn update_matches(&mut self, query: String, cx: &mut ViewContext<Self>) { pub fn update_matches(&mut self, query: String, cx: &mut ViewContext<Self>) {
let update = self.delegate.update_matches(query, cx); let update = self.delegate.update_matches(query, cx);
self.matches_updated(cx); self.matches_updated(cx);
self.pending_update_matches = cx.spawn(|this, mut cx| async move { self.pending_update_matches = Some(cx.spawn(|this, mut cx| async move {
update.await; update.await;
this.update(&mut cx, |this, cx| this.matches_updated(cx)) this.update(&mut cx, |this, cx| {
.log_err() this.matches_updated(cx);
}); })
.log_err()
}));
} }
fn matches_updated(&mut self, cx: &mut ViewContext<Self>) { fn matches_updated(&mut self, cx: &mut ViewContext<Self>) {
@ -278,6 +282,11 @@ impl<D: PickerDelegate> Picker<D> {
ScrollTarget::Show(index) ScrollTarget::Show(index)
}; };
self.list_state.scroll_to(target); self.list_state.scroll_to(target);
self.pending_update_matches = None;
if let Some(secondary) = self.confirm_on_update.take() {
self.confirmed = true;
self.delegate.confirm(secondary, cx)
}
cx.notify(); cx.notify();
} }
@ -331,13 +340,21 @@ impl<D: PickerDelegate> Picker<D> {
} }
pub fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) { pub fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
self.confirmed = true; if self.pending_update_matches.is_some() {
self.delegate.confirm(false, cx); self.confirm_on_update = Some(false)
} else {
self.confirmed = true;
self.delegate.confirm(false, cx);
}
} }
pub fn secondary_confirm(&mut self, _: &SecondaryConfirm, cx: &mut ViewContext<Self>) { pub fn secondary_confirm(&mut self, _: &SecondaryConfirm, cx: &mut ViewContext<Self>) {
self.confirmed = true; if self.pending_update_matches.is_some() {
self.delegate.confirm(true, cx); self.confirm_on_update = Some(true)
} else {
self.confirmed = true;
self.delegate.confirm(true, cx);
}
} }
fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) { fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {