Cargo.lock 🔗
@@ -14363,7 +14363,6 @@ dependencies = [
"anyhow",
"assets",
"client",
- "command_palette_hooks",
"editor",
"feature_flags",
"fs",
Mikayla Maki created
And remove the feature flag for now.
Release Notes:
- N/A
Cargo.lock | 1
crates/gpui/src/platform.rs | 5
crates/settings_ui/Cargo.toml | 1
crates/settings_ui/src/settings_ui.rs | 193 +++++++++++------------
crates/ui/src/components/tree_view_item.rs | 23 -
5 files changed, 106 insertions(+), 117 deletions(-)
@@ -14363,7 +14363,6 @@ dependencies = [
"anyhow",
"assets",
"client",
- "command_palette_hooks",
"editor",
"feature_flags",
"fs",
@@ -1213,6 +1213,11 @@ impl WindowBounds {
WindowBounds::Fullscreen(bounds) => *bounds,
}
}
+
+ /// Creates a new window bounds that centers the window on the screen.
+ pub fn centered(size: Size<Pixels>, cx: &App) -> Self {
+ WindowBounds::Windowed(Bounds::centered(None, size, cx))
+ }
}
impl Default for WindowOptions {
@@ -17,7 +17,6 @@ test-support = []
[dependencies]
anyhow.workspace = true
-command_palette_hooks.workspace = true
heck.workspace = true
editor.workspace = true
feature_flags.workspace = true
@@ -4,12 +4,12 @@ mod page_data;
use anyhow::Result;
use editor::{Editor, EditorEvent};
-use feature_flags::{FeatureFlag, FeatureFlagAppExt as _};
+use feature_flags::FeatureFlag;
use fuzzy::StringMatchCandidate;
use gpui::{
Action, App, Div, Entity, FocusHandle, Focusable, FontWeight, Global, ReadGlobal as _,
- ScrollHandle, Task, TitlebarOptions, UniformListScrollHandle, Window, WindowHandle,
- WindowOptions, actions, div, point, prelude::*, px, size, uniform_list,
+ ScrollHandle, Task, TitlebarOptions, UniformListScrollHandle, Window, WindowBounds,
+ WindowHandle, WindowOptions, actions, div, point, prelude::*, px, size, uniform_list,
};
use heck::ToTitleCase as _;
use project::WorktreeId;
@@ -29,9 +29,8 @@ use std::{
sync::{Arc, LazyLock, RwLock, atomic::AtomicBool},
};
use ui::{
- ContextMenu, Divider, DividerColor, DropdownMenu, DropdownStyle, IconButtonShape, KeyBinding,
- KeybindingHint, PopoverMenu, Switch, SwitchColor, Tooltip, TreeViewItem, WithScrollbar,
- prelude::*,
+ ContextMenu, Divider, DividerColor, DropdownMenu, DropdownStyle, IconButtonShape, PopoverMenu,
+ Switch, SwitchColor, Tooltip, TreeViewItem, WithScrollbar, prelude::*,
};
use ui_input::{NumberField, NumberFieldType};
use util::{ResultExt as _, paths::PathStyle, rel_path::RelPath};
@@ -42,8 +41,12 @@ use crate::components::SettingsEditor;
const NAVBAR_CONTAINER_TAB_INDEX: isize = 0;
const NAVBAR_GROUP_TAB_INDEX: isize = 1;
-const CONTENT_CONTAINER_TAB_INDEX: isize = 2;
-const CONTENT_GROUP_TAB_INDEX: isize = 3;
+
+const HEADER_CONTAINER_TAB_INDEX: isize = 2;
+const HEADER_GROUP_TAB_INDEX: isize = 3;
+
+const CONTENT_CONTAINER_TAB_INDEX: isize = 4;
+const CONTENT_GROUP_TAB_INDEX: isize = 5;
actions!(
settings_editor,
@@ -206,35 +209,12 @@ pub fn init(cx: &mut App) {
init_renderers(cx);
cx.observe_new(|workspace: &mut workspace::Workspace, _, _| {
- workspace.register_action_renderer(|div, _, _, cx| {
- let settings_ui_actions = [
- TypeId::of::<OpenSettingsEditor>(),
- TypeId::of::<ToggleFocusNav>(),
- TypeId::of::<FocusFile>(),
- TypeId::of::<FocusNextFile>(),
- TypeId::of::<FocusPreviousFile>(),
- ];
- let has_flag = cx.has_flag::<SettingsUiFeatureFlag>();
- command_palette_hooks::CommandPaletteFilter::update_global(cx, |filter, _| {
- if has_flag {
- filter.show_action_types(&settings_ui_actions);
- } else {
- filter.hide_action_types(&settings_ui_actions);
- }
- });
- if has_flag {
- div.on_action(
- cx.listener(|workspace, _: &OpenSettingsEditor, window, cx| {
- let window_handle = window
- .window_handle()
- .downcast::<Workspace>()
- .expect("Workspaces are root Windows");
- open_settings_editor(workspace, window_handle, cx);
- }),
- )
- } else {
- div
- }
+ workspace.register_action(|workspace, _: &OpenSettingsEditor, window, cx| {
+ let window_handle = window
+ .window_handle()
+ .downcast::<Workspace>()
+ .expect("Workspaces are root Windows");
+ open_settings_editor(workspace, window_handle, cx);
});
})
.detach();
@@ -472,7 +452,8 @@ pub fn open_settings_editor(
show: true,
kind: gpui::WindowKind::Normal,
window_background: cx.theme().window_background_appearance(),
- window_min_size: Some(size(px(800.), px(600.))), // 4:3 Aspect Ratio
+ window_min_size: Some(size(px(900.), px(750.))), // 4:3 Aspect Ratio
+ window_bounds: Some(WindowBounds::centered(size(px(900.), px(750.)), cx)),
..Default::default()
},
|window, cx| cx.new(|cx| SettingsWindow::new(Some(workspace_handle), window, cx)),
@@ -886,7 +867,10 @@ impl SettingsWindow {
.focus_handle()
.tab_index(CONTENT_CONTAINER_TAB_INDEX)
.tab_stop(false),
- files_focus_handle: cx.focus_handle().tab_stop(false),
+ files_focus_handle: cx
+ .focus_handle()
+ .tab_index(HEADER_CONTAINER_TAB_INDEX)
+ .tab_stop(false),
};
this.fetch_files(cx);
@@ -1206,7 +1190,7 @@ impl SettingsWindow {
.find_map(|(prev_file, handle)| {
(prev_file == &settings_ui_file).then(|| handle.clone())
})
- .unwrap_or_else(|| cx.focus_handle());
+ .unwrap_or_else(|| cx.focus_handle().tab_index(0).tab_stop(true));
ui_files.push((settings_ui_file, focus_handle));
}
ui_files.reverse();
@@ -1223,14 +1207,22 @@ impl SettingsWindow {
fn change_file(&mut self, ix: usize, cx: &mut Context<SettingsWindow>) {
if ix >= self.files.len() {
self.current_file = SettingsUiFile::User;
+ self.build_ui(cx);
return;
}
if self.files[ix].0 == self.current_file {
return;
}
self.current_file = self.files[ix].0.clone();
- // self.navbar_entry = 0;
+ self.navbar_entry = 0;
self.build_ui(cx);
+
+ let first_navbar_entry_index = self
+ .visible_navbar_entries()
+ .next()
+ .map(|e| e.0)
+ .unwrap_or(0);
+ self.navbar_entry = first_navbar_entry_index;
}
fn render_files_header(
@@ -1242,6 +1234,9 @@ impl SettingsWindow {
.w_full()
.gap_1()
.justify_between()
+ .tab_group()
+ .track_focus(&self.files_focus_handle)
+ .tab_index(HEADER_GROUP_TAB_INDEX)
.child(
h_flex()
.id("file_buttons_container")
@@ -1261,26 +1256,23 @@ impl SettingsWindow {
.toggle_state(file == &self.current_file)
.selected_style(ButtonStyle::Tinted(ui::TintColor::Accent))
.track_focus(focus_handle)
- .on_click(cx.listener(
- move |this, evt: &gpui::ClickEvent, window, cx| {
+ .on_click(cx.listener({
+ let focus_handle = focus_handle.clone();
+ move |this, _: &gpui::ClickEvent, window, cx| {
this.change_file(ix, cx);
- if evt.is_keyboard() {
- this.focus_first_nav_item(window, cx);
- }
- },
- ))
+ focus_handle.focus(window);
+ }
+ }))
}),
),
)
.child(
- Button::new(
- "edit-in-json",
- format!("Edit in {}", self.file_location_str()),
- )
- .style(ButtonStyle::Outlined)
- .on_click(cx.listener(|this, _, _, cx| {
- this.open_current_settings_file(cx);
- })),
+ Button::new("edit-in-json", "Edit in settings.json")
+ .tab_index(0_isize)
+ .style(ButtonStyle::Outlined)
+ .on_click(cx.listener(|this, _, _, cx| {
+ this.open_current_settings_file(cx);
+ })),
)
}
@@ -1307,26 +1299,28 @@ impl SettingsWindow {
}
}
- fn file_location_str(&self) -> String {
- match &self.current_file {
- SettingsUiFile::User => "settings.json".to_string(),
- SettingsUiFile::Project((worktree_id, path)) => self
- .worktree_root_dirs
- .get(&worktree_id)
- .map(|directory_name| {
- let path_style = PathStyle::local();
- let file_path = path.join(paths::local_settings_file_relative_path());
- format!(
- "{}{}{}",
- directory_name,
- path_style.separator(),
- file_path.display(path_style)
- )
- })
- .expect("Current file should always be present in root dir map"),
- SettingsUiFile::Server(file) => file.to_string(),
- }
- }
+ // TODO:
+ // Reconsider this after preview launch
+ // fn file_location_str(&self) -> String {
+ // match &self.current_file {
+ // SettingsUiFile::User => "settings.json".to_string(),
+ // SettingsUiFile::Project((worktree_id, path)) => self
+ // .worktree_root_dirs
+ // .get(&worktree_id)
+ // .map(|directory_name| {
+ // let path_style = PathStyle::local();
+ // let file_path = path.join(paths::local_settings_file_relative_path());
+ // format!(
+ // "{}{}{}",
+ // directory_name,
+ // path_style.separator(),
+ // file_path.display(path_style)
+ // )
+ // })
+ // .expect("Current file should always be present in root dir map"),
+ // SettingsUiFile::Server(file) => file.to_string(),
+ // }
+ // }
fn render_search(&self, _window: &mut Window, cx: &mut App) -> Div {
h_flex()
@@ -1349,11 +1343,11 @@ impl SettingsWindow {
) -> impl IntoElement {
let visible_count = self.visible_navbar_entries().count();
- let focus_keybind_label = if self.navbar_focus_handle.contains_focused(window, cx) {
- "Focus Content"
- } else {
- "Focus Navbar"
- };
+ // let focus_keybind_label = if self.navbar_focus_handle.contains_focused(window, cx) {
+ // "Focus Content"
+ // } else {
+ // "Focus Navbar"
+ // };
v_flex()
.w_64()
@@ -1437,24 +1431,25 @@ impl SettingsWindow {
)
.vertical_scrollbar_for(self.list_handle.clone(), window, cx),
)
- .child(
- h_flex()
- .w_full()
- .p_2()
- .pb_0p5()
- .flex_none()
- .border_t_1()
- .border_color(cx.theme().colors().border_variant)
- .children(
- KeyBinding::for_action(&ToggleFocusNav, window, cx).map(|this| {
- KeybindingHint::new(
- this,
- cx.theme().colors().surface_background.opacity(0.5),
- )
- .suffix(focus_keybind_label)
- }),
- ),
- )
+ // TODO: Restore this once we've fixed the ToggleFocusNav action
+ // .child(
+ // h_flex()
+ // .w_full()
+ // .p_2()
+ // .pb_0p5()
+ // .flex_none()
+ // .border_t_1()
+ // .border_color(cx.theme().colors().border_variant)
+ // .children(
+ // KeyBinding::for_action(&ToggleFocusNav, window, cx).map(|this| {
+ // KeybindingHint::new(
+ // this,
+ // cx.theme().colors().surface_background.opacity(0.5),
+ // )
+ // .suffix(focus_keybind_label)
+ // }),
+ // ),
+ // )
}
fn focus_first_nav_item(&self, window: &mut Window, cx: &mut Context<Self>) {
@@ -129,7 +129,6 @@ impl RenderOnce for TreeViewItem {
let selected_border = cx.theme().colors().border.opacity(0.6);
let focused_border = cx.theme().colors().border_focused;
- let transparent_border = cx.theme().colors().border_transparent;
let item_size = rems_from_px(28.);
let indentation_line = h_flex().size(item_size).flex_none().justify_center().child(
@@ -150,6 +149,13 @@ impl RenderOnce for TreeViewItem {
.cursor_pointer()
.size_full()
.relative()
+ .border_1()
+ .focus(|s| s.border_color(focused_border))
+ .when_some(self.tab_index, |this, index| this.tab_index(index))
+ .when(self.selected, |this| {
+ this.border_color(selected_border).bg(selected_bg)
+ })
+ .hover(|s| s.bg(cx.theme().colors().element_hover))
.map(|this| {
let label = self.label;
@@ -158,14 +164,6 @@ impl RenderOnce for TreeViewItem {
.px_1()
.gap_2p5()
.rounded_sm()
- .border_1()
- .border_color(transparent_border)
- .when(self.selected, |this| {
- this.border_color(selected_border).bg(selected_bg)
- })
- .focus(|s| s.border_color(focused_border))
- .hover(|s| s.bg(cx.theme().colors().element_hover))
- .when_some(self.tab_index, |this, index| this.tab_index(index))
.child(
Disclosure::new("toggle", self.expanded)
.when_some(
@@ -189,14 +187,7 @@ impl RenderOnce for TreeViewItem {
.flex_grow()
.px_1()
.rounded_sm()
- .border_1()
- .border_color(transparent_border)
- .when(self.selected, |this| {
- this.border_color(selected_border).bg(selected_bg)
- })
- .focus(|s| s.border_color(focused_border))
.hover(|s| s.bg(cx.theme().colors().element_hover))
- .when_some(self.tab_index, |this, index| this.tab_index(index))
.child(
Label::new(label)
.when(!self.selected, |this| this.color(Color::Muted)),