onboarding: Add some adjustments (#35887)

Release Notes:

- N/A
This commit is contained in:
Danilo Leal 2025-08-08 16:40:41 -03:00 committed by GitHub
parent b77a15d53a
commit 024a5bbcd0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 97 additions and 66 deletions

View file

@ -1187,7 +1187,8 @@
"ctrl-2": "onboarding::ActivateEditingPage", "ctrl-2": "onboarding::ActivateEditingPage",
"ctrl-3": "onboarding::ActivateAISetupPage", "ctrl-3": "onboarding::ActivateAISetupPage",
"ctrl-escape": "onboarding::Finish", "ctrl-escape": "onboarding::Finish",
"alt-tab": "onboarding::SignIn" "alt-tab": "onboarding::SignIn",
"alt-shift-a": "onboarding::OpenAccount"
} }
} }
] ]

View file

@ -1289,7 +1289,8 @@
"cmd-2": "onboarding::ActivateEditingPage", "cmd-2": "onboarding::ActivateEditingPage",
"cmd-3": "onboarding::ActivateAISetupPage", "cmd-3": "onboarding::ActivateAISetupPage",
"cmd-escape": "onboarding::Finish", "cmd-escape": "onboarding::Finish",
"alt-tab": "onboarding::SignIn" "alt-tab": "onboarding::SignIn",
"alt-shift-a": "onboarding::OpenAccount"
} }
} }
] ]

View file

