Iterate on Assistant 2 composer UI (#11306)
- Change project index tool rendering in composer - Update composer UI style Release Notes: - N/A --------- Co-authored-by: Marshall Bowers <1486634+maxdeviant@users.noreply.github.com> Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
parent
9bac64a9c1
commit
78a8a58ee2
6 changed files with 141 additions and 117 deletions
1
assets/icons/code.svg
Normal file
1
assets/icons/code.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-code-xml"><path d="m18 16 4-4-4-4"/><path d="m6 8-4 4 4 4"/><path d="m14.5 4-5 16"/></svg>
|
After Width: | Height: | Size: 293 B |
13
assets/icons/spinner.svg
Normal file
13
assets/icons/spinner.svg
Normal file
|
@ -0,0 +1,13 @@
|
|||
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1803_28)">
|
||||
<path d="M0.5 2C0.5 1.17157 1.17157 0.5 2 0.5V0.5C2.82843 0.5 3.5 1.17157 3.5 2V2C3.5 2.82843 2.82843 3.5 2 3.5V3.5C1.17157 3.5 0.5 2.82843 0.5 2V2Z" fill="black" fill-opacity="0.3"/>
|
||||
<path d="M7.5 6C7.5 6.82843 6.82843 7.5 6 7.5V7.5C5.17157 7.5 4.5 6.82843 4.5 6V6C4.5 5.17157 5.17157 4.5 6 4.5V4.5C6.82843 4.5 7.5 5.17157 7.5 6V6Z" fill="black" fill-opacity="0.6"/>
|
||||
<path d="M2 7.5C1.17157 7.5 0.5 6.82843 0.5 6V6C0.5 5.17157 1.17157 4.5 2 4.5V4.5C2.82843 4.5 3.5 5.17157 3.5 6V6C3.5 6.82843 2.82843 7.5 2 7.5V7.5Z" fill="black" fill-opacity="0.8"/>
|
||||
<path d="M6 0.5C6.82843 0.5 7.5 1.17157 7.5 2V2C7.5 2.82843 6.82843 3.5 6 3.5V3.5C5.17157 3.5 4.5 2.82843 4.5 2V2C4.5 1.17157 5.17157 0.5 6 0.5V0.5Z" fill="black"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1803_28">
|
||||
<rect width="8" height="8" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 956 B |
|
@ -269,7 +269,7 @@ impl AssistantChat {
|
|||
composer_editor: cx.new_view(|cx| {
|
||||
let mut editor = Editor::auto_height(80, cx);
|
||||
editor.set_soft_wrap_mode(SoftWrap::EditorWidth, cx);
|
||||
editor.set_placeholder_text("Type a message to the assistant", cx);
|
||||
editor.set_placeholder_text("Send a message…", cx);
|
||||
editor
|
||||
}),
|
||||
list_state,
|
||||
|
@ -372,10 +372,6 @@ impl AssistantChat {
|
|||
}));
|
||||
}
|
||||
|
||||
fn can_submit(&self) -> bool {
|
||||
self.pending_completion.is_none()
|
||||
}
|
||||
|
||||
fn debug_project_index(&mut self, _: &DebugProjectIndex, cx: &mut ViewContext<Self>) {
|
||||
if let Some(index) = &self.project_index {
|
||||
index.update(cx, |project_index, cx| {
|
||||
|
@ -594,7 +590,6 @@ impl AssistantChat {
|
|||
element.child(Composer::new(
|
||||
body.clone(),
|
||||
self.user_store.read(cx).current_user(),
|
||||
true,
|
||||
self.tool_registry.clone(),
|
||||
crate::ui::ModelSelector::new(
|
||||
cx.view().downgrade(),
|
||||
|
@ -773,7 +768,6 @@ impl Render for AssistantChat {
|
|||
.child(Composer::new(
|
||||
self.composer_editor.clone(),
|
||||
self.user_store.read(cx).current_user(),
|
||||
self.can_submit(),
|
||||
self.tool_registry.clone(),
|
||||
crate::ui::ModelSelector::new(cx.view().downgrade(), self.model.clone())
|
||||
.into_any_element(),
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use anyhow::Result;
|
||||
use assistant_tooling::LanguageModelTool;
|
||||
use gpui::{prelude::*, AnyView, Model, Task};
|
||||
use gpui::{percentage, prelude::*, Animation, AnimationExt, AnyView, Model, Task, Transformation};
|
||||
use project::Fs;
|
||||
use schemars::JsonSchema;
|
||||
use semantic_index::{ProjectIndex, Status};
|
||||
use serde::Deserialize;
|
||||
use std::sync::Arc;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use ui::{
|
||||
div, prelude::*, CollapsibleContainer, Color, Icon, IconName, Label, SharedString,
|
||||
WindowContext,
|
||||
div, prelude::*, ButtonLike, CollapsibleContainer, Color, Icon, IconName, Indicator, Label,
|
||||
SharedString, Tooltip, WindowContext,
|
||||
};
|
||||
use util::ResultExt as _;
|
||||
|
||||
|
@ -255,12 +255,63 @@ impl Render for ProjectIndexStatusView {
|
|||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let status = self.project_index.read(cx).status();
|
||||
|
||||
h_flex().gap_2().map(|element| match status {
|
||||
Status::Idle => element.child(Label::new("Project index ready")),
|
||||
Status::Loading => element.child(Label::new("Project index loading...")),
|
||||
Status::Scanning { remaining_count } => element.child(Label::new(format!(
|
||||
"Project index scanning: {remaining_count} remaining..."
|
||||
))),
|
||||
let is_enabled = match status {
|
||||
Status::Idle => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
let icon = match status {
|
||||
Status::Idle => Icon::new(IconName::Code)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Default),
|
||||
Status::Loading => Icon::new(IconName::Code)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Muted),
|
||||
Status::Scanning { .. } => Icon::new(IconName::Code)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Muted),
|
||||
};
|
||||
|
||||
let indicator = match status {
|
||||
Status::Idle => Some(Indicator::dot().color(Color::Success)),
|
||||
Status::Scanning { .. } => Some(Indicator::dot().color(Color::Warning)),
|
||||
Status::Loading => Some(Indicator::icon(
|
||||
Icon::new(IconName::Spinner)
|
||||
.color(Color::Accent)
|
||||
.with_animation(
|
||||
"arrow-circle",
|
||||
Animation::new(Duration::from_secs(2)).repeat(),
|
||||
|icon, delta| icon.transform(Transformation::rotate(percentage(delta))),
|
||||
),
|
||||
)),
|
||||
};
|
||||
|
||||
ButtonLike::new("project-index")
|
||||
.disabled(!is_enabled)
|
||||
.child(
|
||||
ui::IconWithIndicator::new(icon, indicator)
|
||||
.indicator_border_color(Some(gpui::transparent_black())),
|
||||
)
|
||||
.tooltip({
|
||||
move |cx| {
|
||||
let (tooltip, meta) = match status {
|
||||
Status::Idle => (
|
||||
"Project index ready".to_string(),
|
||||
Some("Click to disable".to_string()),
|
||||
),
|
||||
Status::Loading => ("Project index loading...".to_string(), None),
|
||||
Status::Scanning { remaining_count } => (
|
||||
"Project index scanning...".to_string(),
|
||||
Some(format!("{} remaining...", remaining_count)),
|
||||
),
|
||||
};
|
||||
|
||||
if let Some(meta) = meta {
|
||||
Tooltip::with_meta(tooltip, None, meta, cx)
|
||||
} else {
|
||||
Tooltip::text(tooltip, cx)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,12 @@ use std::sync::Arc;
|
|||
use theme::ThemeSettings;
|
||||
use ui::{popover_menu, prelude::*, Avatar, ButtonLike, ContextMenu, Tooltip};
|
||||
|
||||
use crate::{AssistantChat, CompletionProvider, Submit, SubmitMode};
|
||||
use crate::{AssistantChat, CompletionProvider};
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct Composer {
|
||||
editor: View<Editor>,
|
||||
player: Option<Arc<User>>,
|
||||
can_submit: bool,
|
||||
tool_registry: Arc<ToolRegistry>,
|
||||
model_selector: AnyElement,
|
||||
}
|
||||
|
@ -22,14 +21,12 @@ impl Composer {
|
|||
pub fn new(
|
||||
editor: View<Editor>,
|
||||
player: Option<Arc<User>>,
|
||||
can_submit: bool,
|
||||
tool_registry: Arc<ToolRegistry>,
|
||||
model_selector: AnyElement,
|
||||
) -> Self {
|
||||
Self {
|
||||
editor,
|
||||
player,
|
||||
can_submit,
|
||||
tool_registry,
|
||||
model_selector,
|
||||
}
|
||||
|
@ -55,11 +52,7 @@ impl RenderOnce for Composer {
|
|||
.gap_3()
|
||||
.child(player_avatar)
|
||||
.child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
.gap_1()
|
||||
.pr_4()
|
||||
.child(
|
||||
v_flex().size_full().gap_1().child(
|
||||
v_flex()
|
||||
.w_full()
|
||||
.p_4()
|
||||
|
@ -102,54 +95,14 @@ impl RenderOnce for Composer {
|
|||
.gap_2()
|
||||
.justify_between()
|
||||
.w_full()
|
||||
.child(
|
||||
h_flex().gap_1().child(
|
||||
// IconButton/button
|
||||
// Toggle - if enabled, .selected(true).selected_style(IconButtonStyle::Filled)
|
||||
//
|
||||
// match status
|
||||
// Tooltip::with_meta("some label explaining project index + status", "click to enable")
|
||||
IconButton::new(
|
||||
"add-context",
|
||||
IconName::FileDoc,
|
||||
)
|
||||
.icon_color(Color::Muted),
|
||||
), // .child(
|
||||
// IconButton::new(
|
||||
// "add-context",
|
||||
// IconName::Plus,
|
||||
// )
|
||||
// .icon_color(Color::Muted),
|
||||
// ),
|
||||
)
|
||||
.child(
|
||||
Button::new("send-button", "Send")
|
||||
.style(ButtonStyle::Filled)
|
||||
.disabled(!self.can_submit)
|
||||
.on_click(|_, cx| {
|
||||
cx.dispatch_action(Box::new(Submit(
|
||||
SubmitMode::Codebase,
|
||||
)))
|
||||
})
|
||||
.tooltip(|cx| {
|
||||
Tooltip::for_action(
|
||||
"Submit message",
|
||||
&Submit(SubmitMode::Codebase),
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
.child(h_flex().gap_1().children(
|
||||
self.tool_registry.status_views().iter().cloned(),
|
||||
))
|
||||
.child(h_flex().gap_1().child(self.model_selector)),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.justify_between()
|
||||
.child(self.model_selector)
|
||||
.children(self.tool_registry.status_views().iter().cloned()),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,10 +158,18 @@ impl RenderOnce for ModelSelector {
|
|||
.overflow_x_hidden()
|
||||
.flex_grow()
|
||||
.whitespace_nowrap()
|
||||
.child(Label::new(self.model)),
|
||||
.child(
|
||||
Label::new(self.model)
|
||||
.size(LabelSize::Small)
|
||||
.color(Color::Muted),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div().child(Icon::new(IconName::ChevronDown).color(Color::Muted)),
|
||||
div().child(
|
||||
Icon::new(IconName::ChevronDown)
|
||||
.color(Color::Muted)
|
||||
.size(IconSize::XSmall),
|
||||
),
|
||||
),
|
||||
)
|
||||
.style(ButtonStyle::Subtle)
|
||||
|
|
|
@ -87,6 +87,7 @@ pub enum IconName {
|
|||
ChevronUp,
|
||||
ExpandVertical,
|
||||
Close,
|
||||
Code,
|
||||
Collab,
|
||||
Command,
|
||||
Control,
|
||||
|
@ -153,6 +154,7 @@ pub enum IconName {
|
|||
Snip,
|
||||
Space,
|
||||
Split,
|
||||
Spinner,
|
||||
Tab,
|
||||
Terminal,
|
||||
Trash,
|
||||
|
@ -191,6 +193,7 @@ impl IconName {
|
|||
IconName::ChevronUp => "icons/chevron_up.svg",
|
||||
IconName::ExpandVertical => "icons/expand_vertical.svg",
|
||||
IconName::Close => "icons/x.svg",
|
||||
IconName::Code => "icons/code.svg",
|
||||
IconName::Collab => "icons/user_group_16.svg",
|
||||
IconName::Command => "icons/command.svg",
|
||||
IconName::Control => "icons/control.svg",
|
||||
|
@ -257,6 +260,7 @@ impl IconName {
|
|||
IconName::Snip => "icons/snip.svg",
|
||||
IconName::Space => "icons/space.svg",
|
||||
IconName::Split => "icons/split.svg",
|
||||
IconName::Spinner => "icons/spinner.svg",
|
||||
IconName::Tab => "icons/tab.svg",
|
||||
IconName::Terminal => "icons/terminal.svg",
|
||||
IconName::Trash => "icons/trash.svg",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue