From 4b93a5ca4469ef6c3926b186fc2c4f7476ad69dd Mon Sep 17 00:00:00 2001 From: Michael Sloan Date: Sun, 8 Dec 2024 09:44:48 -0700 Subject: [PATCH] Make completions selector continue to show docs aside if ever shown (#21704) In #21286, documentation fetch was made more efficient by only fetching the current completion. This has a side effect of causing the aside to disappear and reappear when navigating the list. This is particularly jarring when there isn't enough space for the aside, causing the completions list to jump to the left. The solution here is to continue to show the aside even if the current selection does not yet have docs fetched. Release Notes: - N/A --- crates/editor/src/editor.rs | 50 ++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 0bd30465d9..b2abe8db80 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -141,7 +141,7 @@ use snippet::Snippet; use std::{ any::TypeId, borrow::Cow, - cell::RefCell, + cell::{Cell, RefCell}, cmp::{self, Ordering, Reverse}, mem, num::NonZeroU32, @@ -1008,6 +1008,7 @@ struct CompletionsMenu { selected_item: usize, scroll_handle: UniformListScrollHandle, selected_completion_resolve_debounce: Option>>, + aside_was_displayed: Cell, } impl CompletionsMenu { @@ -1040,6 +1041,7 @@ impl CompletionsMenu { selected_item: 0, scroll_handle: UniformListScrollHandle::new(), selected_completion_resolve_debounce: Some(Arc::new(Mutex::new(DebouncedDelay::new()))), + aside_was_displayed: Cell::new(false), } } @@ -1093,6 +1095,7 @@ impl CompletionsMenu { selected_item: 0, scroll_handle: UniformListScrollHandle::new(), selected_completion_resolve_debounce: Some(Arc::new(Mutex::new(DebouncedDelay::new()))), + aside_was_displayed: Cell::new(false), } } @@ -1231,7 +1234,7 @@ impl CompletionsMenu { let multiline_docs = if show_completion_documentation { let mat = &self.matches[selected_item]; - let multiline_docs = match &self.completions.read()[mat.candidate_id].documentation { + match &self.completions.read()[mat.candidate_id].documentation { Some(Documentation::MultiLinePlainText(text)) => { Some(div().child(SharedString::from(text.clone()))) } @@ -1244,24 +1247,37 @@ impl CompletionsMenu { cx, ))) } + Some(Documentation::Undocumented) if self.aside_was_displayed.get() => { + Some(div().child("No documentation")) + } _ => None, - }; - multiline_docs.map(|div| { - div.id("multiline_docs") - .max_h(max_height) - .flex_1() - .px_1p5() - .py_1() - .min_w(px(260.)) - .max_w(px(640.)) - .w(px(500.)) - .overflow_y_scroll() - .occlude() - }) + } } else { None }; + let aside_contents = if let Some(multiline_docs) = multiline_docs { + Some(multiline_docs) + } else if self.aside_was_displayed.get() { + Some(div().child("Fetching documentation...")) + } else { + None + }; + self.aside_was_displayed.set(aside_contents.is_some()); + + let aside_contents = aside_contents.map(|div| { + div.id("multiline_docs") + .max_h(max_height) + .flex_1() + .px_1p5() + .py_1() + .min_w(px(260.)) + .max_w(px(640.)) + .w(px(500.)) + .overflow_y_scroll() + .occlude() + }); + let list = uniform_list( cx.view().clone(), "completions", @@ -1357,8 +1373,8 @@ impl CompletionsMenu { Popover::new() .child(list) - .when_some(multiline_docs, |popover, multiline_docs| { - popover.aside(multiline_docs) + .when_some(aside_contents, |popover, aside_contents| { + popover.aside(aside_contents) }) .into_any_element() }