Add refinements to the AI onboarding flow (#33738)

This includes making sure that both the agent panel and Zed's edit
prediction have a consistent narrative when it comes to onboarding users
into the AI features, considering the possible different plans and
conditions (such as being signed in/out, account age, etc.)

Release Notes:

- N/A

---------

Co-authored-by: Bennet Bo Fenner <53836821+bennetbo@users.noreply.github.com>
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
This commit is contained in:
Danilo Leal 2025-07-18 13:25:36 -03:00 committed by GitHub
parent 9a20843ba2
commit 4476860664
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 1465 additions and 1215 deletions

View file

@ -46,6 +46,7 @@ actions!(
);
const COPILOT_SETTINGS_URL: &str = "https://github.com/settings/copilot";
const PRIVACY_DOCS: &str = "https://zed.dev/docs/ai/privacy-and-security";
struct CopilotErrorToast;
@ -193,13 +194,13 @@ impl Render for InlineCompletionButton {
cx.open_url(activate_url.as_str())
})
.entry(
"Use Copilot",
"Use Zed AI",
None,
move |_, cx| {
set_completion_provider(
fs.clone(),
cx,
EditPredictionProvider::Copilot,
EditPredictionProvider::Zed,
)
},
)
@ -239,22 +240,13 @@ impl Render for InlineCompletionButton {
IconName::ZedPredictDisabled
};
let current_user_terms_accepted =
self.user_store.read(cx).current_user_has_accepted_terms();
let has_subscription = self.user_store.read(cx).current_plan().is_some()
&& self.user_store.read(cx).subscription_period().is_some();
if !has_subscription || !current_user_terms_accepted.unwrap_or(false) {
let signed_in = current_user_terms_accepted.is_some();
let tooltip_meta = if signed_in {
if has_subscription {
"Read Terms of Service"
} else {
"Choose a Plan"
}
} else {
"Sign in to use"
};
if zeta::should_show_upsell_modal(&self.user_store, cx) {
let tooltip_meta =
match self.user_store.read(cx).current_user_has_accepted_terms() {
Some(true) => "Choose a Plan",
Some(false) => "Accept the Terms of Service",
None => "Sign In",
};
return div().child(
IconButton::new("zed-predict-pending-button", zeta_icon)
@ -403,15 +395,16 @@ impl InlineCompletionButton {
) -> Entity<ContextMenu> {
let fs = self.fs.clone();
ContextMenu::build(window, cx, |menu, _, _| {
menu.entry("Sign In", None, copilot::initiate_sign_in)
menu.entry("Sign In to Copilot", None, copilot::initiate_sign_in)
.entry("Disable Copilot", None, {
let fs = fs.clone();
move |_window, cx| hide_copilot(fs.clone(), cx)
})
.entry("Use Supermaven", None, {
.separator()
.entry("Use Zed AI", None, {
let fs = fs.clone();
move |_window, cx| {
set_completion_provider(fs.clone(), cx, EditPredictionProvider::Supermaven)
set_completion_provider(fs.clone(), cx, EditPredictionProvider::Zed)
}
})
})
@ -518,7 +511,7 @@ impl InlineCompletionButton {
);
}
menu = menu.separator().header("Privacy Settings");
menu = menu.separator().header("Privacy");
if let Some(provider) = &self.edit_prediction_provider {
let data_collection = provider.data_collection_state(cx);
if data_collection.is_supported() {
@ -569,13 +562,15 @@ impl InlineCompletionButton {
.child(
Label::new(indoc!{
"Help us improve our open dataset model by sharing data from open source repositories. \
Zed must detect a license file in your repo for this setting to take effect."
Zed must detect a license file in your repo for this setting to take effect. \
Files with sensitive data and secrets are excluded by default."
})
)
.child(
h_flex()
.items_start()
.pt_2()
.pr_1()
.flex_1()
.gap_1p5()
.border_t_1()
@ -635,6 +630,13 @@ impl InlineCompletionButton {
.detach_and_log_err(cx);
}
}),
).item(
ContextMenuEntry::new("View Documentation")
.icon(IconName::FileGeneric)
.icon_color(Color::Muted)
.handler(move |_, cx| {
cx.open_url(PRIVACY_DOCS);
})
);
if !self.editor_enabled.unwrap_or(true) {
@ -672,6 +674,13 @@ impl InlineCompletionButton {
) -> Entity<ContextMenu> {
ContextMenu::build(window, cx, |menu, window, cx| {
self.build_language_settings_menu(menu, window, cx)
.separator()
.entry("Use Zed AI instead", None, {
let fs = self.fs.clone();
move |_window, cx| {
set_completion_provider(fs.clone(), cx, EditPredictionProvider::Zed)
}
})
.separator()
.link(
"Go to Copilot Settings",
@ -750,44 +759,24 @@ impl InlineCompletionButton {
menu = menu
.custom_entry(
|_window, _cx| {
h_flex()
.gap_1()
.child(
Icon::new(IconName::Warning)
.size(IconSize::Small)
.color(Color::Warning),
)
.child(
Label::new("Your GitHub account is less than 30 days old")
.size(LabelSize::Small)
.color(Color::Warning),
)
Label::new("Your GitHub account is less than 30 days old.")
.size(LabelSize::Small)
.color(Color::Warning)
.into_any_element()
},
|_window, cx| cx.open_url(&zed_urls::account_url(cx)),
)
.entry(
"You need to upgrade to Zed Pro or contact us.",
None,
|_window, cx| cx.open_url(&zed_urls::account_url(cx)),
)
.entry("Upgrade to Zed Pro or contact us.", None, |_window, cx| {
cx.open_url(&zed_urls::account_url(cx))
})
.separator();
} else if self.user_store.read(cx).has_overdue_invoices() {
menu = menu
.custom_entry(
|_window, _cx| {
h_flex()
.gap_1()
.child(
Icon::new(IconName::Warning)
.size(IconSize::Small)
.color(Color::Warning),
)
.child(
Label::new("You have an outstanding invoice")
.size(LabelSize::Small)
.color(Color::Warning),
)
Label::new("You have an outstanding invoice")
.size(LabelSize::Small)
.color(Color::Warning)
.into_any_element()
},
|_window, cx| {