copilot_button.rs

  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}