From 45f68422eda71f31b4b89e1bc7a696a656e45d9e Mon Sep 17 00:00:00 2001 From: Chili Palmer Date: Sat, 1 Aug 2026 10:22:27 +0200 Subject: [PATCH] Open Preferences as a complete settings workspace. --- README.md | 2 +- crates/bds-ui/src/app.rs | 26 ++++++++++++++++++++++++++ specs/tabs.allium | 9 +++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 269135f..bb624c2 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The project is under active development. Core blogging workflows are broadly ava ## Available Features -- Native Iced desktop workspace with localized menus, tabs, anchored editor popovers, automatically paged post/media sidebars with locale-aware post dates, calendar months, and relative-dated entity lists, row deletion, dialogs, embedded Wry previews, a live Pico CSS theme editor, and per-project restart restoration of the active activity, shell visibility, and open editor tabs. Its shared task UI keeps queued work off blocking workers, shows every active local or remote task plus recent history, and supports cooperative cancellation without oversubscribing background work. +- Native Iced desktop workspace with localized menus, tabs, anchored editor popovers, automatically paged post/media sidebars with locale-aware post dates, calendar months, and relative-dated entity lists, row deletion, dialogs, embedded Wry previews, a live Pico CSS theme editor, direct Preferences navigation, and per-project restart restoration of the active activity, shell visibility, and open editor tabs. Its shared task UI keeps queued work off blocking workers, shows every active local or remote task plus recent history, and supports cooperative cancellation without oversubscribing background work. - Post and translation authoring with change-aware draft/published/archive lifecycle, file-backed change discard, canonical draft reopening after manual translation edits, non-disruptive automatic translation, desktop archive/unarchive actions, in-place published-frontmatter updates, metadata, tags, categories, live link/backlink graphs, media, and batch gallery-image import. - Media import including HEIC/HEIF decoding, q80 WebP thumbnails (plus q85 AI JPEGs), metadata translations, filters, validation, post assignment, and sequential drag-and-drop insertion into post editors. - WordPress WXR migration with saved analyses, HTML-to-Markdown and shortcode conversion, conflict/taxonomy review, recoverable 500-item execution batches, media-parent linking, progress reporting, and optional AI-assisted taxonomy mapping. diff --git a/crates/bds-ui/src/app.rs b/crates/bds-ui/src/app.rs index 8b9b591..7a9b816 100644 --- a/crates/bds-ui/src/app.rs +++ b/crates/bds-ui/src/app.rs @@ -4589,7 +4589,13 @@ impl BdsApp { Task::none() } MenuAction::EditPreferences => { + 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()); + } + self.sync_menu_state(); Task::none() } // View @@ -10747,6 +10753,26 @@ mod tests { )); } + #[test] + fn preferences_menu_opens_the_hydrated_settings_workspace() { + let (db, project, temp) = setup(); + let mut app = BdsApp::new_for_tests(db, project, temp.path().to_path_buf()); + app.sidebar_view = SidebarView::Posts; + app.sidebar_visible = false; + + let _ = app.dispatch_menu_action(MenuAction::EditPreferences); + + assert_eq!(app.sidebar_view, SidebarView::Settings); + assert!(app.sidebar_visible); + assert_eq!(app.active_tab_type(), Some(TabType::Settings)); + assert_eq!( + app.settings_state + .as_ref() + .map(|state| state.project_name.as_str()), + Some("Test Project") + ); + } + #[test] fn only_transport_loss_closes_an_open_remote_session() { assert!(remote_error_closes_connection("connection_lost")); diff --git a/specs/tabs.allium b/specs/tabs.allium index 85b9567..e223d7b 100644 --- a/specs/tabs.allium +++ b/specs/tabs.allium @@ -12,6 +12,7 @@ surface TabControlSurface { facing _: TabOperator provides: + PreferencesRequested() OpenTabRequested(type, id, intent) OpenTabInBackgroundRequested(type, id, intent) CloseTabRequested(tab) @@ -19,6 +20,14 @@ surface TabControlSurface { ClearTabsRequested() } +rule OpenPreferences { + when: PreferencesRequested() + ensures: OpenTabRequested(type: settings, id: settings, intent: pin) + ensures: SettingsEditorHydrated() + ensures: SettingsSidebarSelected() + ensures: SidebarShown() +} + surface TabRuntimeSurface { facing _: TabRuntime