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// }