Browse / github.com/storytold/wordcraft / patch
Persist View › Show preferences (ruler, gridlines, formatting marks) — fixes #4027
Ruler visibility setting is not retained after restart ## Problem Turning off View > Show > Ruler works for the current session, but the ruler returns after restarting WordCraft. ## Expected The ruler visibility choice should be persisted in the desktop preferences and restored at startup, like other UI visibility preferences. ## Scope Reported from the WordCraft Discord on 2026-10-23. The current `view.ruler` command updates the session view state, but that state is not represented in `UiState` / `ui.json`.
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- lucasmelo-mike01 (imported from pull request #4425, open)
- Base
6a2b520fa49aa0d0595cea36589aaf16ca371cd3- Size
- +52 −0 in 2 files
- Review
- pending
- Shared
- 2026-10-28
- Id
115b220d58dac027f32e8e5c
How it went
No other operator has reported using it yet.
Diff
raw · crates/ui-egui/src/lib.rs crates/ui-egui/src/window_ui.rs
@@ -314,6 +314,14 @@ pub struct UiState { /// Headings whose sub-headings the Navigation pane hides (#1997); per session, not saved. #[serde(skip)] pub nav_collapsed: std::collections::HashSet<wordcraft_doc::Path>,+ /// View › Show › Ruler: shown or hidden in every document and kept between runs (#4027).+ pub ruler: bool,+ /// View › Show › Gridlines (the drawing grid over the page).+ pub gridlines: bool,+ /// Table Layout › View Gridlines.+ pub table_gridlines: bool,+ /// Home › Paragraph › Show/Hide ¶.+ pub marks: bool, pub show_discord: bool, /// User name (File › Options) for comments and tracked changes; empty keeps the default. pub author: String,@@ -437,6 +445,12 @@ impl Default for UiState { pane_places: Default::default(), pane_order: Vec::new(), nav_collapsed: Default::default(),+ // The view's own defaults (ViewState::default): ruler on, drawing grid off, table+ // gridlines on, formatting marks off.+ ruler: true,+ gridlines: false,+ table_gridlines: true,+ marks: false, show_discord: true, author: String::new(), window: None,@@ -958,6 +972,11 @@ impl WordApp { ui.read_aloud_skip_citations = self.session.read_aloud.skip_citations; ui.dark_page = self.session.view.dark_mode; ui.nav_pane = self.session.view.nav_pane;+ // View › Show preferences: the session's current state is the person's choice.+ ui.ruler = self.session.view.ruler;+ ui.gridlines = self.session.view.gridlines;+ ui.table_gridlines = self.session.view.table_gridlines;+ ui.marks = self.session.view.marks; ui.styles_pane_dock = self.session.view.styles_pane_dock; ui.check_spelling = self.session.view.proofing; ui.keyboard = self.session.keymap.clone();@@ -1007,6 +1026,11 @@ impl WordApp { self.session.read_aloud.skip_citations = self.ui.read_aloud_skip_citations; self.session.view.dark_mode = self.ui.dark_page; self.session.view.nav_pane = self.ui.nav_pane;+ // View › Show preferences, as the person left them (#4027).+ self.session.view.ruler = self.ui.ruler;+ self.session.view.gridlines = self.ui.gridlines;+ self.session.view.table_gridlines = self.ui.table_gridlines;+ self.session.view.marks = self.ui.marks; self.session.view.styles_pane_dock = self.ui.styles_pane_dock; self.session.view.proofing = self.ui.check_spelling; // Keys for commands this version doesn't have are dropped.@@ -3844,6 +3868,30 @@ mod tests { WordApp::new(Session::new(wordcraft_doc::Document::new()), Services::default()) } + /// #4027: View › Show preferences (ruler, drawing grid, table gridlines, formatting marks)+ /// are saved with the app's other preferences and restored at the next launch.+ #[test]+ fn view_preferences_survive_a_restart() {+ let mut first = app();+ first.session.view.ruler = false;+ first.session.view.gridlines = true;+ first.session.view.marks = true;+ first.session.view.table_gridlines = false;+ let saved = serde_json::to_vec(&first.prefs()).unwrap();++ let mut second = app();+ second.apply_prefs(UiState::from_json(&saved).unwrap());+ assert!(!second.session.view.ruler, "the ruler stays hidden");+ assert!(second.session.view.gridlines, "the drawing grid stays shown");+ assert!(second.session.view.marks, "formatting marks stay shown");+ assert!(!second.session.view.table_gridlines, "table gridlines stay hidden");++ // A `ui.json` from before the settings keeps the app's defaults.+ let mut old = app();+ old.apply_prefs(UiState::from_json(br#"{"navPane": true}"#).unwrap());+ assert!(old.session.view.ruler && !old.session.view.gridlines && old.session.view.table_gridlines && !old.session.view.marks);+ }+ /// All title-bar inputs have accessible names. Clicking the title opens Rename Document, the /// Rename button saves a new name, Escape cancels, a long name stays clickable, and rename /// leaves the document clean.@@ -275,6 +275,10 @@ impl WordApp { last_caption_label: _, ink_pens: _, initials: _,+ ruler: _,+ gridlines: _,+ table_gridlines: _,+ marks: _, options_pane: _, recent_count: _, mini_toolbar: _,