1use context_menu::{ContextMenu, ContextMenuItem};
2use gpui::{
3 elements::*, impl_internal_actions, CursorStyle, Element, ElementBox, Entity, MouseButton,
4 MutableAppContext, RenderContext, View, ViewContext, ViewHandle,
5};
6use settings::Settings;
7use workspace::{item::ItemHandle, NewTerminal, StatusItemView};
8
9const COPILOT_SETTINGS_URL: &str = "https://github.com/settings/copilot";
10
11#[derive(Clone, PartialEq)]
12pub struct DeployCopilotMenu;
13
14impl_internal_actions!(copilot, [DeployCopilotMenu]);
15
16pub fn init(cx: &mut MutableAppContext) {
17 cx.add_action(CopilotButton::deploy_copilot_menu);
18}
19
20pub struct CopilotButton {
21 popup_menu: ViewHandle<ContextMenu>,
22}
23
24impl Entity for CopilotButton {
25 type Event = ();
26}
27
28impl View for CopilotButton {
29 fn ui_name() -> &'static str {
30 "CopilotButton"
31 }
32
33 fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox {
34 let theme = cx.global::<Settings>().theme.clone();
35
36 let visible = self.popup_menu.read(cx).visible();
37
38 Stack::new()
39 .with_child(
40 MouseEventHandler::<Self>::new(0, cx, {
41 let theme = theme.clone();
42 move |state, _cx| {
43 let style = theme
44 .workspace
45 .status_bar
46 .sidebar_buttons
47 .item
48 .style_for(state, visible);
49
50 Flex::row()
51 .with_child(
52 Svg::new("icons/maybe_copilot.svg")
53 .with_color(style.icon_color)
54 .constrained()
55 .with_width(style.icon_size)
56 .aligned()
57 .named("copilot-icon"),
58 )
59 .constrained()
60 .with_height(style.icon_size)
61 .contained()
62 .with_style(style.container)
63 .boxed()
64 }
65 })
66 .with_cursor_style(CursorStyle::PointingHand)
67 .on_click(MouseButton::Left, move |_, _cx| {
68 // TODO: Behavior of this
69 // if has_terminals {
70 // cx.dispatch_action(DeployCopilotMenu);
71 // } else {
72 // if !active {
73 // cx.dispatch_action(FocusDock);
74 // }
75 // };
76 })
77 .with_tooltip::<Self, _>(
78 0,
79 "GitHub Copilot".into(),
80 None,
81 theme.tooltip.clone(),
82 cx,
83 )
84 .boxed(),
85 )
86 .with_child(
87 ChildView::new(&self.popup_menu, cx)
88 .aligned()
89 .top()
90 .right()
91 .boxed(),
92 )
93 .boxed()
94 }
95}
96
97impl CopilotButton {
98 pub fn new(cx: &mut ViewContext<Self>) -> Self {
99 Self {
100 popup_menu: cx.add_view(|cx| {
101 let mut menu = ContextMenu::new(cx);
102 menu.set_position_mode(OverlayPositionMode::Local);
103 menu
104 }),
105 }
106 }
107
108 pub fn deploy_copilot_menu(&mut self, _: &DeployCopilotMenu, cx: &mut ViewContext<Self>) {
109 let mut menu_options = vec![ContextMenuItem::item("New Terminal", NewTerminal)];
110
111 self.popup_menu.update(cx, |menu, cx| {
112 menu.show(
113 Default::default(),
114 AnchorCorner::BottomRight,
115 menu_options,
116 cx,
117 );
118 });
119 }
120}
121
122impl StatusItemView for CopilotButton {
123 fn set_active_pane_item(&mut self, item: Option<&dyn ItemHandle>, cx: &mut ViewContext<Self>) {
124 cx.notify();
125 }
126}