@ -35,3 +35,11 @@ pub fn upgrade_to_zed_pro_url(cx: &App) -> String {
pub fn terms_of_service(cx: &App) -> String { pub fn terms_of_service(cx: &App) -> String {
format!("{server_url}/terms-of-service", server_url = server_url(cx)) format!("{server_url}/terms-of-service", server_url = server_url(cx))
} }
/// Returns the URL to Zed AI's privacy and security docs.
pub fn ai_privacy_and_security(cx: &App) -> String {
format!(
"{server_url}/docs/ai/privacy-and-security",
server_url = server_url(cx)
)
}

View file

@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use ai_onboarding::AiUpsellCard; use ai_onboarding::AiUpsellCard;
use client::{Client, UserStore}; use client::{Client, UserStore, zed_urls};
use fs::Fs; use fs::Fs;
use gpui::{ use gpui::{
Action, AnyView, App, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, WeakEntity, Action, AnyView, App, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, WeakEntity,
@ -42,10 +42,16 @@ fn render_llm_provider_section(
} }
fn render_privacy_card(tab_index: &mut isize, disabled: bool, cx: &mut App) -> impl IntoElement { fn render_privacy_card(tab_index: &mut isize, disabled: bool, cx: &mut App) -> impl IntoElement {
let privacy_badge = || { let (title, description) = if disabled {
Badge::new("Privacy") (
.icon(IconName::ShieldCheck) "AI is disabled across Zed",
.tooltip(move |_, cx| cx.new(|_| AiPrivacyTooltip::new()).into()) "Re-enable it any time in Settings.",
)
} else {
(
"Privacy is the default for Zed",
"Any use or storage of your data is with your explicit, single-use, opt-in consent.",
)
}; };
v_flex() v_flex()
@ -60,62 +66,41 @@ fn render_privacy_card(tab_index: &mut isize, disabled: bool, cx: &mut App) -> i
.bg(cx.theme().colors().surface_background.opacity(0.3)) .bg(cx.theme().colors().surface_background.opacity(0.3))
.rounded_lg() .rounded_lg()
.overflow_hidden() .overflow_hidden()
.map(|this| { .child(
if disabled { h_flex()
this.child( .gap_2()
.justify_between()
.child(Label::new(title))
.child(
h_flex() h_flex()
.gap_2() .gap_1()
.justify_between()
.child( .child(
h_flex() Badge::new("Privacy")
.gap_1() .icon(IconName::ShieldCheck)
.child(Label::new("AI is disabled across Zed")) .tooltip(move |_, cx| cx.new(|_| AiPrivacyTooltip::new()).into()),
.child(
Icon::new(IconName::Check)
.color(Color::Success)
.size(IconSize::XSmall),
),
) )
.child(privacy_badge()),
)
.child(
Label::new("Re-enable it any time in Settings.")
.size(LabelSize::Small)
.color(Color::Muted),
)
} else {
this.child(
h_flex()
.gap_2()
.justify_between()
.child(Label::new("Privacy is the default for Zed"))
.child( .child(
h_flex().gap_1().child(privacy_badge()).child( Button::new("learn_more", "Learn More")
Button::new("learn_more", "Learn More") .style(ButtonStyle::Outlined)
.style(ButtonStyle::Outlined) .label_size(LabelSize::Small)
.label_size(LabelSize::Small) .icon(IconName::ArrowUpRight)
.icon(IconName::ArrowUpRight) .icon_size(IconSize::XSmall)
.icon_size(IconSize::Small) .icon_color(Color::Muted)
.icon_color(Color::Muted) .on_click(|_, _, cx| {
.on_click(|_, _, cx| { cx.open_url(&zed_urls::ai_privacy_and_security(cx))
cx.open_url("https://zed.dev/docs/ai/privacy-and-security"); })
}) .tab_index({
.tab_index({ *tab_index += 1;
*tab_index += 1; *tab_index - 1
*tab_index - 1 }),
}),
),
), ),
) ),
.child( )
Label::new( .child(
"Any use or storage of your data is with your explicit, single-use, opt-in consent.", Label::new(description)
) .size(LabelSize::Small)
.size(LabelSize::Small) .color(Color::Muted),
.color(Color::Muted), )
)
}
})
} }
fn render_llm_provider_card( fn render_llm_provider_card(

View file

@ -655,7 +655,7 @@ fn render_popular_settings_section(
.child( .child(
SwitchField::new( SwitchField::new(
"onboarding-git-blame-switch", "onboarding-git-blame-switch",
"Git Blame", "Inline Git Blame",
Some("See who committed each line on a given file.".into()), Some("See who committed each line on a given file.".into()),
if read_git_blame(cx) { if read_git_blame(cx) {
ui::ToggleState::Selected ui::ToggleState::Selected

View file

@ -1,5 +1,5 @@
use crate::welcome::{ShowWelcome, WelcomePage}; use crate::welcome::{ShowWelcome, WelcomePage};
use client::{Client, UserStore}; use client::{Client, UserStore, zed_urls};
use command_palette_hooks::CommandPaletteFilter; use command_palette_hooks::CommandPaletteFilter;
use db::kvp::KEY_VALUE_STORE; use db::kvp::KEY_VALUE_STORE;
use feature_flags::{FeatureFlag, FeatureFlagViewExt as _}; use feature_flags::{FeatureFlag, FeatureFlagViewExt as _};
@ -78,7 +78,9 @@ actions!(
/// Finish the onboarding process. /// Finish the onboarding process.
Finish, Finish,
/// Sign in while in the onboarding flow. /// Sign in while in the onboarding flow.
SignIn SignIn,
/// Open the user account in zed.dev while in the onboarding flow.
OpenAccount
] ]
); );
@ -420,11 +422,40 @@ impl Onboarding {
) )
.child( .child(
if let Some(user) = self.user_store.read(cx).current_user() { if let Some(user) = self.user_store.read(cx).current_user() {
h_flex() v_flex()
.pl_1p5() .gap_1()
.gap_2() .child(
.child(Avatar::new(user.avatar_uri.clone())) h_flex()
.child(Label::new(user.github_login.clone())) .ml_2()
.gap_2()
.max_w_full()
.w_full()
.child(Avatar::new(user.avatar_uri.clone()))
.child(Label::new(user.github_login.clone()).truncate()),
)
.child(
ButtonLike::new("open_account")
.size(ButtonSize::Medium)
.child(
h_flex()
.ml_1()
.w_full()
.justify_between()
.child(Label::new("Open Account"))
.children(
KeyBinding::for_action_in(
&OpenAccount,
&self.focus_handle,
window,
cx,
)
.map(|kb| kb.size(rems_from_px(12.))),
),
)
.on_click(|_, window, cx| {
window.dispatch_action(OpenAccount.boxed_clone(), cx);
}),
)
.into_any_element() .into_any_element()
} else { } else {
Button::new("sign_in", "Sign In") Button::new("sign_in", "Sign In")
@ -460,6 +491,10 @@ impl Onboarding {
.detach(); .detach();
} }
fn handle_open_account(_: &OpenAccount, _: &mut Window, cx: &mut App) {
cx.open_url(&zed_urls::account_url(cx))
}
fn render_page(&mut self, window: &mut Window, cx: &mut Context<Self>) -> AnyElement { fn render_page(&mut self, window: &mut Window, cx: &mut Context<Self>) -> AnyElement {
let client = Client::global(cx); let client = Client::global(cx);
@ -495,6 +530,7 @@ impl Render for Onboarding {
.bg(cx.theme().colors().editor_background) .bg(cx.theme().colors().editor_background)
.on_action(Self::on_finish) .on_action(Self::on_finish)
.on_action(Self::handle_sign_in) .on_action(Self::handle_sign_in)
.on_action(Self::handle_open_account)
.on_action(cx.listener(|this, _: &ActivateBasicsPage, _, cx| { .on_action(cx.listener(|this, _: &ActivateBasicsPage, _, cx| {
this.set_page(SelectedPage::Basics, cx); this.set_page(SelectedPage::Basics, cx);
})) }))