Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assistant2: Show file icons for context entries #22928

Merged
merged 6 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/assistant2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ util.workspace = true
uuid.workspace = true
workspace.workspace = true
zed_actions.workspace = true
file_icons.workspace = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we keep this list of dependencies sorted alphabetically?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in eebb114


[dev-dependencies]
rand.workspace = true
Expand Down
19 changes: 19 additions & 0 deletions crates/assistant2/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ use std::rc::Rc;
use std::sync::Arc;

use collections::BTreeMap;
use file_icons::FileIcons;
use gpui::{AppContext, Model, SharedString};
use language::Buffer;
use language_model::{LanguageModelRequestMessage, MessageContent};
use serde::{Deserialize, Serialize};
use text::BufferId;
use ui::IconName;
use util::post_inc;

use crate::thread::Thread;
Expand All @@ -28,6 +30,7 @@ pub struct ContextSnapshot {
pub name: SharedString,
pub parent: Option<SharedString>,
pub tooltip: Option<SharedString>,
pub icon_path: Option<SharedString>,
pub kind: ContextKind,
/// Text to send to the model. This is not refreshed by `snapshot`.
pub text: SharedString,
Expand All @@ -41,6 +44,17 @@ pub enum ContextKind {
Thread,
}

impl ContextKind {
pub fn icon(&self) -> IconName {
match self {
ContextKind::File => IconName::File,
ContextKind::Directory => IconName::Folder,
ContextKind::FetchedUrl => IconName::Globe,
ContextKind::Thread => IconName::MessageCircle,
}
}
}

#[derive(Debug)]
pub enum Context {
File(FileContext),
Expand Down Expand Up @@ -135,11 +149,14 @@ impl FileContext {
.and_then(|p| p.file_name())
.map(|p| p.to_string_lossy().into_owned().into());

let icon_path = FileIcons::get_icon(&path, cx);

Some(ContextSnapshot {
id: self.id,
name,
parent,
tooltip: Some(full_path),
icon_path,
kind: ContextKind::File,
text: self.text.clone(),
})
Expand All @@ -159,6 +176,7 @@ impl FetchedUrlContext {
name: self.url.clone(),
parent: None,
tooltip: None,
icon_path: None,
kind: ContextKind::FetchedUrl,
text: self.text.clone(),
}
Expand All @@ -173,6 +191,7 @@ impl ThreadContext {
name: thread.summary().unwrap_or("New thread".into()),
parent: None,
tooltip: None,
icon_path: None,
kind: ContextKind::Thread,
text: self.text.clone(),
}
Expand Down
6 changes: 6 additions & 0 deletions crates/assistant2/src/context_picker/file_context_picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::path::Path;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;

use file_icons::FileIcons;
use fuzzy::PathMatch;
use gpui::{AppContext, DismissEvent, FocusHandle, FocusableView, Task, View, WeakModel, WeakView};
use picker::{Picker, PickerDelegate};
Expand Down Expand Up @@ -281,13 +282,18 @@ impl PickerDelegate for FileContextPickerDelegate {
.will_include_file_path(&path_match.path, cx)
});

let file_icon = FileIcons::get_icon(&path_match.path.clone(), cx)
.map(|icon_path| Icon::from_path(icon_path))
.unwrap_or_else(|| Icon::new(IconName::File));

Some(
ListItem::new(ix)
.inset(true)
.toggle_state(selected)
.child(
h_flex()
.gap_2()
.child(file_icon.size(IconSize::Small))
.child(Label::new(file_name))
.children(directory.map(|directory| {
Label::new(directory)
Expand Down
1 change: 1 addition & 0 deletions crates/assistant2/src/context_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ impl ContextStore {
name,
parent,
tooltip: Some(full_path),
icon_path: None,
kind: ContextKind::Directory,
text: text.into(),
},
Expand Down
19 changes: 18 additions & 1 deletion crates/assistant2/src/context_strip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::rc::Rc;

use collections::HashSet;
use editor::Editor;
use file_icons::FileIcons;
use gpui::{
AppContext, DismissEvent, EventEmitter, FocusHandle, Model, Subscription, View, WeakModel,
WeakView,
Expand Down Expand Up @@ -94,9 +95,12 @@ impl ContextStrip {
None => path.to_string_lossy().into_owned().into(),
};

let icon_path = FileIcons::get_icon(path, cx);

Some(SuggestedContext::File {
name,
buffer: active_buffer_model.downgrade(),
icon_path,
})
}

Expand Down Expand Up @@ -227,6 +231,7 @@ impl Render for ContextStrip {
.when_some(suggested_context, |el, suggested| {
el.child(ContextPill::new_suggested(
suggested.name().clone(),
suggested.icon_path(),
suggested.kind(),
{
let context_store = self.context_store.clone();
Expand Down Expand Up @@ -283,6 +288,7 @@ pub enum SuggestContextKind {
pub enum SuggestedContext {
File {
name: SharedString,
icon_path: Option<SharedString>,
buffer: WeakModel<Buffer>,
},
Thread {
Expand All @@ -299,9 +305,20 @@ impl SuggestedContext {
}
}

pub fn icon_path(&self) -> Option<SharedString> {
match self {
Self::File { icon_path, .. } => icon_path.clone(),
Self::Thread { .. } => None,
}
}

pub fn accept(&self, context_store: &mut ContextStore, cx: &mut AppContext) {
match self {
Self::File { buffer, name: _ } => {
Self::File {
buffer,
icon_path: _,
name: _,
} => {
if let Some(buffer) = buffer.upgrade() {
context_store.insert_file(buffer, cx);
};
Expand Down
42 changes: 29 additions & 13 deletions crates/assistant2/src/ui/context_pill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub enum ContextPill {
},
Suggested {
name: SharedString,
icon_path: Option<SharedString>,
kind: ContextKind,
on_add: Rc<dyn Fn(&ClickEvent, &mut WindowContext)>,
},
Expand All @@ -34,10 +35,16 @@ impl ContextPill {

pub fn new_suggested(
name: SharedString,
icon_path: Option<SharedString>,
kind: ContextKind,
on_add: Rc<dyn Fn(&ClickEvent, &mut WindowContext)>,
) -> Self {
Self::Suggested { name, kind, on_add }
Self::Suggested {
name,
icon_path,
kind,
on_add,
}
}

pub fn id(&self) -> ElementId {
Expand All @@ -49,23 +56,27 @@ impl ContextPill {
}
}

pub fn kind(&self) -> ContextKind {
pub fn icon(&self) -> Icon {
match self {
Self::Added { context, .. } => context.kind,
Self::Suggested { kind, .. } => *kind,
Self::Added { context, .. } => match &context.icon_path {
Some(icon_path) => Icon::from_path(icon_path),
None => Icon::new(context.kind.icon()),
},
Self::Suggested {
icon_path: Some(icon_path),
..
} => Icon::from_path(icon_path),
Self::Suggested {
kind,
icon_path: None,
..
} => Icon::new(kind.icon()),
}
}
}

impl RenderOnce for ContextPill {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
let icon = match &self.kind() {
ContextKind::File => IconName::File,
ContextKind::Directory => IconName::Folder,
ContextKind::FetchedUrl => IconName::Globe,
ContextKind::Thread => IconName::MessageCircle,
};

let color = cx.theme().colors();

let base_pill = h_flex()
Expand All @@ -75,7 +86,7 @@ impl RenderOnce for ContextPill {
.border_1()
.rounded_md()
.gap_1()
.child(Icon::new(icon).size(IconSize::XSmall).color(Color::Muted));
.child(self.icon().size(IconSize::XSmall).color(Color::Muted));

match &self {
ContextPill::Added {
Expand Down Expand Up @@ -118,7 +129,12 @@ impl RenderOnce for ContextPill {
}),
)
}),
ContextPill::Suggested { name, kind, on_add } => base_pill
ContextPill::Suggested {
name,
icon_path: _,
kind,
on_add,
} => base_pill
.cursor_pointer()
.pr_1()
.border_color(color.border_variant.opacity(0.5))
Expand Down
Loading