mirror of
https://github.com/storytold/gridcraft.git
synced 2026-10-24 10:46:50 -06:00
fix(ui): persist the AutoSave preference across restarts
Closes #1901 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -969,9 +969,9 @@ fn options(app: &mut SheetApp, ui: &mut Ui) {
|
||||
}
|
||||
ui.add_space(18.0);
|
||||
section(ui, lang, "Options|Save");
|
||||
let mut autosave = app.grid.autosave();
|
||||
let mut autosave = app.ui.autosave;
|
||||
if ui.checkbox(&mut autosave, lang.tr("Save .xlsx workbooks automatically after every change")).changed() {
|
||||
app.grid.toggle_autosave();
|
||||
app.toggle_autosave();
|
||||
}
|
||||
let Some(calc) = app.session.active().map(|d| d.wb.calc.clone()) else { return };
|
||||
ui.add_space(18.0);
|
||||
|
||||
@@ -119,7 +119,6 @@ pub struct GridState {
|
||||
pub glide: crate::selection_glide::SelectionGlide,
|
||||
pub last_click: Option<(CellRef, f64)>,
|
||||
pub hover_cell: Option<CellRef>,
|
||||
pub autosave: bool,
|
||||
pub last_autosave: f64,
|
||||
pub last_border: String,
|
||||
pub last_fill: String,
|
||||
@@ -179,15 +178,6 @@ impl WheelZoom {
|
||||
}
|
||||
}
|
||||
|
||||
impl GridState {
|
||||
pub fn autosave(&self) -> bool {
|
||||
self.autosave
|
||||
}
|
||||
pub fn toggle_autosave(&mut self) {
|
||||
self.autosave = !self.autosave;
|
||||
}
|
||||
}
|
||||
|
||||
/// Geometry of the grid for one frame (handles zoom and frozen panes).
|
||||
#[derive(Clone)]
|
||||
pub struct Geo {
|
||||
|
||||
@@ -60,6 +60,9 @@ pub struct UiState {
|
||||
/// Enable AutoComplete for cell values (File ▸ Options ▸ Editing): typed text is completed
|
||||
/// from the one matching entry in the same column.
|
||||
pub autocomplete: bool,
|
||||
/// AutoSave (the title-bar switch): save saved-to-file .xlsx workbooks shortly after every
|
||||
/// change. A preference like the rest of this struct — it stays on across restarts (#1901).
|
||||
pub autosave: bool,
|
||||
pub recent: Vec<String>,
|
||||
/// One-shot keytip request for a ribbon control: set when a keytip action resolves to
|
||||
/// [`keytips::Action::Control`], consumed (and cleared) by the control's render site.
|
||||
@@ -103,6 +106,7 @@ impl Default for UiState {
|
||||
status_bar: true,
|
||||
animations: true,
|
||||
autocomplete: true,
|
||||
autosave: false,
|
||||
recent: vec![],
|
||||
keytip_invoke: None,
|
||||
language: i18n::Language::En,
|
||||
@@ -1128,6 +1132,12 @@ impl SheetApp {
|
||||
}
|
||||
}
|
||||
|
||||
/// Flip AutoSave (title-bar switch / Options ▸ Save). Persisted with the other UI
|
||||
/// preferences, so it stays as the user left it across restarts (#1901).
|
||||
pub fn toggle_autosave(&mut self) {
|
||||
self.ui.autosave = !self.ui.autosave;
|
||||
}
|
||||
|
||||
/// Lays out the whole window.
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
let ctx = ui.ctx().clone();
|
||||
@@ -1190,7 +1200,7 @@ impl SheetApp {
|
||||
}
|
||||
self.perf.last = now;
|
||||
// AutoSave: save workbooks that have a file shortly after they change.
|
||||
if self.grid.autosave
|
||||
if self.ui.autosave
|
||||
&& self.editor.is_none()
|
||||
&& self.text_box_editor.is_none()
|
||||
&& now - self.grid.last_autosave > 2000.0
|
||||
|
||||
@@ -53,14 +53,14 @@ pub fn title_bar(app: &mut SheetApp, ui: &mut Ui) {
|
||||
ui.add_space(TITLE_LEFT_PAD);
|
||||
// AutoSave toggle (saves after each change when the workbook has a file).
|
||||
ui.label(egui::RichText::new("AutoSave").font(theme::ui_font(12.5)).color(t.text_dim));
|
||||
let on = app.grid.autosave();
|
||||
let on = app.ui.autosave;
|
||||
let (r, resp) = ui.allocate_exact_size(vec2(30.0, 16.0), Sense::click());
|
||||
ui.painter().rect_filled(r, 8.0, if on { t.accent } else { Color32::TRANSPARENT });
|
||||
ui.painter().rect_stroke(r, 8.0, Stroke::new(1.0, if on { t.accent } else { t.text_dim }), StrokeKind::Inside);
|
||||
let knob = if on { pos2(r.right() - 8.0, r.center().y) } else { pos2(r.left() + 8.0, r.center().y) };
|
||||
ui.painter().circle_filled(knob, 5.0, if on { Color32::WHITE } else { t.text_dim });
|
||||
if resp.on_hover_text("AutoSave: save after every change (workbooks saved to a file)").clicked() {
|
||||
app.grid.toggle_autosave();
|
||||
app.toggle_autosave();
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
let __k = icon_button(ui, Icon::Home, t.text_dim, "Home", vec2(26.0, ch));
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
//! #1901: AutoSave is a preference — it must survive a restart like the other UI settings.
|
||||
|
||||
use gridcraft_engine::Session;
|
||||
use gridcraft_ui_egui::SheetApp;
|
||||
|
||||
#[test]
|
||||
fn autosave_survives_a_restart() {
|
||||
let mut app = SheetApp::new(Session::new(), Default::default());
|
||||
assert!(!app.ui.autosave, "off by default");
|
||||
app.toggle_autosave();
|
||||
assert!(app.ui.autosave, "the toggle flips the persisted flag");
|
||||
// What the desktop app writes to ui.json, and reads back on the next launch.
|
||||
let saved = serde_json::to_string(&app.ui).unwrap();
|
||||
let restored: gridcraft_ui_egui::UiState = serde_json::from_str(&saved).unwrap();
|
||||
assert!(restored.autosave, "a saved ui.json restores AutoSave on (#1901)");
|
||||
app.toggle_autosave();
|
||||
assert!(!app.ui.autosave, "toggling back persists off too");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_old_ui_json_without_autosave_still_loads() {
|
||||
// Files saved by earlier versions have no autosave key; serde(default) reads them as off.
|
||||
let restored: gridcraft_ui_egui::UiState = serde_json::from_str(r#"{"dark": true}"#).unwrap();
|
||||
assert!(!restored.autosave);
|
||||
assert!(restored.dark, "the rest of the old file still applies");
|
||||
}
|
||||
Reference in New Issue
Block a user