sign_in.rs

  1// TODO add logging in
  2// use crate::{request::PromptUserDeviceFlow, Copilot, Status};
  3// use gpui::{
  4//     elements::*,
  5//     geometry::rect::RectF,
  6//     platform::{WindowBounds, WindowKind, WindowOptions},
  7//     AnyElement, AnyViewHandle, AppContext, ClipboardItem, Element, Entity, View, ViewContext,
  8//     WindowHandle,
  9// };
 10// use theme::ui::modal;
 11
 12// #[derive(PartialEq, Eq, Debug, Clone)]
 13// struct CopyUserCode;
 14
 15// #[derive(PartialEq, Eq, Debug, Clone)]
 16// struct OpenGithub;
 17
 18// const COPILOT_SIGN_UP_URL: &'static str = "https://github.com/features/copilot";
 19
 20// pub fn init(cx: &mut AppContext) {
 21//     if let Some(copilot) = Copilot::global(cx) {
 22//         let mut verification_window: Option<WindowHandle<CopilotCodeVerification>> = None;
 23//         cx.observe(&copilot, move |copilot, cx| {
 24//             let status = copilot.read(cx).status();
 25
 26//             match &status {
 27//                 crate::Status::SigningIn { prompt } => {
 28//                     if let Some(window) = verification_window.as_mut() {
 29//                         let updated = window
 30//                             .root(cx)
 31//                             .map(|root| {
 32//                                 root.update(cx, |verification, cx| {
 33//                                     verification.set_status(status.clone(), cx);
 34//                                     cx.activate_window();
 35//                                 })
 36//                             })
 37//                             .is_some();
 38//                         if !updated {
 39//                             verification_window = Some(create_copilot_auth_window(cx, &status));
 40//                         }
 41//                     } else if let Some(_prompt) = prompt {
 42//                         verification_window = Some(create_copilot_auth_window(cx, &status));
 43//                     }
 44//                 }
 45//                 Status::Authorized | Status::Unauthorized => {
 46//                     if let Some(window) = verification_window.as_ref() {
 47//                         if let Some(verification) = window.root(cx) {
 48//                             verification.update(cx, |verification, cx| {
 49//                                 verification.set_status(status, cx);
 50//                                 cx.platform().activate(true);
 51//                                 cx.activate_window();
 52//                             });
 53//                         }
 54//                     }
 55//                 }
 56//                 _ => {
 57//                     if let Some(code_verification) = verification_window.take() {
 58//                         code_verification.update(cx, |cx| cx.remove_window());
 59//                     }
 60//                 }
 61//             }
 62//         })
 63//         .detach();
 64//     }
 65// }
 66
 67// fn create_copilot_auth_window(
 68//     cx: &mut AppContext,
 69//     status: &Status,
 70// ) -> WindowHandle<CopilotCodeVerification> {
 71//     let window_size = theme::current(cx).copilot.modal.dimensions();
 72//     let window_options = WindowOptions {
 73//         bounds: WindowBounds::Fixed(RectF::new(Default::default(), window_size)),
 74//         titlebar: None,
 75//         center: true,
 76//         focus: true,
 77//         show: true,
 78//         kind: WindowKind::Normal,
 79//         is_movable: true,
 80//         screen: None,
 81//     };
 82//     cx.add_window(window_options, |_cx| {
 83//         CopilotCodeVerification::new(status.clone())
 84//     })
 85// }
 86
 87// pub struct CopilotCodeVerification {
 88//     status: Status,
 89//     connect_clicked: bool,
 90// }
 91
 92// impl CopilotCodeVerification {
 93//     pub fn new(status: Status) -> Self {
 94//         Self {
 95//             status,
 96//             connect_clicked: false,
 97//         }
 98//     }
 99
