From d5adca389554c5235a97d890ac6dbc98b5457881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Houl=C3=A9?= Date: Tue, 26 May 2026 14:11:41 +0200 Subject: [PATCH] settings: Show warning that your organization can override some settings --- crates/settings_ui/src/page_data.rs | 15 ++++++ crates/settings_ui/src/settings_ui.rs | 68 ++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/crates/settings_ui/src/page_data.rs b/crates/settings_ui/src/page_data.rs index 1a38337fb49..3e0497bea72 100644 --- a/crates/settings_ui/src/page_data.rs +++ b/crates/settings_ui/src/page_data.rs @@ -128,6 +128,7 @@ fn developer_page(cx: &App) -> SettingsPage { SettingsPage { title: "Developer", + is_overridable_by_organization_settings: false, items: items.into_boxed_slice(), } } @@ -418,6 +419,7 @@ fn general_page(cx: &App) -> SettingsPage { SettingsPage { title: "General", + is_overridable_by_organization_settings: true, items: concat_sections!( @vec, general_settings_section(cx), @@ -1303,6 +1305,7 @@ fn appearance_page() -> SettingsPage { SettingsPage { title: "Appearance", + is_overridable_by_organization_settings: false, items, } } @@ -1391,6 +1394,7 @@ fn keymap_page() -> SettingsPage { SettingsPage { title: "Keymap", + is_overridable_by_organization_settings: false, items, } } @@ -2867,6 +2871,7 @@ fn editor_page() -> SettingsPage { SettingsPage { title: "Editor", + is_overridable_by_organization_settings: false, items: items, } } @@ -3163,6 +3168,7 @@ fn languages_and_tools_page(cx: &App) -> SettingsPage { SettingsPage { title: "Languages & Tools", + is_overridable_by_organization_settings: false, items: { concat_sections!( non_editor_language_settings_data(), @@ -3506,6 +3512,7 @@ fn search_and_files_page() -> SettingsPage { SettingsPage { title: "Search & Files", + is_overridable_by_organization_settings: false, items: concat_sections![search_section(), file_finder_section(), file_scan_section()], } } @@ -4608,6 +4615,7 @@ fn window_and_layout_page() -> SettingsPage { SettingsPage { title: "Window & Layout", + is_overridable_by_organization_settings: false, items: concat_sections![ status_bar_section(), title_bar_section(), @@ -5992,6 +6000,7 @@ fn panels_page() -> SettingsPage { SettingsPage { title: "Panels", + is_overridable_by_organization_settings: false, items: concat_sections![ project_panel_section(), terminal_panel_section(), @@ -6114,6 +6123,7 @@ fn debugger_page() -> SettingsPage { SettingsPage { title: "Debugger", + is_overridable_by_organization_settings: false, items: concat_sections![general_section()], } } @@ -6932,6 +6942,7 @@ fn terminal_page() -> SettingsPage { SettingsPage { title: "Terminal", + is_overridable_by_organization_settings: false, items: concat_sections![ environment_section(), font_section(), @@ -7338,6 +7349,7 @@ fn version_control_page() -> SettingsPage { SettingsPage { title: "Version Control", + is_overridable_by_organization_settings: false, items: concat_sections![ git_integration_section(), git_gutter_section(), @@ -7446,6 +7458,7 @@ fn collaboration_page() -> SettingsPage { SettingsPage { title: "Collaboration", + is_overridable_by_organization_settings: true, items: concat_sections![calls_section(), audio_settings()], } } @@ -7808,6 +7821,7 @@ fn ai_page(cx: &App) -> SettingsPage { SettingsPage { title: "AI", + is_overridable_by_organization_settings: true, items: concat_sections![ general_section(), agent_configuration_section(cx), @@ -7859,6 +7873,7 @@ fn network_page() -> SettingsPage { SettingsPage { title: "Network", + is_overridable_by_organization_settings: false, items: concat_sections![network_section()], } } diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index eae0e60166e..d4323fc69b2 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -842,6 +842,8 @@ struct NavBarEntry { struct SettingsPage { title: &'static str, + /// Are some of the settings on this page susceptible to being overridden by organization settings? (Zed for Business) + is_overridable_by_organization_settings: bool, items: Box<[SettingsPageItem]>, } @@ -1595,6 +1597,11 @@ impl SettingsWindow { .filter_map(|weak| weak.upgrade()) .collect(); + // Re-render when the current organization changes, so the org-override + // banner appears/disappears on sign in/out and org switches. + cx.observe(&app_state.user_store, |_, _, cx| cx.notify()) + .detach(); + for workspace in workspaces { let project = workspace.read(cx).project().clone(); cx.observe_release_in(&project, window, |this, _, window, cx| { @@ -2136,7 +2143,7 @@ impl SettingsWindow { }); push_candidates(&mut fuzzy_match_candidates, key_index, header); header_index = item_index; - header_str = *header; + header_str = header; } SettingsPageItem::SubPageLink(sub_page_link) => { json_path = sub_page_link.json_path; @@ -3266,6 +3273,58 @@ impl SettingsWindow { } } + /// Banner warning that the user's organization may override settings on + /// this page. Shown on the screens that hold data and privacy controls: + /// General (telemetry), AI (Zed model provider, agent feedback, edit + /// predictions), and Collaboration. + /// + /// Suppressed when there's a settings parse/migration error for the + /// current file, so the more urgent outdated-settings banner takes + /// precedence (per the ticket's edge-case preference). + fn render_org_override_banner(&self, cx: &App) -> AnyElement { + let on_overridable_page = matches!( + self.current_file, + SettingsUiFile::User | SettingsUiFile::Project(_) + ) && self.current_page().is_overridable_by_organization_settings; + + if !on_overridable_page { + return gpui::Empty.into_any_element(); + } + + let has_settings_error = SettingsStore::global(cx) + .error_for_file(self.current_file.to_settings()) + .is_some(); + if has_settings_error { + return gpui::Empty.into_any_element(); + } + + let in_business_org = AppState::global(cx) + .user_store + .read(cx) + .current_organization() + .is_some_and(|org| !org.is_personal); + if !in_business_org { + return gpui::Empty.into_any_element(); + } + + Banner::new() + .severity(Severity::Warning) + .child( + v_flex() + .my_0p5() + .gap_0p5() + .child(Label::new("Organization Settings")) + .child( + Label::new( + "Your organization's data and privacy settings may override your changes here.", + ) + .size(LabelSize::Small) + .color(Color::Muted), + ), + ) + .into_any_element() + } + fn render_page( &mut self, window: &mut Window, @@ -3454,6 +3513,8 @@ impl SettingsWindow { } } + let org_override_banner = self.render_org_override_banner(cx); + v_flex() .id("settings-ui-page") .on_action(cx.listener(|this, _: &menu::SelectNext, window, cx| { @@ -3545,7 +3606,8 @@ impl SettingsWindow { .gap_2() .child(page_header) .child(warning_banner) - .child(restricted_banner), + .child(restricted_banner) + .child(org_override_banner), ) .child( div() @@ -4544,6 +4606,7 @@ pub mod test { let search_bar = cx.new(|cx| Editor::single_line(window, cx)); let dummy_page = SettingsPage { title: "Test", + is_overridable_by_organization_settings: false, items: Box::new([]), }; Self { @@ -4670,6 +4733,7 @@ pub mod test { .into_iter() .map(|builder| SettingsPage { title: builder.title, + is_overridable_by_organization_settings: false, items: builder.items.into_boxed_slice(), }) .collect();