1use std::rc::Rc;
2
3use gpui::{Model, View, WeakModel, WeakView};
4use ui::{prelude::*, PopoverMenu, PopoverMenuHandle, Tooltip};
5use workspace::Workspace;
6
7use crate::context_picker::ContextPicker;
8use crate::context_store::ContextStore;
9use crate::thread_store::ThreadStore;
10use crate::ui::ContextPill;
11
12pub struct ContextStrip {
13 context_store: Model<ContextStore>,
14 context_picker: View<ContextPicker>,
15 pub(crate) context_picker_handle: PopoverMenuHandle<ContextPicker>,
16}
17
18impl ContextStrip {
19 pub fn new(
20 context_store: Model<ContextStore>,
21 workspace: WeakView<Workspace>,
22 thread_store: Option<WeakModel<ThreadStore>>,
23 cx: &mut ViewContext<Self>,
24 ) -> Self {
25 Self {
26 context_store: context_store.clone(),
27 context_picker: cx.new_view(|cx| {
28 ContextPicker::new(
29 workspace.clone(),
30 thread_store.clone(),
31 context_store.downgrade(),
32 cx,
33 )
34 }),
35 context_picker_handle: PopoverMenuHandle::default(),
36 }
37 }
38}
39
40impl Render for ContextStrip {
41 fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
42 let context = self.context_store.read(cx).context();
43 let context_picker = self.context_picker.clone();
44
45 h_flex()
46 .flex_wrap()
47 .gap_1()
48 .child(
49 PopoverMenu::new("context-picker")
50 .menu(move |_cx| Some(context_picker.clone()))
51 .trigger(
52 IconButton::new("add-context", IconName::Plus)
53 .icon_size(IconSize::Small)
54 .style(ui::ButtonStyle::Filled),
55 )
56 .attach(gpui::AnchorCorner::TopLeft)
57 .anchor(gpui::AnchorCorner::BottomLeft)
58 .offset(gpui::Point {
59 x: px(0.0),
60 y: px(-16.0),
61 })
62 .with_handle(self.context_picker_handle.clone()),
63 )
64 .children(context.iter().map(|context| {
65 ContextPill::new(context.clone()).on_remove({
66 let context = context.clone();
67 let context_store = self.context_store.clone();
68 Rc::new(cx.listener(move |_this, _event, cx| {
69 context_store.update(cx, |this, _cx| {
70 this.remove_context(&context.id);
71 });
72 cx.notify();
73 }))
74 })
75 }))
76 .when(!context.is_empty(), |parent| {
77 parent.child(
78 IconButton::new("remove-all-context", IconName::Eraser)
79 .icon_size(IconSize::Small)
80 .tooltip(move |cx| Tooltip::text("Remove All Context", cx))
81 .on_click({
82 let context_store = self.context_store.clone();
83 cx.listener(move |_this, _event, cx| {
84 context_store.update(cx, |this, _cx| this.clear());
85 cx.notify();
86 })
87 }),
88 )
89 })
90 }
91}