zeta: Onboarding and title bar banner (#23797)

Release Notes:

- N/A

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: Danilo <danilo@zed.dev>
Co-authored-by: João Marcos <joao@zed.dev>
This commit is contained in:
Agus Zubiaga 2025-01-30 16:55:32 -03:00 committed by GitHub
parent 4ab372d6b5
commit e23e03592b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 1207 additions and 249 deletions

View file

@ -379,6 +379,12 @@ pub mod simple_message_notification {
click_message: Option<SharedString>,
secondary_click_message: Option<SharedString>,
secondary_on_click: Option<Arc<dyn Fn(&mut Window, &mut Context<Self>)>>,
tertiary_click_message: Option<SharedString>,
tertiary_on_click: Option<Arc<dyn Fn(&mut Window, &mut Context<Self>)>>,
more_info_message: Option<SharedString>,
more_info_url: Option<Arc<str>>,
show_close_button: bool,
title: Option<SharedString>,
}
impl EventEmitter<DismissEvent> for MessageNotification {}
@ -402,6 +408,12 @@ pub mod simple_message_notification {
click_message: None,
secondary_on_click: None,
secondary_click_message: None,
tertiary_on_click: None,
tertiary_click_message: None,
more_info_message: None,
more_info_url: None,
show_close_button: true,
title: None,
}
}
@ -437,31 +449,85 @@ pub mod simple_message_notification {
self
}
pub fn with_tertiary_click_message<S>(mut self, message: S) -> Self
where
S: Into<SharedString>,
{
self.tertiary_click_message = Some(message.into());
self
}
pub fn on_tertiary_click<F>(mut self, on_click: F) -> Self
where
F: 'static + Fn(&mut Window, &mut Context<Self>),
{
self.tertiary_on_click = Some(Arc::new(on_click));
self
}
pub fn more_info_message<S>(mut self, message: S) -> Self
where
S: Into<SharedString>,
{
self.more_info_message = Some(message.into());
self
}
pub fn more_info_url<S>(mut self, url: S) -> Self
where
S: Into<Arc<str>>,
{
self.more_info_url = Some(url.into());
self
}
pub fn dismiss(&mut self, cx: &mut Context<Self>) {
cx.emit(DismissEvent);
}
pub fn show_close_button(mut self, show: bool) -> Self {
self.show_close_button = show;
self
}
pub fn with_title<S>(mut self, title: S) -> Self
where
S: Into<SharedString>,
{
self.title = Some(title.into());
self
}
}
impl Render for MessageNotification {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex()
.p_3()
.gap_2()
.gap_3()
.elevation_3(cx)
.child(
h_flex()
.gap_4()
.justify_between()
.items_start()
.child(div().max_w_96().child((self.build_content)(window, cx)))
.child(
IconButton::new("close", IconName::Close)
.on_click(cx.listener(|this, _, _, cx| this.dismiss(cx))),
),
v_flex()
.gap_0p5()
.when_some(self.title.clone(), |element, title| {
element.child(Label::new(title))
})
.child(div().max_w_96().child((self.build_content)(window, cx))),
)
.when(self.show_close_button, |this| {
this.child(
IconButton::new("close", IconName::Close)
.on_click(cx.listener(|this, _, _, cx| this.dismiss(cx))),
)
}),
)
.child(
h_flex()
.gap_2()
.gap_1()
.children(self.click_message.iter().map(|message| {
Button::new(message.clone(), message.clone())
.label_size(LabelSize::Small)
@ -489,7 +555,40 @@ pub mod simple_message_notification {
};
this.dismiss(cx)
}))
})),
}))
.child(
h_flex()
.w_full()
.gap_1()
.justify_end()
.children(self.tertiary_click_message.iter().map(|message| {
Button::new(message.clone(), message.clone())
.label_size(LabelSize::Small)
.on_click(cx.listener(|this, _, window, cx| {
if let Some(on_click) = this.tertiary_on_click.as_ref()
{
(on_click)(window, cx)
};
this.dismiss(cx)
}))
}))
.children(
self.more_info_message
.iter()
.zip(self.more_info_url.iter())
.map(|(message, url)| {
let url = url.clone();
Button::new(message.clone(), message.clone())
.label_size(LabelSize::Small)
.icon(IconName::ArrowUpRight)
.icon_size(IconSize::Indicator)
.icon_color(Color::Muted)
.on_click(cx.listener(move |_, _, _, cx| {
cx.open_url(&url);
}))
}),
),
),
)
}
}

View file

@ -58,7 +58,9 @@ use persistence::{
SerializedWindowBounds, DB,
};
use postage::stream::Stream;
use project::{DirectoryLister, Project, ProjectEntryId, ProjectPath, ResolvedPath, Worktree};
use project::{
DirectoryLister, Project, ProjectEntryId, ProjectPath, ResolvedPath, Worktree, WorktreeId,
};
use remote::{ssh_session::ConnectionIdentifier, SshClientDelegate, SshConnectionOptions};
use schemars::JsonSchema;
use serde::Deserialize;
@ -2200,6 +2202,18 @@ impl Workspace {
}
}
pub fn absolute_path_of_worktree(
&self,
worktree_id: WorktreeId,
cx: &mut Context<Self>,
) -> Option<PathBuf> {
self.project
.read(cx)
.worktree_for_id(worktree_id, cx)
// TODO: use `abs_path` or `root_dir`
.map(|wt| wt.read(cx).abs_path().as_ref().to_path_buf())
}
fn add_folder_to_project(
&mut self,
_: &AddFolderToProject,