assistant2: Derive the `Context` icon at render time instead of storing (#22397)

Marshall Bowers created

This PR is a follow up to #22385 that makes it so we treat the icon as
derived state.

Release Notes:

- N/A

Change summary

crates/assistant2/src/context.rs         | 15 +--------------
crates/assistant2/src/context_store.rs   |  3 +--
crates/assistant2/src/ui/context_pill.rs | 14 ++++++++------
3 files changed, 10 insertions(+), 22 deletions(-)

Detailed changes

crates/assistant2/src/context.rs 🔗

@@ -1,7 +1,6 @@
 use gpui::SharedString;
 use language_model::{LanguageModelRequestMessage, MessageContent};
 use serde::{Deserialize, Serialize};
-use ui::prelude::*;
 use util::post_inc;
 
 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize)]
@@ -20,10 +19,9 @@ pub struct Context {
     pub name: SharedString,
     pub kind: ContextKind,
     pub text: SharedString,
-    pub icon: IconName,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum ContextKind {
     File,
     Directory,
@@ -31,17 +29,6 @@ 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,
-        }
-    }
-}
-
 pub fn attach_context_to_message(
     message: &mut LanguageModelRequestMessage,
     context: impl IntoIterator<Item = Context>,

crates/assistant2/src/context_store.rs 🔗

@@ -36,9 +36,8 @@ impl ContextStore {
         self.context.push(Context {
             id: self.next_context_id.post_inc(),
             name: name.into(),
-            kind: kind.clone(),
+            kind,
             text: text.into(),
-            icon: kind.icon(),
         });
     }
 

crates/assistant2/src/ui/context_pill.rs 🔗

@@ -3,7 +3,7 @@ use std::rc::Rc;
 use gpui::ClickEvent;
 use ui::{prelude::*, IconButtonShape};
 
-use crate::context::Context;
+use crate::context::{Context, ContextKind};
 
 #[derive(IntoElement)]
 pub struct ContextPill {
@@ -32,6 +32,12 @@ impl RenderOnce for ContextPill {
         } else {
             px(4.)
         };
+        let icon = match self.context.kind {
+            ContextKind::File => IconName::File,
+            ContextKind::Directory => IconName::Folder,
+            ContextKind::FetchedUrl => IconName::Globe,
+            ContextKind::Thread => IconName::MessageCircle,
+        };
 
         h_flex()
             .gap_1()
@@ -42,11 +48,7 @@ impl RenderOnce for ContextPill {
             .border_color(cx.theme().colors().border.opacity(0.5))
             .bg(cx.theme().colors().element_background)
             .rounded_md()
-            .child(
-                Icon::new(self.context.icon)
-                    .size(IconSize::XSmall)
-                    .color(Color::Muted),
-            )
+            .child(Icon::new(icon).size(IconSize::XSmall).color(Color::Muted))
             .child(Label::new(self.context.name.clone()).size(LabelSize::Small))
             .when_some(self.on_remove, |parent, on_remove| {
                 parent.child(