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:
parent
b85492bd00
commit
35ec4753b4
14 changed files with 181 additions and 294 deletions
|
@ -19,7 +19,6 @@ test-support = []
|
|||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
arrayvec.workspace = true
|
||||
chrono.workspace = true
|
||||
client.workspace = true
|
||||
collections.workspace = true
|
||||
command_palette_hooks.workspace = true
|
||||
|
|
|
@ -43,8 +43,6 @@ pub fn init(cx: &mut App) {
|
|||
.edit_prediction_provider = Some(EditPredictionProvider::None)
|
||||
},
|
||||
);
|
||||
|
||||
crate::onboarding_banner::clear_dismissed(cx);
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
use chrono::Utc;
|
||||
use feature_flags::{FeatureFlagAppExt as _, PredictEditsFeatureFlag};
|
||||
use gpui::Subscription;
|
||||
use language::language_settings::{all_language_settings, EditPredictionProvider};
|
||||
use settings::SettingsStore;
|
||||
use ui::{prelude::*, ButtonLike, Tooltip};
|
||||
use util::ResultExt;
|
||||
|
||||
use crate::onboarding_event;
|
||||
|
||||
/// Prompts the user to try Zed's Edit Prediction feature
|
||||
pub struct ZedPredictBanner {
|
||||
dismissed: bool,
|
||||
provider: EditPredictionProvider,
|
||||
_subscription: Subscription,
|
||||
}
|
||||
|
||||
impl ZedPredictBanner {
|
||||
pub fn new(cx: &mut Context<Self>) -> Self {
|
||||
Self {
|
||||
dismissed: get_dismissed(),
|
||||
provider: all_language_settings(None, cx).edit_predictions.provider,
|
||||
_subscription: cx.observe_global::<SettingsStore>(Self::handle_settings_changed),
|
||||
}
|
||||
}
|
||||
|
||||
fn should_show(&self, cx: &mut App) -> bool {
|
||||
cx.has_flag::<PredictEditsFeatureFlag>() && !self.dismissed && !self.provider.is_zed()
|
||||
}
|
||||
|
||||
fn handle_settings_changed(&mut self, cx: &mut Context<Self>) {
|
||||
let new_provider = all_language_settings(None, cx).edit_predictions.provider;
|
||||
|
||||
if new_provider == self.provider {
|
||||
return;
|
||||
}
|
||||
|
||||
if new_provider.is_zed() {
|
||||
self.dismiss(cx);
|
||||
} else {
|
||||
self.dismissed = get_dismissed();
|
||||
}
|
||||
|
||||
self.provider = new_provider;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn dismiss(&mut self, cx: &mut Context<Self>) {
|
||||
onboarding_event!("Banner Dismissed");
|
||||
persist_dismissed(cx);
|
||||
self.dismissed = true;
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
|
||||
const DISMISSED_AT_KEY: &str = "zed_predict_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 = 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.spawn(async |_| {
|
||||
db::kvp::KEY_VALUE_STORE
|
||||
.delete_kvp(DISMISSED_AT_KEY.into())
|
||||
.await
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
impl Render for ZedPredictBanner {
|
||||
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-zed-predict")
|
||||
.child(
|
||||
h_flex()
|
||||
.h_full()
|
||||
.items_center()
|
||||
.gap_1p5()
|
||||
.child(Icon::new(IconName::ZedPredict).size(IconSize::Small))
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
Label::new("Introducing:")
|
||||
.size(LabelSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.child(Label::new("Edit Prediction").size(LabelSize::Small)),
|
||||
),
|
||||
)
|
||||
.on_click(|_, window, cx| {
|
||||
onboarding_event!("Banner Clicked");
|
||||
window.dispatch_action(Box::new(zed_actions::OpenZedPredictOnboarding), 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)
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ mod completion_diff_element;
|
|||
mod init;
|
||||
mod input_excerpt;
|
||||
mod license_detection;
|
||||
mod onboarding_banner;
|
||||
mod onboarding_modal;
|
||||
mod onboarding_telemetry;
|
||||
mod rate_completion_modal;
|
||||
|
@ -13,7 +12,6 @@ pub use init::*;
|
|||
use inline_completion::DataCollectionState;
|
||||
pub use license_detection::is_license_eligible_for_data_collection;
|
||||
use license_detection::LICENSE_FILES_TO_CHECK;
|
||||
pub use onboarding_banner::*;
|
||||
pub use rate_completion_modal::*;
|
||||
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue