Signed out state is looking good

Piotr Osiewicz created

Change summary

Cargo.lock                        |   1 
crates/copilot2/Cargo.toml        |   1 
crates/copilot2/src/sign_in.rs    | 278 ++++++++++++++++++--------------
crates/ui2/src/components/icon.rs |   3 
4 files changed, 164 insertions(+), 119 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -2121,6 +2121,7 @@ dependencies = [
  "settings2",
  "smol",
  "theme2",
+ "ui2",
  "util",
 ]
 

crates/copilot2/Cargo.toml 🔗

@@ -28,6 +28,7 @@ theme = { package = "theme2", path = "../theme2" }
 lsp = { package = "lsp2", path = "../lsp2" }
 node_runtime = { path = "../node_runtime"}
 util = { path = "../util" }
+ui = { package = "ui2", path = "../ui2" }
 async-compression = { version = "0.3", features = ["gzip", "futures-bufread"] }
 async-tar = "0.4.2"
 anyhow.workspace = true

crates/copilot2/src/sign_in.rs 🔗

@@ -11,11 +11,15 @@
 
 const COPILOT_SIGN_UP_URL: &'static str = "https://github.com/features/copilot";
 
-use crate::{Copilot, Status};
+use crate::{request::PromptUserDeviceFlow, Copilot, Status};
 use gpui::{
-    px, size, AppContext, Bounds, Div, GlobalPixels, Point, Render, ViewContext, VisualContext,
-    WindowBounds, WindowHandle, WindowKind, WindowOptions,
+    div, px, red, size, AnyElement, AppContext, Bounds, ClipboardItem, Div, Element, GlobalPixels,
+    InteractiveElement, IntoElement, MouseButton, ParentElement, Point, Render, Stateful,
+    StatefulInteractiveElement, Styled, ViewContext, VisualContext, WindowBounds, WindowHandle,
+    WindowKind, WindowOptions,
 };
