From 926d7b356d585c5631a459dfed103c405b30b9a5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 10 May 2023 10:25:49 -0700 Subject: [PATCH] Define auto_update setting in the auto_update crate --- crates/auto_update/src/auto_update.rs | 29 +++++++++++++++++++++------ crates/settings/src/settings.rs | 10 +-------- crates/settings/src/settings_file.rs | 21 +++++++++++++++++-- crates/settings/src/settings_store.rs | 11 ++++++++++ 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/crates/auto_update/src/auto_update.rs b/crates/auto_update/src/auto_update.rs index 68d3776e1c..2e00a204ba 100644 --- a/crates/auto_update/src/auto_update.rs +++ b/crates/auto_update/src/auto_update.rs @@ -10,7 +10,7 @@ use gpui::{ use isahc::AsyncBody; use serde::Deserialize; use serde_derive::Serialize; -use settings::Settings; +use settings::{Setting, Settings, SettingsStore}; use smol::{fs::File, io::AsyncReadExt, process::Command}; use std::{ffi::OsString, sync::Arc, time::Duration}; use update_notification::UpdateNotification; @@ -58,18 +58,35 @@ impl Entity for AutoUpdater { type Event = (); } +struct AutoUpdateSetting(bool); + +impl Setting for AutoUpdateSetting { + const KEY: Option<&'static str> = Some("auto_update"); + + type FileContent = Option; + + fn load(default_value: &Option, user_values: &[&Option], _: &AppContext) -> Self { + Self( + Self::json_merge(default_value, user_values) + .unwrap() + .unwrap(), + ) + } +} + pub fn init(http_client: Arc, server_url: String, cx: &mut AppContext) { + settings::register_setting::(cx); + if let Some(version) = (*ZED_APP_VERSION).or_else(|| cx.platform().app_version().ok()) { let auto_updater = cx.add_model(|cx| { let updater = AutoUpdater::new(version, http_client, server_url); - let mut update_subscription = cx - .global::() - .auto_update + let mut update_subscription = settings::get_setting::(None, cx) + .0 .then(|| updater.start_polling(cx)); - cx.observe_global::(move |updater, cx| { - if cx.global::().auto_update { + cx.observe_global::(move |updater, cx| { + if settings::get_setting::(None, cx).0 { if update_subscription.is_none() { update_subscription = Some(updater.start_polling(cx)) } diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index 3bc7eb81df..6428e4100d 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -14,7 +14,6 @@ use schemars::{ }; use serde::{Deserialize, Serialize}; use serde_json::Value; -use settings_store::Setting; use sqlez::{ bindable::{Bind, Column, StaticColumnCount}, statement::Statement, @@ -25,7 +24,7 @@ use util::ResultExt as _; pub use keymap_file::{keymap_file_json_schema, KeymapFileContent}; pub use settings_file::*; -pub use settings_store::{SettingsJsonSchemaParams, SettingsStore}; +pub use settings_store::{Setting, SettingsJsonSchemaParams, SettingsStore}; pub const DEFAULT_SETTINGS_ASSET_PATH: &str = "settings/default.json"; pub const INITIAL_USER_SETTINGS_ASSET_PATH: &str = "settings/initial_user_settings.json"; @@ -62,7 +61,6 @@ pub struct Settings { pub theme: Arc, pub telemetry_defaults: TelemetrySettings, pub telemetry_overrides: TelemetrySettings, - pub auto_update: bool, pub base_keymap: BaseKeymap, } @@ -137,7 +135,6 @@ impl Setting for Settings { theme: themes.get(defaults.theme.as_ref().unwrap()).unwrap(), telemetry_defaults: defaults.telemetry, telemetry_overrides: Default::default(), - auto_update: defaults.auto_update.unwrap(), base_keymap: Default::default(), features: Features { copilot: defaults.features.copilot.unwrap(), @@ -576,8 +573,6 @@ pub struct SettingsFileContent { #[serde(default)] pub telemetry: TelemetrySettings, #[serde(default)] - pub auto_update: Option, - #[serde(default)] pub base_keymap: Option, #[serde(default)] pub features: FeaturesContent, @@ -695,7 +690,6 @@ impl Settings { theme: themes.get(&defaults.theme.unwrap()).unwrap(), telemetry_defaults: defaults.telemetry, telemetry_overrides: Default::default(), - auto_update: defaults.auto_update.unwrap(), base_keymap: Default::default(), features: Features { copilot: defaults.features.copilot.unwrap(), @@ -770,7 +764,6 @@ impl Settings { self.language_overrides = data.languages; self.telemetry_overrides = data.telemetry; self.lsp = data.lsp; - merge(&mut self.auto_update, data.auto_update); } pub fn with_language_defaults( @@ -980,7 +973,6 @@ impl Settings { metrics: Some(true), }, telemetry_overrides: Default::default(), - auto_update: true, base_keymap: Default::default(), features: Features { copilot: true }, } diff --git a/crates/settings/src/settings_file.rs b/crates/settings/src/settings_file.rs index 17294235ec..a07560307f 100644 --- a/crates/settings/src/settings_file.rs +++ b/crates/settings/src/settings_file.rs @@ -1,15 +1,32 @@ use crate::{ settings_store::parse_json_with_comments, settings_store::SettingsStore, KeymapFileContent, - Settings, SettingsFileContent, DEFAULT_SETTINGS_ASSET_PATH, + Setting, Settings, SettingsFileContent, DEFAULT_SETTINGS_ASSET_PATH, }; use anyhow::Result; use assets::Assets; use fs::Fs; use futures::{channel::mpsc, StreamExt}; use gpui::{executor::Background, AppContext, AssetSource}; -use std::{borrow::Cow, io::ErrorKind, path::PathBuf, str, sync::Arc, time::Duration}; +use std::{ + borrow::Cow, + io::ErrorKind, + path::{Path, PathBuf}, + str, + sync::Arc, + time::Duration, +}; use util::{paths, ResultExt}; +pub fn register_setting(cx: &mut AppContext) { + cx.update_global::(|store, cx| { + store.register_setting::(cx); + }); +} + +pub fn get_setting<'a, T: Setting>(path: Option<&Path>, cx: &'a AppContext) -> &'a T { + cx.global::().get(path) +} + pub fn default_settings() -> Cow<'static, str> { match Assets.load(DEFAULT_SETTINGS_ASSET_PATH).unwrap() { Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 887b4eef11..38f9d09df0 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -43,6 +43,17 @@ pub trait Setting: 'static { generator.root_schema_for::() } + fn json_merge( + default_value: &Self::FileContent, + user_values: &[&Self::FileContent], + ) -> Result { + let mut merged = serde_json::Value::Null; + for value in [default_value].iter().chain(user_values) { + merge_non_null_json_value_into(serde_json::to_value(value).unwrap(), &mut merged); + } + Ok(serde_json::from_value(merged)?) + } + fn load_via_json_merge( default_value: &Self::FileContent, user_values: &[&Self::FileContent],