assistant: Adjust the toolbar design (#20101)
This PR's most relevant change is removing the three-dot menu dropdown from the assistant toolbar. The "Regenerate Title" button is now only visible on hover and it appears on the far right of the title input. <img width="700" alt="Screenshot 2024-11-04 at 13 31 37" src="https://github.com/user-attachments/assets/891703af-7985-4b16-bb5e-d852491abd6f"> Release Notes: - N/A
This commit is contained in:
parent
83ad28dfe7
commit
02b1e3a3c1
3 changed files with 77 additions and 133 deletions
5
assets/icons/refresh_title.svg
Normal file
5
assets/icons/refresh_title.svg
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M7 21V12M7 12H3M7 12H11" stroke="black" stroke-width="2" stroke-linecap="round"/>
|
||||||
|
<path d="M21 19L16 19L16 14" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M7.99987 5.07027L7.49915 4.20467L7.99987 5.07027ZM6.04652 5.25026C5.63245 5.61573 5.59305 6.24766 5.95851 6.66173C6.32398 7.0758 6.95592 7.1152 7.36999 6.74974L6.04652 5.25026ZM11.9999 5C15.8659 5 18.9999 8.13401 18.9999 12H20.9999C20.9999 7.02944 16.9705 3 11.9999 3V5ZM18.9999 12C18.9999 14.2101 17.9768 16.1806 16.3744 17.4651L17.6254 19.0256C19.6809 17.3779 20.9999 14.8426 20.9999 12H18.9999ZM8.5006 5.93588C9.5292 5.34086 10.7232 5 11.9999 5V3C10.3623 3 8.82395 3.4383 7.49915 4.20467L8.5006 5.93588ZM7.36999 6.74974C7.71803 6.44255 8.09667 6.16954 8.5006 5.93588L7.49915 4.20467C6.9797 4.50515 6.49329 4.85593 6.04652 5.25026L7.36999 6.74974Z" fill="black"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 979 B |
|
@ -441,48 +441,49 @@ impl AssistantPanel {
|
||||||
.map_or(false, |item| item.downcast::<ContextHistory>().is_some()),
|
.map_or(false, |item| item.downcast::<ContextHistory>().is_some()),
|
||||||
);
|
);
|
||||||
let _pane = cx.view().clone();
|
let _pane = cx.view().clone();
|
||||||
let right_children = h_flex()
|
let right_children =
|
||||||
.gap(Spacing::Small.rems(cx))
|
h_flex()
|
||||||
.child(
|
.gap(Spacing::XSmall.rems(cx))
|
||||||
IconButton::new("new-context", IconName::Plus)
|
.child(
|
||||||
.on_click(
|
IconButton::new("new-context", IconName::Plus)
|
||||||
cx.listener(|_, _, cx| {
|
.on_click(cx.listener(|_, _, cx| {
|
||||||
cx.dispatch_action(NewContext.boxed_clone())
|
cx.dispatch_action(NewContext.boxed_clone())
|
||||||
}),
|
|
||||||
)
|
|
||||||
.tooltip(move |cx| {
|
|
||||||
Tooltip::for_action_in(
|
|
||||||
"New Context",
|
|
||||||
&NewContext,
|
|
||||||
&focus_handle,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.child(
|
|
||||||
PopoverMenu::new("assistant-panel-popover-menu")
|
|
||||||
.trigger(
|
|
||||||
IconButton::new("menu", IconName::Menu).icon_size(IconSize::Small),
|
|
||||||
)
|
|
||||||
.menu(move |cx| {
|
|
||||||
let zoom_label = if _pane.read(cx).is_zoomed() {
|
|
||||||
"Zoom Out"
|
|
||||||
} else {
|
|
||||||
"Zoom In"
|
|
||||||
};
|
|
||||||
let focus_handle = _pane.focus_handle(cx);
|
|
||||||
Some(ContextMenu::build(cx, move |menu, _| {
|
|
||||||
menu.context(focus_handle.clone())
|
|
||||||
.action("New Context", Box::new(NewContext))
|
|
||||||
.action("History", Box::new(DeployHistory))
|
|
||||||
.action("Prompt Library", Box::new(DeployPromptLibrary))
|
|
||||||
.action("Configure", Box::new(ShowConfiguration))
|
|
||||||
.action(zoom_label, Box::new(ToggleZoom))
|
|
||||||
}))
|
}))
|
||||||
}),
|
.tooltip(move |cx| {
|
||||||
)
|
Tooltip::for_action_in(
|
||||||
.into_any_element()
|
"New Context",
|
||||||
.into();
|
&NewContext,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
PopoverMenu::new("assistant-panel-popover-menu")
|
||||||
|
.trigger(
|
||||||
|
IconButton::new("menu", IconName::EllipsisVertical)
|
||||||
|
.icon_size(IconSize::Small)
|
||||||
|
.tooltip(|cx| Tooltip::text("Toggle Assistant Menu", cx)),
|
||||||
|
)
|
||||||
|
.menu(move |cx| {
|
||||||
|
let zoom_label = if _pane.read(cx).is_zoomed() {
|
||||||
|
"Zoom Out"
|
||||||
|
} else {
|
||||||
|
"Zoom In"
|
||||||
|
};
|
||||||
|
let focus_handle = _pane.focus_handle(cx);
|
||||||
|
Some(ContextMenu::build(cx, move |menu, _| {
|
||||||
|
menu.context(focus_handle.clone())
|
||||||
|
.action("New Context", Box::new(NewContext))
|
||||||
|
.action("History", Box::new(DeployHistory))
|
||||||
|
.action("Prompt Library", Box::new(DeployPromptLibrary))
|
||||||
|
.action("Configure", Box::new(ShowConfiguration))
|
||||||
|
.action(zoom_label, Box::new(ToggleZoom))
|
||||||
|
}))
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.into_any_element()
|
||||||
|
.into();
|
||||||
|
|
||||||
(Some(left_children.into_any_element()), right_children)
|
(Some(left_children.into_any_element()), right_children)
|
||||||
});
|
});
|
||||||
|
@ -4367,26 +4368,11 @@ impl FollowableItem for ContextEditor {
|
||||||
|
|
||||||
pub struct ContextEditorToolbarItem {
|
pub struct ContextEditorToolbarItem {
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
workspace: WeakView<Workspace>,
|
|
||||||
active_context_editor: Option<WeakView<ContextEditor>>,
|
active_context_editor: Option<WeakView<ContextEditor>>,
|
||||||
model_summary_editor: View<Editor>,
|
model_summary_editor: View<Editor>,
|
||||||
model_selector_menu_handle: PopoverMenuHandle<Picker<ModelPickerDelegate>>,
|
model_selector_menu_handle: PopoverMenuHandle<Picker<ModelPickerDelegate>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn active_editor_focus_handle(
|
|
||||||
workspace: &WeakView<Workspace>,
|
|
||||||
cx: &WindowContext<'_>,
|
|
||||||
) -> Option<FocusHandle> {
|
|
||||||
workspace.upgrade().and_then(|workspace| {
|
|
||||||
Some(
|
|
||||||
workspace
|
|
||||||
.read(cx)
|
|
||||||
.active_item_as::<Editor>(cx)?
|
|
||||||
.focus_handle(cx),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_inject_context_menu(
|
fn render_inject_context_menu(
|
||||||
active_context_editor: WeakView<ContextEditor>,
|
active_context_editor: WeakView<ContextEditor>,
|
||||||
cx: &mut WindowContext<'_>,
|
cx: &mut WindowContext<'_>,
|
||||||
|
@ -4413,7 +4399,6 @@ impl ContextEditorToolbarItem {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
fs: workspace.app_state().fs.clone(),
|
fs: workspace.app_state().fs.clone(),
|
||||||
workspace: workspace.weak_handle(),
|
|
||||||
active_context_editor: None,
|
active_context_editor: None,
|
||||||
model_summary_editor,
|
model_summary_editor,
|
||||||
model_selector_menu_handle,
|
model_selector_menu_handle,
|
||||||
|
@ -4466,16 +4451,30 @@ impl ContextEditorToolbarItem {
|
||||||
impl Render for ContextEditorToolbarItem {
|
impl Render for ContextEditorToolbarItem {
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
let left_side = h_flex()
|
let left_side = h_flex()
|
||||||
.pl_1()
|
.group("chat-title-group")
|
||||||
.gap_2()
|
.pl_0p5()
|
||||||
.flex_1()
|
.gap_1()
|
||||||
.min_w(rems(DEFAULT_TAB_TITLE.len() as f32))
|
.items_center()
|
||||||
.when(self.active_context_editor.is_some(), |left_side| {
|
.flex_grow()
|
||||||
left_side.child(self.model_summary_editor.clone())
|
.child(
|
||||||
});
|
div()
|
||||||
|
.w_full()
|
||||||
|
.when(self.active_context_editor.is_some(), |left_side| {
|
||||||
|
left_side.child(self.model_summary_editor.clone())
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div().visible_on_hover("chat-title-group").child(
|
||||||
|
IconButton::new("regenerate-context", IconName::RefreshTitle)
|
||||||
|
.shape(ui::IconButtonShape::Square)
|
||||||
|
.tooltip(|cx| Tooltip::text("Regenerate Title", cx))
|
||||||
|
.on_click(cx.listener(move |_, _, cx| {
|
||||||
|
cx.emit(ContextEditorToolbarItemEvent::RegenerateSummary)
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
);
|
||||||
let active_provider = LanguageModelRegistry::read_global(cx).active_provider();
|
let active_provider = LanguageModelRegistry::read_global(cx).active_provider();
|
||||||
let active_model = LanguageModelRegistry::read_global(cx).active_model();
|
let active_model = LanguageModelRegistry::read_global(cx).active_model();
|
||||||
let weak_self = cx.view().downgrade();
|
|
||||||
let right_side = h_flex()
|
let right_side = h_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
// TODO display this in a nicer way, once we have a design for it.
|
// TODO display this in a nicer way, once we have a design for it.
|
||||||
|
@ -4488,7 +4487,6 @@ impl Render for ContextEditorToolbarItem {
|
||||||
// let scan_items_remaining = cx.update_global(|db: &mut SemanticDb, cx| {
|
// let scan_items_remaining = cx.update_global(|db: &mut SemanticDb, cx| {
|
||||||
// project.and_then(|project| db.remaining_summaries(&project, cx))
|
// project.and_then(|project| db.remaining_summaries(&project, cx))
|
||||||
// });
|
// });
|
||||||
|
|
||||||
// scan_items_remaining
|
// scan_items_remaining
|
||||||
// .map(|remaining_items| format!("Files to scan: {}", remaining_items))
|
// .map(|remaining_items| format!("Files to scan: {}", remaining_items))
|
||||||
// })
|
// })
|
||||||
|
@ -4510,9 +4508,13 @@ impl Render for ContextEditorToolbarItem {
|
||||||
(Some(provider), Some(model)) => h_flex()
|
(Some(provider), Some(model)) => h_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.child(
|
.child(
|
||||||
Icon::new(model.icon().unwrap_or_else(|| provider.icon()))
|
Icon::new(
|
||||||
.color(Color::Muted)
|
model
|
||||||
.size(IconSize::XSmall),
|
.icon()
|
||||||
|
.unwrap_or_else(|| provider.icon()),
|
||||||
|
)
|
||||||
|
.color(Color::Muted)
|
||||||
|
.size(IconSize::XSmall),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Label::new(model.name().0)
|
Label::new(model.name().0)
|
||||||
|
@ -4538,71 +4540,7 @@ impl Render for ContextEditorToolbarItem {
|
||||||
)
|
)
|
||||||
.with_handle(self.model_selector_menu_handle.clone()),
|
.with_handle(self.model_selector_menu_handle.clone()),
|
||||||
)
|
)
|
||||||
.children(self.render_remaining_tokens(cx))
|
.children(self.render_remaining_tokens(cx));
|
||||||
.child(
|
|
||||||
PopoverMenu::new("context-editor-popover")
|
|
||||||
.trigger(
|
|
||||||
IconButton::new("context-editor-trigger", IconName::EllipsisVertical)
|
|
||||||
.icon_size(IconSize::Small)
|
|
||||||
.tooltip(|cx| Tooltip::text("Open Context Options", cx)),
|
|
||||||
)
|
|
||||||
.menu({
|
|
||||||
let weak_self = weak_self.clone();
|
|
||||||
move |cx| {
|
|
||||||
let weak_self = weak_self.clone();
|
|
||||||
Some(ContextMenu::build(cx, move |menu, cx| {
|
|
||||||
let context = weak_self
|
|
||||||
.update(cx, |this, cx| {
|
|
||||||
active_editor_focus_handle(&this.workspace, cx)
|
|
||||||
})
|
|
||||||
.ok()
|
|
||||||
.flatten();
|
|
||||||
menu.when_some(context, |menu, context| menu.context(context))
|
|
||||||
.entry("Regenerate Context Title", None, {
|
|
||||||
let weak_self = weak_self.clone();
|
|
||||||
move |cx| {
|
|
||||||
weak_self
|
|
||||||
.update(cx, |_, cx| {
|
|
||||||
cx.emit(ContextEditorToolbarItemEvent::RegenerateSummary)
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.custom_entry(
|
|
||||||
|_| {
|
|
||||||
h_flex()
|
|
||||||
.w_full()
|
|
||||||
.justify_between()
|
|
||||||
.gap_2()
|
|
||||||
.child(Label::new("Add Context"))
|
|
||||||
.child(Label::new("/ command").color(Color::Muted))
|
|
||||||
.into_any()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
let weak_self = weak_self.clone();
|
|
||||||
move |cx| {
|
|
||||||
weak_self
|
|
||||||
.update(cx, |this, cx| {
|
|
||||||
if let Some(editor) =
|
|
||||||
&this.active_context_editor
|
|
||||||
{
|
|
||||||
editor
|
|
||||||
.update(cx, |this, cx| {
|
|
||||||
this.slash_menu_handle
|
|
||||||
.toggle(cx);
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.action("Add Selection", QuoteSelection.boxed_clone())
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.size_full()
|
.size_full()
|
||||||
|
|
|
@ -234,6 +234,7 @@ pub enum IconName {
|
||||||
Public,
|
Public,
|
||||||
PullRequest,
|
PullRequest,
|
||||||
Quote,
|
Quote,
|
||||||
|
RefreshTitle,
|
||||||
Regex,
|
Regex,
|
||||||
ReplNeutral,
|
ReplNeutral,
|
||||||
Replace,
|
Replace,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue