diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index 3f5d5ef8a2..fb8eb28a61 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -206,6 +206,17 @@ pub enum InlineCompletionProvider { Zed, } +impl InlineCompletionProvider { + pub fn is_zed(&self) -> bool { + match self { + InlineCompletionProvider::Zed => true, + InlineCompletionProvider::None + | InlineCompletionProvider::Copilot + | InlineCompletionProvider::Supermaven => false, + } + } +} + /// The settings for edit predictions, such as [GitHub Copilot](https://github.com/features/copilot) /// or [Supermaven](https://supermaven.com). #[derive(Clone, Debug, Default)] diff --git a/crates/zeta/src/init.rs b/crates/zeta/src/init.rs index 1559250cbc..a45f5a58a2 100644 --- a/crates/zeta/src/init.rs +++ b/crates/zeta/src/init.rs @@ -4,11 +4,16 @@ use command_palette_hooks::CommandPaletteFilter; use feature_flags::{ FeatureFlagAppExt as _, PredictEditsFeatureFlag, PredictEditsRateCompletionsFeatureFlag, }; +use gpui::actions; +use language::language_settings::{AllLanguageSettings, InlineCompletionProvider}; +use settings::update_settings_file; use ui::App; use workspace::Workspace; use crate::{onboarding_modal::ZedPredictModal, RateCompletionModal, RateCompletions}; +actions!(edit_predictions, [ResetOnboarding]); + pub fn init(cx: &mut App) { cx.observe_new(move |workspace: &mut Workspace, _, _cx| { workspace.register_action(|workspace, _: &RateCompletions, window, cx| { @@ -31,6 +36,20 @@ pub fn init(cx: &mut App) { } }, ); + + workspace.register_action(|workspace, _: &ResetOnboarding, _window, cx| { + update_settings_file::( + workspace.app_state().fs.clone(), + cx, + move |file, _| { + file.features + .get_or_insert(Default::default()) + .inline_completion_provider = Some(InlineCompletionProvider::None) + }, + ); + + crate::onboarding_banner::clear_dismissed(cx); + }); }) .detach(); diff --git a/crates/zeta/src/onboarding_banner.rs b/crates/zeta/src/onboarding_banner.rs index 54a6939d62..713b84604a 100644 --- a/crates/zeta/src/onboarding_banner.rs +++ b/crates/zeta/src/onboarding_banner.rs @@ -11,6 +11,7 @@ use crate::onboarding_event; /// Prompts the user to try Zed's Edit Prediction feature pub struct ZedPredictBanner { dismissed: bool, + provider: InlineCompletionProvider, _subscription: Subscription, } @@ -18,40 +19,30 @@ impl ZedPredictBanner { pub fn new(cx: &mut Context) -> Self { Self { dismissed: get_dismissed(), + provider: all_language_settings(None, cx).inline_completions.provider, _subscription: cx.observe_global::(Self::handle_settings_changed), } } fn should_show(&self, cx: &mut App) -> bool { - if !cx.has_flag::() || self.dismissed { - return false; - } - - let provider = all_language_settings(None, cx).inline_completions.provider; - - match provider { - InlineCompletionProvider::None - | InlineCompletionProvider::Copilot - | InlineCompletionProvider::Supermaven => true, - InlineCompletionProvider::Zed => false, - } + cx.has_flag::() && !self.dismissed && !self.provider.is_zed() } fn handle_settings_changed(&mut self, cx: &mut Context) { - if self.dismissed { + let new_provider = all_language_settings(None, cx).inline_completions.provider; + + if new_provider == self.provider { return; } - let provider = all_language_settings(None, cx).inline_completions.provider; - - match provider { - InlineCompletionProvider::None - | InlineCompletionProvider::Copilot - | InlineCompletionProvider::Supermaven => {} - InlineCompletionProvider::Zed => { - self.dismiss(cx); - } + 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) { @@ -64,14 +55,14 @@ impl ZedPredictBanner { const DISMISSED_AT_KEY: &str = "zed_predict_banner_dismissed_at"; -pub(crate) fn get_dismissed() -> bool { +fn get_dismissed() -> bool { db::kvp::KEY_VALUE_STORE .read_kvp(DISMISSED_AT_KEY) .log_err() .map_or(false, |dismissed| dismissed.is_some()) } -pub(crate) fn persist_dismissed(cx: &mut App) { +fn persist_dismissed(cx: &mut App) { cx.spawn(|_| { let time = Utc::now().to_rfc3339(); db::kvp::KEY_VALUE_STORE.write_kvp(DISMISSED_AT_KEY.into(), time) @@ -79,6 +70,11 @@ pub(crate) fn persist_dismissed(cx: &mut App) { .detach_and_log_err(cx); } +pub(crate) fn clear_dismissed(cx: &mut App) { + cx.spawn(|_| db::kvp::KEY_VALUE_STORE.delete_kvp(DISMISSED_AT_KEY.into())) + .detach_and_log_err(cx); +} + impl Render for ZedPredictBanner { fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { if !self.should_show(cx) {