Cargo.lock 🔗
@@ -3672,6 +3672,7 @@ dependencies = [
"task",
"theme",
"ui",
+ "url",
"util",
"workspace",
"zlog",
Moritz Bitsch created
Use the url crate to extract the domain from the verification URI and
construct the appropriate Copilot sign-up URL for GitHub or GitHub
Enterprise.
Release Notes:
- Improved github enterprise (ghe) copilot sign in
Cargo.lock | 1
crates/copilot/Cargo.toml | 1
crates/copilot/src/sign_in.rs | 44 ++++++++++++++++++++++++++++++++++--
3 files changed, 43 insertions(+), 3 deletions(-)
@@ -3672,6 +3672,7 @@ dependencies = [
"task",
"theme",
"ui",
+ "url",
"util",
"workspace",
"zlog",
@@ -52,6 +52,7 @@ ui.workspace = true
util.workspace = true
workspace.workspace = true
itertools.workspace = true
+url.workspace = true
[target.'cfg(windows)'.dependencies]
async-std = { version = "1.12.0", features = ["unstable"] }
@@ -6,6 +6,7 @@ use gpui::{
Subscription, Window, WindowBounds, WindowOptions, div, point,
};
use ui::{ButtonLike, CommonAnimationExt, ConfiguredApiCard, Vector, VectorName, prelude::*};
+use url::Url;
use util::ResultExt as _;
use workspace::{Toast, Workspace, notifications::NotificationId};
@@ -152,6 +153,7 @@ pub struct CopilotCodeVerification {
focus_handle: FocusHandle,
copilot: Entity<Copilot>,
_subscription: Subscription,
+ sign_up_url: Option<String>,
}
impl Focusable for CopilotCodeVerification {
@@ -183,11 +185,22 @@ impl CopilotCodeVerification {
.detach();
let status = copilot.read(cx).status();
+ // Determine sign-up URL based on verification_uri domain if available
+ let sign_up_url = if let Status::SigningIn {
+ prompt: Some(ref prompt),
+ } = status
+ {
+ // Extract domain from verification_uri to construct sign-up URL
+ Self::get_sign_up_url_from_verification(&prompt.verification_uri)
+ } else {
+ None
+ };
Self {
status,
connect_clicked: false,
focus_handle: cx.focus_handle(),
copilot: copilot.clone(),
+ sign_up_url,
_subscription: cx.observe(copilot, |this, copilot, cx| {
let status = copilot.read(cx).status();
match status {
@@ -201,10 +214,30 @@ impl CopilotCodeVerification {
}
pub fn set_status(&mut self, status: Status, cx: &mut Context<Self>) {
+ // Update sign-up URL if we have a new verification URI
+ if let Status::SigningIn {
+ prompt: Some(ref prompt),
+ } = status
+ {
+ self.sign_up_url = Self::get_sign_up_url_from_verification(&prompt.verification_uri);
+ }
self.status = status;
cx.notify();
}
+ fn get_sign_up_url_from_verification(verification_uri: &str) -> Option<String> {
+ // Extract domain from verification URI using url crate
+ if let Ok(url) = Url::parse(verification_uri)
+ && let Some(host) = url.host_str()
+ && !host.contains("github.com")
+ {
+ // For GHE, construct URL from domain
+ Some(format!("https://{}/features/copilot", host))
+ } else {
+ None
+ }
+ }
+
fn render_device_code(data: &PromptUserDeviceFlow, cx: &mut Context<Self>) -> impl IntoElement {
let copied = cx
.read_from_clipboard()
@@ -302,7 +335,12 @@ impl CopilotCodeVerification {
)
}
- fn render_unauthorized_modal(cx: &mut Context<Self>) -> impl Element {
+ fn render_unauthorized_modal(&self, cx: &mut Context<Self>) -> impl Element {
+ let sign_up_url = self
+ .sign_up_url
+ .as_deref()
+ .unwrap_or(COPILOT_SIGN_UP_URL)
+ .to_owned();
let description = "Enable Copilot by connecting your existing license once you have subscribed or renewed your subscription.";
v_flex()
@@ -319,7 +357,7 @@ impl CopilotCodeVerification {
.full_width()
.style(ButtonStyle::Outlined)
.size(ButtonSize::Medium)
- .on_click(|_, _, cx| cx.open_url(COPILOT_SIGN_UP_URL)),
+ .on_click(move |_, _, cx| cx.open_url(&sign_up_url)),
)
.child(
Button::new("copilot-subscribe-cancel-button", "Cancel")
@@ -374,7 +412,7 @@ impl Render for CopilotCodeVerification {
} => Self::render_prompting_modal(self.connect_clicked, prompt, cx).into_any_element(),
Status::Unauthorized => {
self.connect_clicked = false;
- Self::render_unauthorized_modal(cx).into_any_element()
+ self.render_unauthorized_modal(cx).into_any_element()
}
Status::Authorized => {
self.connect_clicked = false;