100//     pub fn set_status(&mut self, status: Status, cx: &mut ViewContext<Self>) {
101//         self.status = status;
102//         cx.notify();
103//     }
104
105//     fn render_device_code(
106//         data: &PromptUserDeviceFlow,
107//         style: &theme::Copilot,
108//         cx: &mut ViewContext<Self>,
109//     ) -> impl IntoAnyElement<Self> {
110//         let copied = cx
111//             .read_from_clipboard()
112//             .map(|item| item.text() == &data.user_code)
113//             .unwrap_or(false);
114
115//         let device_code_style = &style.auth.prompting.device_code;
116
117//         MouseEventHandler::new::<Self, _>(0, cx, |state, _cx| {
118//             Flex::row()
119//                 .with_child(
120//                     Label::new(data.user_code.clone(), device_code_style.text.clone())
121//                         .aligned()
122//                         .contained()
123//                         .with_style(device_code_style.left_container)
124//                         .constrained()
125//                         .with_width(device_code_style.left),
126//                 )
127//                 .with_child(
128//                     Label::new(
129//                         if copied { "Copied!" } else { "Copy" },
130//                         device_code_style.cta.style_for(state).text.clone(),
131//                     )
132//                     .aligned()
133//                     .contained()
134//                     .with_style(*device_code_style.right_container.style_for(state))
135//                     .constrained()
136//                     .with_width(device_code_style.right),
137//                 )
138//                 .contained()
139//                 .with_style(device_code_style.cta.style_for(state).container)
140//         })
141//         .on_click(gpui::platform::MouseButton::Left, {
142//             let user_code = data.user_code.clone();
143//             move |_, _, cx| {
144//                 cx.platform()
145//                     .write_to_clipboard(ClipboardItem::new(user_code.clone()));
146//                 cx.notify();
147//             }
148//         })
149//         .with_cursor_style(gpui::platform::CursorStyle::PointingHand)
150//     }
151
152//     fn render_prompting_modal(
153//         connect_clicked: bool,
154//         data: &PromptUserDeviceFlow,
155//         style: &theme::Copilot,
156//         cx: &mut ViewContext<Self>,
157//     ) -> AnyElement<Self> {
158//         enum ConnectButton {}
159
160//         Flex::column()
161//             .with_child(
162//                 Flex::column()
163//                     .with_children([
164//                         Label::new(
165//                             "Enable Copilot by connecting",
166//                             style.auth.prompting.subheading.text.clone(),
167//                         )
168//                         .aligned(),
169//                         Label::new(
170//                             "your existing license.",
171//                             style.auth.prompting.subheading.text.clone(),
172//                         )
173//                         .aligned(),
174//                     ])
175//                     .align_children_center()
176//                     .contained()
177//                     .with_style(style.auth.prompting.subheading.container),
178//             )
179//             .with_child(Self::render_device_code(data, &style, cx))
180//             .with_child(
181//                 Flex::column()
182//                     .with_children([
183//                         Label::new(
184//                             "Paste this code into GitHub after",
185//                             style.auth.prompting.hint.text.clone(),
186//                         )
187//                         .aligned(),
188//                         Label::new(
189//                             "clicking the button below.",
190//                             style.auth.prompting.hint.text.clone(),
191//                         )
192//                         .aligned(),
193//                     ])
194//                     .align_children_center()
195//                     .contained()
196//                     .with_style(style.auth.prompting.hint.container.clone()),
197//             )
198//             .with_child(theme::ui::cta_button::<ConnectButton, _, _, _>(
199//                 if connect_clicked {
200//                     "Waiting for connection..."
201//                 } else {
202//                     "Connect to GitHub"
203//                 },
204//                 style.auth.content_width,
205//                 &style.auth.cta_button,
206//                 cx,
207//                 {
208//                     let verification_uri = data.verification_uri.clone();
209//                     move |_, verification, cx| {
210//                         cx.platform().open_url(&verification_uri);
211//                         verification.connect_clicked = true;
212//                     }
213//                 },
214//             ))
215//             .align_children_center()
216//             .into_any()
217//     }
218
219//     fn render_enabled_modal(
220//         style: &theme::Copilot,
221//         cx: &mut ViewContext<Self>,
222//     ) -> AnyElement<Self> {
223//         enum DoneButton {}
224
225//         let enabled_style = &style.auth.authorized;
226//         Flex::column()
227//             .with_child(
228//                 Label::new("Copilot Enabled!", enabled_style.subheading.text.clone())
229//                     .contained()
230//                     .with_style(enabled_style.subheading.container)
231//                     .aligned(),
232//             )
233//             .with_child(
234//                 Flex::column()
235//                     .with_children([
236//                         Label::new(
237//                             "You can update your settings or",
238//                             enabled_style.hint.text.clone(),
239//                         )
240//                         .aligned(),
241//                         Label::new(
242//                             "sign out from the Copilot menu in",
243//                             enabled_style.hint.text.clone(),
244//                         )
245//                         .aligned(),
246//                         Label::new("the status bar.", enabled_style.hint.text.clone()).aligned(),
247//                     ])
248//                     .align_children_center()
249//                     .contained()
250//                     .with_style(enabled_style.hint.container),
251//             )
252//             .with_child(theme::ui::cta_button::<DoneButton, _, _, _>(
253//                 "Done",
254//                 style.auth.content_width,
255//                 &style.auth.cta_button,
256//                 cx,
257//                 |_, _, cx| cx.remove_window(),
258//             ))
259//             .align_children_center()
260//             .into_any()
261//     }
262
263//     fn render_unauthorized_modal(
264//         style: &theme::Copilot,
265//         cx: &mut ViewContext<Self>,
266//     ) -> AnyElement<Self> {
267//         let unauthorized_style = &style.auth.not_authorized;
268
269//         Flex::column()
270//             .with_child(
271//                 Flex::column()
272//                     .with_children([
273//                         Label::new(
274//                             "Enable Copilot by connecting",
275//                             unauthorized_style.subheading.text.clone(),
276//                         )
277//                         .aligned(),
278//                         Label::new(
279//                             "your existing license.",
280//                             unauthorized_style.subheading.text.clone(),
281//                         )
282//                         .aligned(),
283//                     ])
284//                     .align_children_center()
285//                     .contained()
286//                     .with_style(unauthorized_style.subheading.container),
287//             )
288//             .with_child(
289//                 Flex::column()
290//                     .with_children([
291//                         Label::new(
292//                             "You must have an active copilot",
293//                             unauthorized_style.warning.text.clone(),
294//                         )
295//                         .aligned(),
296//                         Label::new(
297//                             "license to use it in Zed.",
298//                             unauthorized_style.warning.text.clone(),
299//                         )
300//                         .aligned(),
301//                     ])
302//                     .align_children_center()
303//                     .contained()
304//                     .with_style(unauthorized_style.warning.container),
305//             )
306//             .with_child(theme::ui::cta_button::<Self, _, _, _>(
307//                 "Subscribe on GitHub",
308//                 style.auth.content_width,
309//                 &style.auth.cta_button,
310//                 cx,
311//                 |_, _, cx| {
312//                     cx.remove_window();
313//                     cx.platform().open_url(COPILOT_SIGN_UP_URL)
314//                 },
315//             ))
316//             .align_children_center()
317//             .into_any()
318//     }
319// }
320
321// impl Entity for CopilotCodeVerification {
322//     type Event = ();
323// }
324
325// impl View for CopilotCodeVerification {
326//     fn ui_name() -> &'static str {
327//         "CopilotCodeVerification"
328//     }
329
330//     fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
331//         cx.notify()
332//     }
333
334//     fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
335//         cx.notify()
336//     }
337
338//     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
339//         enum ConnectModal {}
340
341//         let style = theme::current(cx).clone();
342
343//         modal::<ConnectModal, _, _, _, _>(
344//             "Connect Copilot to Zed",
345//             &style.copilot.modal,
346//             cx,
347//             |cx| {
348//                 Flex::column()
349//                     .with_children([
350//                         theme::ui::icon(&style.copilot.auth.header).into_any(),
351//                         match &self.status {
352//                             Status::SigningIn {
353//                                 prompt: Some(prompt),
354//                             } => Self::render_prompting_modal(
355//                                 self.connect_clicked,
356//                                 &prompt,
357//                                 &style.copilot,
358//                                 cx,
359//                             ),
360//                             Status::Unauthorized => {
361//                                 self.connect_clicked = false;
362//                                 Self::render_unauthorized_modal(&style.copilot, cx)
363//                             }
364//                             Status::Authorized => {
365//                                 self.connect_clicked = false;
366//                                 Self::render_enabled_modal(&style.copilot, cx)
367//                             }
368//                             _ => Empty::new().into_any(),
369//                         },
370//                     ])
371//                     .align_children_center()
372//             },
373//         )
374//         .into_any()
375//     }
376// }