Kyle Kelley 2024-05-02 13:26:46 -07:00 committed by GitHub
parent 43ad470e58
commit 1915a756a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 209 additions and 138 deletions

View file

@ -1,4 +1,4 @@
use assistant_tooling::ToolRegistry;
use crate::{ui::ProjectIndexButton, AssistantChat, CompletionProvider};
use client::User;
use editor::{Editor, EditorElement, EditorStyle};
use gpui::{AnyElement, FontStyle, FontWeight, TextStyle, View, WeakView, WhiteSpace};
@ -7,13 +7,11 @@ use std::sync::Arc;
use theme::ThemeSettings;
use ui::{popover_menu, prelude::*, Avatar, ButtonLike, ContextMenu, Tooltip};
use crate::{AssistantChat, CompletionProvider};
#[derive(IntoElement)]
pub struct Composer {
editor: View<Editor>,
player: Option<Arc<User>>,
tool_registry: Arc<ToolRegistry>,
project_index_button: Option<View<ProjectIndexButton>>,
model_selector: AnyElement,
}
@ -21,20 +19,28 @@ impl Composer {
pub fn new(
editor: View<Editor>,
player: Option<Arc<User>>,
tool_registry: Arc<ToolRegistry>,
project_index_button: Option<View<ProjectIndexButton>>,
model_selector: AnyElement,
) -> Self {
Self {
editor,
player,
tool_registry,
project_index_button,
model_selector,
}
}
fn render_tools(&mut self, _cx: &mut WindowContext) -> impl IntoElement {
h_flex().children(
self.project_index_button
.clone()
.map(|view| view.into_any_element()),
)
}
}
impl RenderOnce for Composer {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
fn render(mut self, cx: &mut WindowContext) -> impl IntoElement {
let mut player_avatar = div().size(rems_from_px(20.)).into_any_element();
if let Some(player) = self.player.clone() {
player_avatar = Avatar::new(player.avatar_uri.clone())
@ -95,9 +101,7 @@ impl RenderOnce for Composer {
.gap_2()
.justify_between()
.w_full()
.child(h_flex().gap_1().children(
self.tool_registry.status_views().iter().cloned(),
))
.child(h_flex().gap_1().child(self.render_tools(cx)))
.child(h_flex().gap_1().child(self.model_selector)),
),
),

View file

@ -0,0 +1,109 @@
use assistant_tooling::ToolRegistry;
use gpui::{percentage, prelude::*, Animation, AnimationExt, Model, Transformation};
use semantic_index::{ProjectIndex, Status};
use std::{sync::Arc, time::Duration};
use ui::{prelude::*, ButtonLike, Color, Icon, IconName, Indicator, Tooltip};
use crate::tools::ProjectIndexTool;
pub struct ProjectIndexButton {
project_index: Model<ProjectIndex>,
tool_registry: Arc<ToolRegistry>,
}
impl ProjectIndexButton {
pub fn new(
project_index: Model<ProjectIndex>,
tool_registry: Arc<ToolRegistry>,
cx: &mut ViewContext<Self>,
) -> Self {
cx.subscribe(&project_index, |_this, _, _status: &Status, cx| {
cx.notify();
})
.detach();
Self {
project_index,
tool_registry,
}
}
pub fn set_enabled(&mut self, enabled: bool) {
self.tool_registry
.set_tool_enabled::<ProjectIndexTool>(enabled);
}
}
impl Render for ProjectIndexButton {
// Expanded information on ToolView
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let status = self.project_index.read(cx).status();
let is_enabled = self.tool_registry.is_tool_enabled::<ProjectIndexTool>();
let icon = if is_enabled {
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),
}
} else {
Icon::new(IconName::Code)
.size(IconSize::XSmall)
.color(Color::Disabled)
};
let indicator = if is_enabled {
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))),
),
)),
}
} else {
None
};
ButtonLike::new("project-index")
.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)
}
}
})
.on_click(cx.listener(move |this, _, cx| {
this.set_enabled(!is_enabled);
cx.notify();
}))
}
}