fix: preferences were broken
This commit is contained in:
@@ -44,6 +44,7 @@ pub enum Message {
|
|||||||
SetActiveView(SidebarView),
|
SetActiveView(SidebarView),
|
||||||
ToggleSidebar,
|
ToggleSidebar,
|
||||||
TogglePanel,
|
TogglePanel,
|
||||||
|
OpenSettingsSection(crate::views::settings_view::SettingsSection),
|
||||||
|
|
||||||
// Sidebar resize
|
// Sidebar resize
|
||||||
SidebarResizeStart,
|
SidebarResizeStart,
|
||||||
@@ -748,6 +749,19 @@ impl BdsApp {
|
|||||||
self.panel_visible = !self.panel_visible;
|
self.panel_visible = !self.panel_visible;
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
Message::OpenSettingsSection(section) => {
|
||||||
|
self.sidebar_view = SidebarView::Settings;
|
||||||
|
self.sidebar_visible = true;
|
||||||
|
self.open_singleton_tab(TabType::Settings, "common.settings");
|
||||||
|
if self.settings_state.is_none() {
|
||||||
|
self.settings_state = Some(self.hydrate_settings_state());
|
||||||
|
}
|
||||||
|
if let Some(state) = self.settings_state.as_mut() {
|
||||||
|
state.focus_section(section);
|
||||||
|
}
|
||||||
|
self.sync_menu_state();
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
Message::SidebarResizeStart => {
|
Message::SidebarResizeStart => {
|
||||||
self.sidebar_dragging = true;
|
self.sidebar_dragging = true;
|
||||||
Task::none()
|
Task::none()
|
||||||
@@ -3463,16 +3477,7 @@ impl BdsApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SettingsMsg::FocusSection(section) => {
|
SettingsMsg::FocusSection(section) => {
|
||||||
// Expand the target section, collapse all others
|
state.focus_section(section);
|
||||||
use crate::views::settings_view::SettingsSection;
|
|
||||||
let all_others: Vec<SettingsSection> = SettingsSection::all()
|
|
||||||
.iter()
|
|
||||||
.filter(|s| **s != section)
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
state.collapsed = all_others;
|
|
||||||
// Clear search filter to ensure section is visible
|
|
||||||
state.search_query.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Task::none()
|
Task::none()
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ impl SettingsSection {
|
|||||||
pub struct SettingsViewState {
|
pub struct SettingsViewState {
|
||||||
pub search_query: String,
|
pub search_query: String,
|
||||||
pub collapsed: Vec<SettingsSection>,
|
pub collapsed: Vec<SettingsSection>,
|
||||||
|
pub active_section: Option<SettingsSection>,
|
||||||
// Project
|
// Project
|
||||||
pub project_name: String,
|
pub project_name: String,
|
||||||
pub project_description: text_editor::Content,
|
pub project_description: text_editor::Content,
|
||||||
@@ -88,6 +89,7 @@ impl Clone for SettingsViewState {
|
|||||||
Self {
|
Self {
|
||||||
search_query: self.search_query.clone(),
|
search_query: self.search_query.clone(),
|
||||||
collapsed: self.collapsed.clone(),
|
collapsed: self.collapsed.clone(),
|
||||||
|
active_section: self.active_section.clone(),
|
||||||
project_name: self.project_name.clone(),
|
project_name: self.project_name.clone(),
|
||||||
project_description: text_editor::Content::with_text(&self.project_description.text()),
|
project_description: text_editor::Content::with_text(&self.project_description.text()),
|
||||||
data_path: self.data_path.clone(),
|
data_path: self.data_path.clone(),
|
||||||
@@ -113,6 +115,7 @@ impl Default for SettingsViewState {
|
|||||||
Self {
|
Self {
|
||||||
search_query: String::new(),
|
search_query: String::new(),
|
||||||
collapsed: Vec::new(),
|
collapsed: Vec::new(),
|
||||||
|
active_section: None,
|
||||||
project_name: String::new(),
|
project_name: String::new(),
|
||||||
project_description: text_editor::Content::new(),
|
project_description: text_editor::Content::new(),
|
||||||
data_path: String::new(),
|
data_path: String::new(),
|
||||||
@@ -133,6 +136,29 @@ impl Default for SettingsViewState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SettingsViewState {
|
||||||
|
pub fn focus_section(&mut self, section: SettingsSection) {
|
||||||
|
self.collapsed = SettingsSection::all()
|
||||||
|
.iter()
|
||||||
|
.filter(|candidate| **candidate != section)
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
self.search_query.clear();
|
||||||
|
self.active_section = Some(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ordered_sections(&self) -> Vec<SettingsSection> {
|
||||||
|
let mut sections = SettingsSection::all().to_vec();
|
||||||
|
if let Some(active) = &self.active_section {
|
||||||
|
if let Some(index) = sections.iter().position(|section| section == active) {
|
||||||
|
let focused = sections.remove(index);
|
||||||
|
sections.insert(0, focused);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sections
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Settings view messages.
|
/// Settings view messages.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum SettingsMsg {
|
pub enum SettingsMsg {
|
||||||
@@ -190,13 +216,13 @@ pub fn view<'a>(
|
|||||||
let query_lower = state.search_query.to_lowercase();
|
let query_lower = state.search_query.to_lowercase();
|
||||||
|
|
||||||
let mut sections = column![].spacing(12).width(Length::Fill);
|
let mut sections = column![].spacing(12).width(Length::Fill);
|
||||||
for section in SettingsSection::all() {
|
for section in state.ordered_sections() {
|
||||||
let label = t(locale, section.i18n_key());
|
let label = t(locale, section.i18n_key());
|
||||||
if !query_lower.is_empty() && !label.to_lowercase().contains(&query_lower) {
|
if !query_lower.is_empty() && !label.to_lowercase().contains(&query_lower) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let collapsed = state.collapsed.contains(section);
|
let collapsed = state.collapsed.contains(§ion);
|
||||||
let section_el = render_section(state, section, &label, collapsed, locale);
|
let section_el = render_section(state, §ion, &label, collapsed, locale);
|
||||||
sections = sections.push(section_el);
|
sections = sections.push(section_el);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +241,38 @@ pub fn view<'a>(
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::{SettingsSection, SettingsViewState};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn focus_section_collapses_other_sections_and_clears_search() {
|
||||||
|
let mut state = SettingsViewState {
|
||||||
|
search_query: "publish".to_string(),
|
||||||
|
..SettingsViewState::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
state.focus_section(SettingsSection::Publishing);
|
||||||
|
|
||||||
|
assert_eq!(state.active_section, Some(SettingsSection::Publishing));
|
||||||
|
assert!(state.search_query.is_empty());
|
||||||
|
assert!(!state.collapsed.contains(&SettingsSection::Publishing));
|
||||||
|
assert!(state.collapsed.contains(&SettingsSection::Project));
|
||||||
|
assert!(state.collapsed.contains(&SettingsSection::MCP));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn focused_section_is_rendered_first() {
|
||||||
|
let mut state = SettingsViewState::default();
|
||||||
|
state.focus_section(SettingsSection::Technology);
|
||||||
|
|
||||||
|
let ordered = state.ordered_sections();
|
||||||
|
|
||||||
|
assert_eq!(ordered.first(), Some(&SettingsSection::Technology));
|
||||||
|
assert_eq!(ordered.len(), SettingsSection::all().len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn render_section<'a>(
|
fn render_section<'a>(
|
||||||
state: &'a SettingsViewState,
|
state: &'a SettingsViewState,
|
||||||
section: &SettingsSection,
|
section: &SettingsSection,
|
||||||
|
|||||||
@@ -930,7 +930,7 @@ pub fn view(
|
|||||||
}
|
}
|
||||||
SidebarView::Settings => {
|
SidebarView::Settings => {
|
||||||
// Per sidebar_views.allium SettingsNav: 9 fixed-order sections
|
// Per sidebar_views.allium SettingsNav: 9 fixed-order sections
|
||||||
use crate::views::settings_view::{SettingsSection, SettingsMsg};
|
use crate::views::settings_view::SettingsSection;
|
||||||
let sections: &[(&str, Option<SettingsSection>)] = &[
|
let sections: &[(&str, Option<SettingsSection>)] = &[
|
||||||
("settings.nav.project", Some(SettingsSection::Project)),
|
("settings.nav.project", Some(SettingsSection::Project)),
|
||||||
("settings.nav.editor", Some(SettingsSection::Editor)),
|
("settings.nav.editor", Some(SettingsSection::Editor)),
|
||||||
@@ -950,12 +950,12 @@ pub fn view(
|
|||||||
.size(12)
|
.size(12)
|
||||||
.shaping(Shaping::Advanced);
|
.shaping(Shaping::Advanced);
|
||||||
let msg = if let Some(section) = section_opt {
|
let msg = if let Some(section) = section_opt {
|
||||||
Message::Settings(SettingsMsg::FocusSection(section.clone()))
|
Message::OpenSettingsSection(section.clone())
|
||||||
} else {
|
} else {
|
||||||
Message::OpenTab(Tab {
|
Message::OpenTab(Tab {
|
||||||
id: "settings".to_string(),
|
id: "style".to_string(),
|
||||||
tab_type: TabType::Settings,
|
tab_type: TabType::Style,
|
||||||
title: t(locale, "common.settings"),
|
title: t(locale, "tabBar.style"),
|
||||||
is_transient: false,
|
is_transient: false,
|
||||||
is_dirty: false,
|
is_dirty: false,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user