+use theme::ActiveTheme;
+use ui::{h_stack, v_stack, Button, Clickable, Icon, IconElement, Label};
 
 pub fn init(cx: &mut AppContext) {
     if let Some(copilot) = Copilot::global(cx) {
@@ -72,13 +76,14 @@ fn create_copilot_auth_window(
         center: true,
         focus: true,
         show: true,
-        kind: WindowKind::Normal,
+        kind: WindowKind::PopUp,
         is_movable: true,
         display_id: None,
     };
-    cx.open_window(window_options, |cx| {
+    let window = cx.open_window(window_options, |cx| {
         cx.build_view(|_| CopilotCodeVerification::new(status.clone()))
-    })
+    });
+    window
 }
 
 pub struct CopilotCodeVerification {
@@ -99,119 +104,138 @@ impl CopilotCodeVerification {
         cx.notify();
     }
 
-    //     fn render_device_code(
-    //         data: &PromptUserDeviceFlow,
-    //         style: &theme::Copilot,
-    //         cx: &mut ViewContext<Self>,
-    //     ) -> impl IntoAnyElement<Self> {
-    //         let copied = cx
-    //             .read_from_clipboard()
-    //             .map(|item| item.text() == &data.user_code)
-    //             .unwrap_or(false);
-
-    //         let device_code_style = &style.auth.prompting.device_code;
-
-    //         MouseEventHandler::new::<Self, _>(0, cx, |state, _cx| {
-    //             Flex::row()
-    //                 .with_child(
-    //                     Label::new(data.user_code.clone(), device_code_style.text.clone())
-    //                         .aligned()
-    //                         .contained()
-    //                         .with_style(device_code_style.left_container)
-    //                         .constrained()
-    //                         .with_width(device_code_style.left),
-    //                 )
-    //                 .with_child(
-    //                     Label::new(
-    //                         if copied { "Copied!" } else { "Copy" },
-    //                         device_code_style.cta.style_for(state).text.clone(),
-    //                     )
-    //                     .aligned()
-    //                     .contained()
-    //                     .with_style(*device_code_style.right_container.style_for(state))
-    //                     .constrained()
-    //                     .with_width(device_code_style.right),
-    //                 )
-    //                 .contained()
-    //                 .with_style(device_code_style.cta.style_for(state).container)
-    //         })
-    //         .on_click(gpui::platform::MouseButton::Left, {
-    //             let user_code = data.user_code.clone();
-    //             move |_, _, cx| {
-    //                 cx.platform()
-    //                     .write_to_clipboard(ClipboardItem::new(user_code.clone()));
-    //                 cx.notify();
-    //             }
-    //         })
-    //         .with_cursor_style(gpui::platform::CursorStyle::PointingHand)
-    //     }
+    fn render_device_code(
+        data: &PromptUserDeviceFlow,
+        cx: &mut ViewContext<Self>,
+    ) -> impl IntoElement {
+        let copied = cx
+            .read_from_clipboard()
+            .map(|item| item.text() == &data.user_code)
+            .unwrap_or(false);
+        h_stack()
+            .cursor_pointer()
+            .justify_between()
+            .on_mouse_down(gpui::MouseButton::Left, {
+                let user_code = data.user_code.clone();
+                move |_, cx| {
+                    dbg!("Copied");
+                    cx.write_to_clipboard(ClipboardItem::new(user_code.clone()));
+                    cx.notify();
+                }
+            })
+            .child(Label::new(data.user_code.clone()))
+            .child(Label::new(if copied { "Copied!" } else { "Copy" }))
 
-    //     fn render_prompting_modal(
-    //         connect_clicked: bool,
-    //         data: &PromptUserDeviceFlow,
-    //         style: &theme::Copilot,
-    //         cx: &mut ViewContext<Self>,
-    //     ) -> AnyElement<Self> {
-    //         enum ConnectButton {}
+        // MouseEventHandler::new::<Self, _>(0, cx, |state, _cx| {
+        //     Flex::row()
+        //         .with_child(
+        //             Label::new(data.user_code.clone(), device_code_style.text.clone())
+        //                 .aligned()
+        //                 .contained()
+        //                 .with_style(device_code_style.left_container)
+        //                 .constrained()
+        //                 .with_width(device_code_style.left),
+        //         )
+        //         .with_child(
+        //             Label::new(
+        //                 if copied { "Copied!" } else { "Copy" },
+        //                 device_code_style.cta.style_for(state).text.clone(),
+        //             )
+        //             .aligned()
+        //             .contained()
+        //             .with_style(*device_code_style.right_container.style_for(state))
+        //             .constrained()
+        //             .with_width(device_code_style.right),
+        //         )
+        //         .contained()
+        //         .with_style(device_code_style.cta.style_for(state).container)
+        // })
+        // .on_click(gpui::platform::MouseButton::Left, {
+        //
+        //     move |_, _, cx| {
+        //
+        //     }
+        // })
+        // .with_cursor_style(gpui::platform::CursorStyle::PointingHand)
+    }
 
-    //         Flex::column()
-    //             .with_child(
-    //                 Flex::column()
-    //                     .with_children([
-    //                         Label::new(
-    //                             "Enable Copilot by connecting",
-    //                             style.auth.prompting.subheading.text.clone(),
-    //                         )
-    //                         .aligned(),
-    //                         Label::new(
-    //                             "your existing license.",
-    //                             style.auth.prompting.subheading.text.clone(),
-    //                         )
-    //                         .aligned(),
-    //                     ])
-    //                     .align_children_center()
-    //                     .contained()
-    //                     .with_style(style.auth.prompting.subheading.container),
-    //             )
-    //             .with_child(Self::render_device_code(data, &style, cx))
-    //             .with_child(
-    //                 Flex::column()
-    //                     .with_children([
-    //                         Label::new(
-    //                             "Paste this code into GitHub after",
-    //                             style.auth.prompting.hint.text.clone(),
-    //                         )
-    //                         .aligned(),
-    //                         Label::new(
-    //                             "clicking the button below.",
-    //                             style.auth.prompting.hint.text.clone(),
-    //                         )
-    //                         .aligned(),
-    //                     ])
-    //                     .align_children_center()
-    //                     .contained()
-    //                     .with_style(style.auth.prompting.hint.container.clone()),
-    //             )
-    //             .with_child(theme::ui::cta_button::<ConnectButton, _, _, _>(
-    //                 if connect_clicked {
-    //                     "Waiting for connection..."
-    //                 } else {
-    //                     "Connect to GitHub"
-    //                 },
-    //                 style.auth.content_width,
-    //                 &style.auth.cta_button,
-    //                 cx,
-    //                 {
-    //                     let verification_uri = data.verification_uri.clone();
-    //                     move |_, verification, cx| {
-    //                         cx.platform().open_url(&verification_uri);
-    //                         verification.connect_clicked = true;
-    //                     }
-    //                 },
-    //             ))
-    //             .align_children_center()
-    //             .into_any()
-    //     }
+    fn render_prompting_modal(
+        connect_clicked: bool,
+        data: &PromptUserDeviceFlow,
+        cx: &mut ViewContext<Self>,
+    ) -> impl Element {
+        let connect_button_label = if connect_clicked {
+            "Waiting for connection..."
+        } else {
+            "Connect to Github"
+        };
+        v_stack()
+            .child(
+                v_stack()
+                    .flex_1()
+                    .w_full()
+                    .items_center()
+                    .justify_between()
+                    .children([
+                        h_stack()
+                            .items_center()
+                            .child(Label::new("Enable Copilot by connecting")),
+                        h_stack()
+                            .items_center()
+                            .child(Label::new("your existing license")),
+                    ]),
+            )
+            .child(Self::render_device_code(data, cx))
+            .child(Label::new("Paste this code into GitHub after").size(ui::LabelSize::Small))
+            .child(Label::new("clicking the button below.").size(ui::LabelSize::Small))
+            .child(
+                Button::new("connect-button", connect_button_label).on_click({
+                    let verification_uri = data.verification_uri.clone();
+                    cx.listener(move |this, _, cx| {
+                        cx.open_url(&verification_uri);
+                        this.connect_clicked = true;
+                    })
+                }),
+            )
+        // Flex::column()
+        //     .with_child(Self::render_device_code(data, &style, cx))
+        //     .with_child(
+        //         Flex::column()
+        //             .with_children([
+        //                 Label::new(
+        //                     "Paste this code into GitHub after",
+        //                     style.auth.prompting.hint.text.clone(),
+        //                 )
+        //                 .aligned(),
+        //                 Label::new(
+        //                     "clicking the button below.",
+        //                     style.auth.prompting.hint.text.clone(),
+        //                 )
+        //                 .aligned(),
+        //             ])
+        //             .align_children_center()
+        //             .contained()
+        //             .with_style(style.auth.prompting.hint.container.clone()),
+        //     )
+        //     .with_child(theme::ui::cta_button::<ConnectButton, _, _, _>(
+        //         if connect_clicked {
+        //             "Waiting for connection..."
+        //         } else {
+        //             "Connect to GitHub"
+        //         },
+        //         style.auth.content_width,
+        //         &style.auth.cta_button,
+        //         cx,
+        //         {
+        //             let verification_uri = data.verification_uri.clone();
+        //             move |_, verification, cx| {
+        //                 cx.platform().open_url(&verification_uri);
+        //                 verification.connect_clicked = true;
+        //             }
+        //         },
+        //     ))
+        //     .align_children_center()
+    }
 
     //     fn render_enabled_modal(
     //         style: &theme::Copilot,
@@ -316,10 +340,26 @@ impl CopilotCodeVerification {
 }
 
 impl Render for CopilotCodeVerification {
-    type Element = Div;
+    type Element = Stateful<Div>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
-        todo!()
+        let prompt = match &self.status {
+            Status::SigningIn { prompt } => prompt.as_ref(),
+            _ => None,
+        };
+        div()
+            .id("copilot code verification")
+            .flex()
+            .flex_col()
+            .size_full()
+            .items_center()
+            .p_10()
+            .bg(cx.theme().colors().element_background)
+            .child(ui::Label::new("Connect Copilot to Zed"))
+            .child(IconElement::new(Icon::ZedXCopilot))
+            .children(
+                prompt.map(|data| Self::render_prompting_modal(self.connect_clicked, data, cx)),
+            )
     }
 }
 

crates/ui2/src/components/icon.rs 🔗

@@ -81,6 +81,7 @@ pub enum Icon {
     Shift,
     Option,
     Return,
+    ZedXCopilot,
 }
 
 impl Icon {
@@ -109,6 +110,7 @@ impl Icon {
             Icon::Close => "icons/x.svg",
             Icon::Collab => "icons/user_group_16.svg",
             Icon::Copilot => "icons/copilot.svg",
+
             Icon::CopilotInit => "icons/copilot_init.svg",
             Icon::CopilotError => "icons/copilot_error.svg",
             Icon::CopilotDisabled => "icons/copilot_disabled.svg",
@@ -155,6 +157,7 @@ impl Icon {
             Icon::Shift => "icons/shift.svg",
             Icon::Option => "icons/option.svg",
             Icon::Return => "icons/return.svg",
+            Icon::ZedXCopilot => "icons/zed_x_copilot.svg",
         }
     }
 }