parent
106d4cfce9
commit
070f7dbe1a
12 changed files with 155 additions and 72 deletions
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 6.4 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 5.3 KiB |
1
assets/images/pro_user_stamp.svg
Normal file
1
assets/images/pro_user_stamp.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 5.5 KiB |
|
@ -1103,6 +1103,13 @@
|
||||||
"ctrl-enter": "menu::Confirm"
|
"ctrl-enter": "menu::Confirm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"context": "OnboardingAiConfigurationModal",
|
||||||
|
"use_key_equivalents": true,
|
||||||
|
"bindings": {
|
||||||
|
"escape": "menu::Cancel"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"context": "Diagnostics",
|
"context": "Diagnostics",
|
||||||
"use_key_equivalents": true,
|
"use_key_equivalents": true,
|
||||||
|
@ -1179,7 +1186,8 @@
|
||||||
"ctrl-1": "onboarding::ActivateBasicsPage",
|
"ctrl-1": "onboarding::ActivateBasicsPage",
|
||||||
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1205,6 +1205,13 @@
|
||||||
"cmd-enter": "menu::Confirm"
|
"cmd-enter": "menu::Confirm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"context": "OnboardingAiConfigurationModal",
|
||||||
|
"use_key_equivalents": true,
|
||||||
|
"bindings": {
|
||||||
|
"escape": "menu::Cancel"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"context": "Diagnostics",
|
"context": "Diagnostics",
|
||||||
"use_key_equivalents": true,
|
"use_key_equivalents": true,
|
||||||
|
@ -1281,7 +1288,8 @@
|
||||||
"cmd-1": "onboarding::ActivateBasicsPage",
|
"cmd-1": "onboarding::ActivateBasicsPage",
|
||||||
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -137,7 +137,7 @@ impl RenderOnce for AiUpsellCard {
|
||||||
.size(rems_from_px(72.))
|
.size(rems_from_px(72.))
|
||||||
.child(
|
.child(
|
||||||
Vector::new(
|
Vector::new(
|
||||||
VectorName::CertifiedUserStamp,
|
VectorName::ProUserStamp,
|
||||||
rems_from_px(72.),
|
rems_from_px(72.),
|
||||||
rems_from_px(72.),
|
rems_from_px(72.),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ai_onboarding::{AiUpsellCard, SignInStatus};
|
use ai_onboarding::AiUpsellCard;
|
||||||
use client::UserStore;
|
use client::{Client, UserStore};
|
||||||
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,
|
||||||
|
@ -12,8 +12,8 @@ use language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageMod
|
||||||
use project::DisableAiSettings;
|
use project::DisableAiSettings;
|
||||||
use settings::{Settings, update_settings_file};
|
use settings::{Settings, update_settings_file};
|
||||||
use ui::{
|
use ui::{
|
||||||
Badge, ButtonLike, Divider, Modal, ModalFooter, ModalHeader, Section, SwitchField, ToggleState,
|
Badge, ButtonLike, Divider, KeyBinding, Modal, ModalFooter, ModalHeader, Section, SwitchField,
|
||||||
prelude::*, tooltip_container,
|
ToggleState, prelude::*, tooltip_container,
|
||||||
};
|
};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
use workspace::{ModalView, Workspace};
|
use workspace::{ModalView, Workspace};
|
||||||
|
@ -88,7 +88,7 @@ fn render_privacy_card(tab_index: &mut isize, disabled: bool, cx: &mut App) -> i
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.child(Label::new("We don't train models using your data"))
|
.child(Label::new("Privacy is the default for Zed"))
|
||||||
.child(
|
.child(
|
||||||
h_flex().gap_1().child(privacy_badge()).child(
|
h_flex().gap_1().child(privacy_badge()).child(
|
||||||
Button::new("learn_more", "Learn More")
|
Button::new("learn_more", "Learn More")
|
||||||
|
@ -109,7 +109,7 @@ fn render_privacy_card(tab_index: &mut isize, disabled: bool, cx: &mut App) -> i
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Label::new(
|
Label::new(
|
||||||
"Feel confident in the security and privacy of your projects using Zed.",
|
"Any use or storage of your data is with your explicit, single-use, opt-in consent.",
|
||||||
)
|
)
|
||||||
.size(LabelSize::Small)
|
.size(LabelSize::Small)
|
||||||
.color(Color::Muted),
|
.color(Color::Muted),
|
||||||
|
@ -240,6 +240,7 @@ fn render_llm_provider_card(
|
||||||
pub(crate) fn render_ai_setup_page(
|
pub(crate) fn render_ai_setup_page(
|
||||||
workspace: WeakEntity<Workspace>,
|
workspace: WeakEntity<Workspace>,
|
||||||
user_store: Entity<UserStore>,
|
user_store: Entity<UserStore>,
|
||||||
|
client: Arc<Client>,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
|
@ -283,15 +284,16 @@ pub(crate) fn render_ai_setup_page(
|
||||||
v_flex()
|
v_flex()
|
||||||
.mt_2()
|
.mt_2()
|
||||||
.gap_6()
|
.gap_6()
|
||||||
.child(AiUpsellCard {
|
.child({
|
||||||
sign_in_status: SignInStatus::SignedIn,
|
let mut ai_upsell_card =
|
||||||
sign_in: Arc::new(|_, _| {}),
|
AiUpsellCard::new(client, &user_store, user_store.read(cx).plan(), cx);
|
||||||
account_too_young: user_store.read(cx).account_too_young(),
|
|
||||||
user_plan: user_store.read(cx).plan(),
|
ai_upsell_card.tab_index = Some({
|
||||||
tab_index: Some({
|
|
||||||
tab_index += 1;
|
tab_index += 1;
|
||||||
tab_index - 1
|
tab_index - 1
|
||||||
}),
|
});
|
||||||
|
|
||||||
|
ai_upsell_card
|
||||||
})
|
})
|
||||||
.child(render_llm_provider_section(
|
.child(render_llm_provider_section(
|
||||||
&mut tab_index,
|
&mut tab_index,
|
||||||
|
@ -336,6 +338,10 @@ impl AiConfigurationModal {
|
||||||
selected_provider,
|
selected_provider,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn cancel(&mut self, _: &menu::Cancel, cx: &mut Context<Self>) {
|
||||||
|
cx.emit(DismissEvent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModalView for AiConfigurationModal {}
|
impl ModalView for AiConfigurationModal {}
|
||||||
|
@ -349,11 +355,15 @@ impl Focusable for AiConfigurationModal {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for AiConfigurationModal {
|
impl Render for AiConfigurationModal {
|
||||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
v_flex()
|
v_flex()
|
||||||
|
.key_context("OnboardingAiConfigurationModal")
|
||||||
.w(rems(34.))
|
.w(rems(34.))
|
||||||
.elevation_3(cx)
|
.elevation_3(cx)
|
||||||
.track_focus(&self.focus_handle)
|
.track_focus(&self.focus_handle)
|
||||||
|
.on_action(
|
||||||
|
cx.listener(|this, _: &menu::Cancel, _window, cx| this.cancel(&menu::Cancel, cx)),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
Modal::new("onboarding-ai-setup-modal", None)
|
Modal::new("onboarding-ai-setup-modal", None)
|
||||||
.header(
|
.header(
|
||||||
|
@ -368,18 +378,19 @@ impl Render for AiConfigurationModal {
|
||||||
.section(Section::new().child(self.configuration_view.clone()))
|
.section(Section::new().child(self.configuration_view.clone()))
|
||||||
.footer(
|
.footer(
|
||||||
ModalFooter::new().end_slot(
|
ModalFooter::new().end_slot(
|
||||||
h_flex()
|
Button::new("ai-onb-modal-Done", "Done")
|
||||||
.gap_1()
|
.key_binding(
|
||||||
.child(
|
KeyBinding::for_action_in(
|
||||||
Button::new("onboarding-closing-cancel", "Cancel")
|
&menu::Cancel,
|
||||||
.on_click(cx.listener(|_, _, _, cx| cx.emit(DismissEvent))),
|
&self.focus_handle.clone(),
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.map(|kb| kb.size(rems_from_px(12.))),
|
||||||
)
|
)
|
||||||
.child(Button::new("save-btn", "Done").on_click(cx.listener(
|
.on_click(cx.listener(|this, _event, _window, cx| {
|
||||||
|_, _, window, cx| {
|
this.cancel(&menu::Cancel, cx)
|
||||||
window.dispatch_action(menu::Confirm.boxed_clone(), cx);
|
})),
|
||||||
cx.emit(DismissEvent);
|
|
||||||
},
|
|
||||||
))),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -396,7 +407,7 @@ impl AiPrivacyTooltip {
|
||||||
|
|
||||||
impl Render for AiPrivacyTooltip {
|
impl Render for AiPrivacyTooltip {
|
||||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
const DESCRIPTION: &'static str = "One of Zed's most important principles is transparency. This is why we are and value open-source so much. And it wouldn't be any different with AI.";
|
const DESCRIPTION: &'static str = "We believe in opt-in data sharing as the default for building AI products, rather than opt-out. We'll only use or store your data if you affirmatively send it to us. ";
|
||||||
|
|
||||||
tooltip_container(window, cx, move |this, _, _| {
|
tooltip_container(window, cx, move |this, _, _| {
|
||||||
this.child(
|
this.child(
|
||||||
|
@ -407,7 +418,7 @@ impl Render for AiPrivacyTooltip {
|
||||||
.size(IconSize::Small)
|
.size(IconSize::Small)
|
||||||
.color(Color::Muted),
|
.color(Color::Muted),
|
||||||
)
|
)
|
||||||
.child(Label::new("Privacy Principle")),
|
.child(Label::new("Privacy First")),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div().max_w_64().child(
|
div().max_w_64().child(
|
||||||
|
|
|
@ -201,12 +201,15 @@ fn render_telemetry_section(tab_index: &mut isize, cx: &App) -> impl IntoElement
|
||||||
let fs = <dyn Fs>::global(cx);
|
let fs = <dyn Fs>::global(cx);
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
|
.pt_6()
|
||||||
.gap_4()
|
.gap_4()
|
||||||
|
.border_t_1()
|
||||||
|
.border_color(cx.theme().colors().border_variant.opacity(0.5))
|
||||||
.child(Label::new("Telemetry").size(LabelSize::Large))
|
.child(Label::new("Telemetry").size(LabelSize::Large))
|
||||||
.child(SwitchField::new(
|
.child(SwitchField::new(
|
||||||
"onboarding-telemetry-metrics",
|
"onboarding-telemetry-metrics",
|
||||||
"Help Improve Zed",
|
"Help Improve Zed",
|
||||||
Some("Sending anonymous usage data helps us build the right features and create the best experience.".into()),
|
Some("Anonymous usage data helps us build the right features and improve your experience.".into()),
|
||||||
if TelemetrySettings::get_global(cx).metrics {
|
if TelemetrySettings::get_global(cx).metrics {
|
||||||
ui::ToggleState::Selected
|
ui::ToggleState::Selected
|
||||||
} else {
|
} else {
|
||||||
|
@ -294,7 +297,7 @@ fn render_base_keymap_section(tab_index: &mut isize, cx: &mut App) -> impl IntoE
|
||||||
ToggleButtonWithIcon::new("Emacs", IconName::EditorEmacs, |_, _, cx| {
|
ToggleButtonWithIcon::new("Emacs", IconName::EditorEmacs, |_, _, cx| {
|
||||||
write_keymap_base(BaseKeymap::Emacs, cx);
|
write_keymap_base(BaseKeymap::Emacs, cx);
|
||||||
}),
|
}),
|
||||||
ToggleButtonWithIcon::new("Cursor (Beta)", IconName::EditorCursor, |_, _, cx| {
|
ToggleButtonWithIcon::new("Cursor", IconName::EditorCursor, |_, _, cx| {
|
||||||
write_keymap_base(BaseKeymap::Cursor, cx);
|
write_keymap_base(BaseKeymap::Cursor, cx);
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
@ -326,10 +329,7 @@ fn render_vim_mode_switch(tab_index: &mut isize, cx: &mut App) -> impl IntoEleme
|
||||||
SwitchField::new(
|
SwitchField::new(
|
||||||
"onboarding-vim-mode",
|
"onboarding-vim-mode",
|
||||||
"Vim Mode",
|
"Vim Mode",
|
||||||
Some(
|
Some("Coming from Neovim? Use our first-class implementation of Vim Mode.".into()),
|
||||||
"Coming from Neovim? Zed's first-class implementation of Vim Mode has got your back."
|
|
||||||
.into(),
|
|
||||||
),
|
|
||||||
toggle_state,
|
toggle_state,
|
||||||
{
|
{
|
||||||
let fs = <dyn Fs>::global(cx);
|
let fs = <dyn Fs>::global(cx);
|
||||||
|
|
|
@ -584,11 +584,15 @@ fn render_popular_settings_section(
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
const LIGATURE_TOOLTIP: &'static str = "Ligatures are when a font creates a special character out of combining two characters into one. For example, with ligatures turned on, =/= would become ≠.";
|
const LIGATURE_TOOLTIP: &'static str =
|
||||||
|
"Font ligatures combine two characters into one. For example, turning =/= into ≠.";
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_5()
|
.pt_6()
|
||||||
.child(Label::new("Popular Settings").size(LabelSize::Large).mt_8())
|
.gap_4()
|
||||||
|
.border_t_1()
|
||||||
|
.border_color(cx.theme().colors().border_variant.opacity(0.5))
|
||||||
|
.child(Label::new("Popular Settings").size(LabelSize::Large))
|
||||||
.child(render_font_customization_section(tab_index, window, cx))
|
.child(render_font_customization_section(tab_index, window, cx))
|
||||||
.child(
|
.child(
|
||||||
SwitchField::new(
|
SwitchField::new(
|
||||||
|
@ -683,7 +687,10 @@ fn render_popular_settings_section(
|
||||||
[
|
[
|
||||||
ToggleButtonSimple::new("Auto", |_, _, cx| {
|
ToggleButtonSimple::new("Auto", |_, _, cx| {
|
||||||
write_show_mini_map(ShowMinimap::Auto, cx);
|
write_show_mini_map(ShowMinimap::Auto, cx);
|
||||||
}),
|
})
|
||||||
|
.tooltip(Tooltip::text(
|
||||||
|
"Show the minimap if the editor's scrollbar is visible.",
|
||||||
|
)),
|
||||||
ToggleButtonSimple::new("Always", |_, _, cx| {
|
ToggleButtonSimple::new("Always", |_, _, cx| {
|
||||||
write_show_mini_map(ShowMinimap::Always, cx);
|
write_show_mini_map(ShowMinimap::Always, cx);
|
||||||
}),
|
}),
|
||||||
|
@ -707,7 +714,7 @@ fn render_popular_settings_section(
|
||||||
pub(crate) fn render_editing_page(window: &mut Window, cx: &mut App) -> impl IntoElement {
|
pub(crate) fn render_editing_page(window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||||
let mut tab_index = 0;
|
let mut tab_index = 0;
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_4()
|
.gap_6()
|
||||||
.child(render_import_settings_section(&mut tab_index, cx))
|
.child(render_import_settings_section(&mut tab_index, cx))
|
||||||
.child(render_popular_settings_section(&mut tab_index, window, cx))
|
.child(render_popular_settings_section(&mut tab_index, window, cx))
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,8 @@ actions!(
|
||||||
ActivateAISetupPage,
|
ActivateAISetupPage,
|
||||||
/// Finish the onboarding process.
|
/// Finish the onboarding process.
|
||||||
Finish,
|
Finish,
|
||||||
|
/// Sign in while in the onboarding flow.
|
||||||
|
SignIn
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -376,6 +378,7 @@ impl Onboarding {
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.map(|kb| kb.size(rems_from_px(12.)));
|
.map(|kb| kb.size(rems_from_px(12.)));
|
||||||
|
|
||||||
if ai_setup_page {
|
if ai_setup_page {
|
||||||
this.child(
|
this.child(
|
||||||
ButtonLike::new("start_building")
|
ButtonLike::new("start_building")
|
||||||
|
@ -387,14 +390,7 @@ impl Onboarding {
|
||||||
.w_full()
|
.w_full()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.child(Label::new("Start Building"))
|
.child(Label::new("Start Building"))
|
||||||
.child(keybinding.map_or_else(
|
.children(keybinding),
|
||||||
|| {
|
|
||||||
Icon::new(IconName::Check)
|
|
||||||
.size(IconSize::Small)
|
|
||||||
.into_any_element()
|
|
||||||
},
|
|
||||||
IntoElement::into_any_element,
|
|
||||||
)),
|
|
||||||
)
|
)
|
||||||
.on_click(|_, window, cx| {
|
.on_click(|_, window, cx| {
|
||||||
window.dispatch_action(Finish.boxed_clone(), cx);
|
window.dispatch_action(Finish.boxed_clone(), cx);
|
||||||
|
@ -409,11 +405,10 @@ impl Onboarding {
|
||||||
.ml_1()
|
.ml_1()
|
||||||
.w_full()
|
.w_full()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.child(Label::new("Skip All"))
|
.child(
|
||||||
.child(keybinding.map_or_else(
|
Label::new("Skip All").color(Color::Muted),
|
||||||
|| gpui::Empty.into_any_element(),
|
)
|
||||||
IntoElement::into_any_element,
|
.children(keybinding),
|
||||||
)),
|
|
||||||
)
|
)
|
||||||
.on_click(|_, window, cx| {
|
.on_click(|_, window, cx| {
|
||||||
window.dispatch_action(Finish.boxed_clone(), cx);
|
window.dispatch_action(Finish.boxed_clone(), cx);
|
||||||
|
@ -435,23 +430,39 @@ impl Onboarding {
|
||||||
Button::new("sign_in", "Sign In")
|
Button::new("sign_in", "Sign In")
|
||||||
.full_width()
|
.full_width()
|
||||||
.style(ButtonStyle::Outlined)
|
.style(ButtonStyle::Outlined)
|
||||||
|
.size(ButtonSize::Medium)
|
||||||
|
.key_binding(
|
||||||
|
KeyBinding::for_action_in(&SignIn, &self.focus_handle, window, cx)
|
||||||
|
.map(|kb| kb.size(rems_from_px(12.))),
|
||||||
|
)
|
||||||
.on_click(|_, window, cx| {
|
.on_click(|_, window, cx| {
|
||||||
let client = Client::global(cx);
|
window.dispatch_action(SignIn.boxed_clone(), cx);
|
||||||
window
|
|
||||||
.spawn(cx, async move |cx| {
|
|
||||||
client
|
|
||||||
.sign_in_with_optional_connect(true, &cx)
|
|
||||||
.await
|
|
||||||
.notify_async_err(cx);
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
})
|
})
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_finish(_: &Finish, _: &mut Window, cx: &mut App) {
|
||||||
|
go_to_welcome_page(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_sign_in(_: &SignIn, window: &mut Window, cx: &mut App) {
|
||||||
|
let client = Client::global(cx);
|
||||||
|
|
||||||
|
window
|
||||||
|
.spawn(cx, async move |cx| {
|
||||||
|
client
|
||||||
|
.sign_in_with_optional_connect(true, &cx)
|
||||||
|
.await
|
||||||
|
.notify_async_err(cx);
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
match self.selected_page {
|
match self.selected_page {
|
||||||
SelectedPage::Basics => crate::basics_page::render_basics_page(cx).into_any_element(),
|
SelectedPage::Basics => crate::basics_page::render_basics_page(cx).into_any_element(),
|
||||||
SelectedPage::Editing => {
|
SelectedPage::Editing => {
|
||||||
|
@ -460,16 +471,13 @@ impl Onboarding {
|
||||||
SelectedPage::AiSetup => crate::ai_setup_page::render_ai_setup_page(
|
SelectedPage::AiSetup => crate::ai_setup_page::render_ai_setup_page(
|
||||||
self.workspace.clone(),
|
self.workspace.clone(),
|
||||||
self.user_store.clone(),
|
self.user_store.clone(),
|
||||||
|
client,
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_finish(_: &Finish, _: &mut Window, cx: &mut App) {
|
|
||||||
go_to_welcome_page(cx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for Onboarding {
|
impl Render for Onboarding {
|
||||||
|
@ -486,6 +494,7 @@ impl Render for Onboarding {
|
||||||
.size_full()
|
.size_full()
|
||||||
.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(cx.listener(|this, _: &ActivateBasicsPage, _, cx| {
|
.on_action(cx.listener(|this, _: &ActivateBasicsPage, _, cx| {
|
||||||
this.set_page(SelectedPage::Basics, cx);
|
this.set_page(SelectedPage::Basics, cx);
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use gpui::{AnyView, ClickEvent};
|
use gpui::{AnyView, ClickEvent};
|
||||||
|
|
||||||
use crate::{ButtonLike, ButtonLikeRounding, ElevationIndex, TintColor, prelude::*};
|
use crate::{ButtonLike, ButtonLikeRounding, ElevationIndex, TintColor, Tooltip, prelude::*};
|
||||||
|
|
||||||
/// The position of a [`ToggleButton`] within a group of buttons.
|
/// The position of a [`ToggleButton`] within a group of buttons.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
@ -301,6 +303,7 @@ pub struct ButtonConfiguration {
|
||||||
icon: Option<IconName>,
|
icon: Option<IconName>,
|
||||||
on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
|
tooltip: Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyView>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
mod private {
|
mod private {
|
||||||
|
@ -315,6 +318,7 @@ pub struct ToggleButtonSimple {
|
||||||
label: SharedString,
|
label: SharedString,
|
||||||
on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
|
tooltip: Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyView>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToggleButtonSimple {
|
impl ToggleButtonSimple {
|
||||||
|
@ -326,6 +330,7 @@ impl ToggleButtonSimple {
|
||||||
label: label.into(),
|
label: label.into(),
|
||||||
on_click: Box::new(on_click),
|
on_click: Box::new(on_click),
|
||||||
selected: false,
|
selected: false,
|
||||||
|
tooltip: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,6 +338,11 @@ impl ToggleButtonSimple {
|
||||||
self.selected = selected;
|
self.selected = selected;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||||
|
self.tooltip = Some(Rc::new(tooltip));
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl private::ToggleButtonStyle for ToggleButtonSimple {}
|
impl private::ToggleButtonStyle for ToggleButtonSimple {}
|
||||||
|
@ -344,6 +354,7 @@ impl ButtonBuilder for ToggleButtonSimple {
|
||||||
icon: None,
|
icon: None,
|
||||||
on_click: self.on_click,
|
on_click: self.on_click,
|
||||||
selected: self.selected,
|
selected: self.selected,
|
||||||
|
tooltip: self.tooltip,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,6 +364,7 @@ pub struct ToggleButtonWithIcon {
|
||||||
icon: IconName,
|
icon: IconName,
|
||||||
on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
on_click: Box<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
|
tooltip: Option<Rc<dyn Fn(&mut Window, &mut App) -> AnyView>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToggleButtonWithIcon {
|
impl ToggleButtonWithIcon {
|
||||||
|
@ -366,6 +378,7 @@ impl ToggleButtonWithIcon {
|
||||||
icon,
|
icon,
|
||||||
on_click: Box::new(on_click),
|
on_click: Box::new(on_click),
|
||||||
selected: false,
|
selected: false,
|
||||||
|
tooltip: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,6 +386,11 @@ impl ToggleButtonWithIcon {
|
||||||
self.selected = selected;
|
self.selected = selected;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tooltip(mut self, tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static) -> Self {
|
||||||
|
self.tooltip = Some(Rc::new(tooltip));
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl private::ToggleButtonStyle for ToggleButtonWithIcon {}
|
impl private::ToggleButtonStyle for ToggleButtonWithIcon {}
|
||||||
|
@ -384,6 +402,7 @@ impl ButtonBuilder for ToggleButtonWithIcon {
|
||||||
icon: Some(self.icon),
|
icon: Some(self.icon),
|
||||||
on_click: self.on_click,
|
on_click: self.on_click,
|
||||||
selected: self.selected,
|
selected: self.selected,
|
||||||
|
tooltip: self.tooltip,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,11 +505,13 @@ impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> RenderOnce
|
||||||
icon,
|
icon,
|
||||||
on_click,
|
on_click,
|
||||||
selected,
|
selected,
|
||||||
|
tooltip,
|
||||||
} = button.into_configuration();
|
} = button.into_configuration();
|
||||||
|
|
||||||
let entry_index = row_index * COLS + col_index;
|
let entry_index = row_index * COLS + col_index;
|
||||||
|
|
||||||
ButtonLike::new((self.group_name, entry_index))
|
ButtonLike::new((self.group_name, entry_index))
|
||||||
|
.rounding(None)
|
||||||
.when_some(self.tab_index, |this, tab_index| {
|
.when_some(self.tab_index, |this, tab_index| {
|
||||||
this.tab_index(tab_index + entry_index as isize)
|
this.tab_index(tab_index + entry_index as isize)
|
||||||
})
|
})
|
||||||
|
@ -498,7 +519,6 @@ impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> RenderOnce
|
||||||
this.toggle_state(true)
|
this.toggle_state(true)
|
||||||
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
|
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
|
||||||
})
|
})
|
||||||
.rounding(None)
|
|
||||||
.when(self.style == ToggleButtonGroupStyle::Filled, |button| {
|
.when(self.style == ToggleButtonGroupStyle::Filled, |button| {
|
||||||
button.style(ButtonStyle::Filled)
|
button.style(ButtonStyle::Filled)
|
||||||
})
|
})
|
||||||
|
@ -527,6 +547,9 @@ impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> RenderOnce
|
||||||
|this| this.color(Color::Accent),
|
|this| this.color(Color::Accent),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
.when_some(tooltip, |this, tooltip| {
|
||||||
|
this.tooltip(move |window, cx| tooltip(window, cx))
|
||||||
|
})
|
||||||
.on_click(on_click)
|
.on_click(on_click)
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
})
|
})
|
||||||
|
@ -920,6 +943,23 @@ impl<T: ButtonBuilder, const COLS: usize, const ROWS: usize> Component
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)])
|
)])
|
||||||
|
.children(vec![single_example(
|
||||||
|
"With Tooltips",
|
||||||
|
ToggleButtonGroup::single_row(
|
||||||
|
"with_tooltips",
|
||||||
|
[
|
||||||
|
ToggleButtonSimple::new("First", |_, _, _| {})
|
||||||
|
.tooltip(Tooltip::text("This is a tooltip. Hello!")),
|
||||||
|
ToggleButtonSimple::new("Second", |_, _, _| {})
|
||||||
|
.tooltip(Tooltip::text("This is a tooltip. Hey?")),
|
||||||
|
ToggleButtonSimple::new("Third", |_, _, _| {})
|
||||||
|
.tooltip(Tooltip::text("This is a tooltip. Get out of here now!")),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.selected_index(1)
|
||||||
|
.button_width(rems_from_px(100.))
|
||||||
|
.into_any_element(),
|
||||||
|
)])
|
||||||
.into_any_element(),
|
.into_any_element(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,10 @@ use crate::prelude::*;
|
||||||
#[strum(serialize_all = "snake_case")]
|
#[strum(serialize_all = "snake_case")]
|
||||||
pub enum VectorName {
|
pub enum VectorName {
|
||||||
AiGrid,
|
AiGrid,
|
||||||
CertifiedUserStamp,
|
|
||||||
DebuggerGrid,
|
DebuggerGrid,
|
||||||
Grid,
|
Grid,
|
||||||
ProTrialStamp,
|
ProTrialStamp,
|
||||||
|
ProUserStamp,
|
||||||
ZedLogo,
|
ZedLogo,
|
||||||
ZedXCopilot,
|
ZedXCopilot,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue