workspace: Hide "View AI Settings" when AI is disabled (#50941)

Om Chillure created

Fixes #50835

### Problem :
The "View AI Settings" button on the Welcome page was always rendered
regardless of the disable_ai setting. This made it visible (and
non-functional) for users who had AI disabled, which was confusing.

### Fix :
- Adds an optional visibility: Option<fn(&App) -> bool> predicate field
to SectionEntry
- At render time, Section::render uses filter_map to skip entries whose
predicate returns false.
- The "View AI Settings" entry is given a predicate that checks
!DisableAiSettings::get_global(cx).disable_ai, matching the same pattern
used in `title_bar.rs` and `quick_action_bar.rs`.
- All other entries have visibility: None, meaning they are always shown
— no behaviour change for them.

### Video :
[Screencast from 2026-03-06
20-18-43.webm](https://github.com/user-attachments/assets/cbfab423-3ef3-41dd-a9ab-cbae055eef6e)


Release Notes:

- Fixed the "View AI Settings" button being visible on the Welcome page
despite AI features being disabled in settings.

Change summary

crates/workspace/src/welcome.rs | 51 ++++++++++++++++++++++++++++------
1 file changed, 42 insertions(+), 9 deletions(-)

Detailed changes

crates/workspace/src/welcome.rs 🔗

@@ -10,8 +10,10 @@ use gpui::{
     ParentElement, Render, Styled, Task, Window, actions,
 };
 use menu::{SelectNext, SelectPrevious};
+use project::DisableAiSettings;
 use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
+use settings::Settings;
 use ui::{ButtonLike, Divider, DividerColor, KeyBinding, Vector, VectorName, prelude::*};
 use util::ResultExt;
 use zed_actions::{Extensions, OpenOnboarding, OpenSettings, agent, command_palette};
@@ -121,21 +123,43 @@ impl RenderOnce for SectionButton {
     }
 }
 
+enum SectionVisibility {
+    Always,
+    Conditional(fn(&App) -> bool),
+}
+
+impl SectionVisibility {
+    fn is_visible(&self, cx: &App) -> bool {
+        match self {
+            SectionVisibility::Always => true,
+            SectionVisibility::Conditional(f) => f(cx),
+        }
+    }
+}
+
 struct SectionEntry {
     icon: IconName,
     title: &'static str,
     action: &'static dyn Action,
+    visibility_guard: SectionVisibility,
 }
 
 impl SectionEntry {
-    fn render(&self, button_index: usize, focus: &FocusHandle, _cx: &App) -> impl IntoElement {
-        SectionButton::new(
-            self.title,
-            self.icon,
-            self.action,
-            button_index,
-            focus.clone(),
-        )
+    fn render(
+        &self,
+        button_index: usize,
+        focus: &FocusHandle,
+        cx: &App,
+    ) -> Option<impl IntoElement> {
+        self.visibility_guard.is_visible(cx).then(|| {
+            SectionButton::new(
+                self.title,
+                self.icon,
+                self.action,
+                button_index,
+                focus.clone(),
+            )
+        })
     }
 }
 
@@ -147,21 +171,25 @@ const CONTENT: (Section<4>, Section<3>) = (
                 icon: IconName::Plus,
                 title: "New File",
                 action: &NewFile,
+                visibility_guard: SectionVisibility::Always,
             },
             SectionEntry {
                 icon: IconName::FolderOpen,
                 title: "Open Project",
                 action: &Open::DEFAULT,
+                visibility_guard: SectionVisibility::Always,
             },
             SectionEntry {
                 icon: IconName::CloudDownload,
                 title: "Clone Repository",
                 action: &GitClone,
+                visibility_guard: SectionVisibility::Always,
             },
             SectionEntry {
                 icon: IconName::ListCollapse,
                 title: "Open Command Palette",
                 action: &command_palette::Toggle,
+                visibility_guard: SectionVisibility::Always,
             },
         ],
     },
@@ -172,11 +200,15 @@ const CONTENT: (Section<4>, Section<3>) = (
                 icon: IconName::Settings,
                 title: "Open Settings",
                 action: &OpenSettings,
+                visibility_guard: SectionVisibility::Always,
             },
             SectionEntry {
                 icon: IconName::ZedAssistant,
                 title: "View AI Settings",
                 action: &agent::OpenSettings,
+                visibility_guard: SectionVisibility::Conditional(|cx| {
+                    !DisableAiSettings::get_global(cx).disable_ai
+                }),
             },
             SectionEntry {
                 icon: IconName::Blocks,
@@ -185,6 +217,7 @@ const CONTENT: (Section<4>, Section<3>) = (
                     category_filter: None,
                     id: None,
                 },
+                visibility_guard: SectionVisibility::Always,
             },
         ],
     },
@@ -204,7 +237,7 @@ impl<const COLS: usize> Section<COLS> {
                 self.entries
                     .iter()
                     .enumerate()
-                    .map(|(index, entry)| entry.render(index_offset + index, focus, cx)),
+                    .filter_map(|(index, entry)| entry.render(index_offset + index, focus, cx)),
             )
     }
 }