Make a single re-usable banner component (#27412)

Release Notes:

- Fixed an issue where both the predict edit and git onboarding banners
would both show at the same time.
This commit is contained in:
Mikayla Maki 2025-03-25 00:05:25 -07:00 committed by GitHub
parent b85492bd00
commit 35ec4753b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 181 additions and 294 deletions

View file

@ -21,7 +21,6 @@ anyhow.workspace = true
askpass.workspace = true
assistant_settings.workspace = true
buffer_diff.workspace = true
chrono.workspace = true
collections.workspace = true
command_palette_hooks.workspace = true
component.workspace = true

View file

@ -9,7 +9,7 @@ use git::{
};
use git_panel_settings::GitPanelSettings;
use gpui::{actions, App, FocusHandle};
use onboarding::{clear_dismissed, GitOnboardingModal};
use onboarding::GitOnboardingModal;
use project_diff::ProjectDiff;
use ui::prelude::*;
use workspace::Workspace;
@ -103,7 +103,7 @@ pub fn init(cx: &mut App) {
},
);
workspace.register_action(move |_, _: &ResetOnboarding, window, cx| {
clear_dismissed(cx);
cx.dispatch_action(&workspace::RestoreBanner);
window.refresh();
});
workspace.register_action(|workspace, _action: &git::Init, window, cx| {

View file

@ -1,9 +1,8 @@
use gpui::{
svg, ClickEvent, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, Global,
MouseDownEvent, Render,
svg, ClickEvent, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, MouseDownEvent,
Render,
};
use ui::{prelude::*, ButtonLike, TintColor, Tooltip};
use util::ResultExt;
use ui::{prelude::*, TintColor};
use workspace::{ModalView, Workspace};
use crate::git_panel::GitPanel;
@ -144,130 +143,3 @@ impl Render for GitOnboardingModal {
)
}
}
/// Prompts the user to try Zed's git features
pub struct GitBanner {
dismissed: bool,
}
#[derive(Clone)]
struct GitBannerGlobal(Entity<GitBanner>);
impl Global for GitBannerGlobal {}
impl GitBanner {
pub fn new(cx: &mut Context<Self>) -> Self {
cx.set_global(GitBannerGlobal(cx.entity()));
Self {
dismissed: get_dismissed(),
}
}
fn should_show(&self, _cx: &mut App) -> bool {
!self.dismissed
}
fn dismiss(&mut self, cx: &mut Context<Self>) {
git_onboarding_event!("Banner Dismissed");
persist_dismissed(cx);
self.dismissed = true;
cx.notify();
}
}
const DISMISSED_AT_KEY: &str = "zed_git_banner_dismissed_at";
fn get_dismissed() -> bool {
db::kvp::KEY_VALUE_STORE
.read_kvp(DISMISSED_AT_KEY)
.log_err()
.map_or(false, |dismissed| dismissed.is_some())
}
fn persist_dismissed(cx: &mut App) {
cx.spawn(async |_| {
let time = chrono::Utc::now().to_rfc3339();
db::kvp::KEY_VALUE_STORE
.write_kvp(DISMISSED_AT_KEY.into(), time)
.await
})
.detach_and_log_err(cx);
}
pub(crate) fn clear_dismissed(cx: &mut App) {
cx.defer(|cx| {
cx.global::<GitBannerGlobal>()
.clone()
.0
.update(cx, |this, cx| {
this.dismissed = false;
cx.notify();
});
});
cx.spawn(async |_| {
db::kvp::KEY_VALUE_STORE
.delete_kvp(DISMISSED_AT_KEY.into())
.await
})
.detach_and_log_err(cx);
}
impl Render for GitBanner {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
if !self.should_show(cx) {
return div();
}
let border_color = cx.theme().colors().editor_foreground.opacity(0.3);
let banner = h_flex()
.rounded_sm()
.border_1()
.border_color(border_color)
.child(
ButtonLike::new("try-git")
.child(
h_flex()
.h_full()
.items_center()
.gap_1()
.child(Icon::new(IconName::GitBranchSmall).size(IconSize::Small))
.child(
h_flex()
.gap_0p5()
.child(
Label::new("Introducing:")
.size(LabelSize::Small)
.color(Color::Muted),
)
.child(Label::new("Git Support").size(LabelSize::Small)),
),
)
.on_click(cx.listener(|this, _, window, cx| {
git_onboarding_event!("Banner Clicked");
this.dismiss(cx);
window.dispatch_action(
Box::new(zed_actions::OpenGitIntegrationOnboarding),
cx,
)
})),
)
.child(
div().border_l_1().border_color(border_color).child(
IconButton::new("close", IconName::Close)
.icon_size(IconSize::Indicator)
.on_click(cx.listener(|this, _, _window, cx| this.dismiss(cx)))
.tooltip(|window, cx| {
Tooltip::with_meta(
"Close Announcement Banner",
None,
"It won't show again for this feature",
window,
cx,
)
}),
),
);
div().pr_2().child(banner)
}
}