Integrate document-format storage into the editor (#4265)

* Integrate document-format storage into the editor

* Address review feedback: drop redundant clones and dedupe metadata traversal

* Extract DocumentHistory and move storage-metadata tests to their own file

* Extract storage diffing/IO, gate validation and .gdd save behind preferences, restructure tests

* Address PR review: save-format/path consistency, autosave persistence, and view-settings/diff fixes

* Skip storage remount on .gdd open and split value/timestamp drift in attribute diff

* Rename storage tests module and surface .gdd open failures with per-resource diff detail

* Add debug-menu toggle to hide the storage preferences section

* Hopefully fix async tests

* Shorten comments

* Fix tests

* Review

* Review

* Review

* Block on future mesages in tests

* Review

* Shorten comments

---------

Co-authored-by: Timon <me@timon.zip>
This commit is contained in:
Dennis Kobert
2026-07-04 19:27:00 +00:00
committed by GitHub
co-authored by Timon
parent 294952e152
commit 540a4ff273
32 changed files with 2979 additions and 72 deletions
@@ -303,6 +303,62 @@ impl PreferencesDialogMessageHandler {
rows.extend_from_slice(&[header, node_graph_wires_label, graph_wire_style, brush_tool]);
}
// =========
// DOCUMENTS
// =========
// Soak-only `.gdd` storage options, hidden unless enabled from the developer debug menu.
if preferences.show_storage_preferences {
let header = vec![TextLabel::new("Documents").italic(true).widget_instance()];
let save_as_gdd_description = "
Save documents in the new .gdd container format (with the legacy .graphite file embedded as a recovery fallback) instead of a plain .graphite file. The .gdd format is still being validated, so this is opt-in for now.\n\
\n\
*Default: Off.*
"
.trim();
let save_as_gdd_checkbox_id = CheckboxId::new();
let save_as_gdd = vec![
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
CheckboxInput::new(preferences.save_as_gdd)
.tooltip_label("Save as .gdd")
.tooltip_description(save_as_gdd_description)
.on_update(|checkbox_input: &CheckboxInput| PreferencesMessage::SaveAsGdd { enabled: checkbox_input.checked }.into())
.for_label(save_as_gdd_checkbox_id)
.widget_instance(),
TextLabel::new("Save as .gdd")
.tooltip_label("Save as .gdd")
.tooltip_description(save_as_gdd_description)
.for_checkbox(save_as_gdd_checkbox_id)
.widget_instance(),
];
let validate_description = "
Validate every document save, open, and undo by round-tripping it through the .gdd storage format and comparing against the legacy path, logging any mismatch. Useful for debugging the .gdd format during its soak, but the per-edit round-trip has a performance cost.\n\
\n\
*Default: Off.*
"
.trim();
let validate_checkbox_id = CheckboxId::new();
let validate_storage_round_trip = vec![
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
CheckboxInput::new(preferences.validate_storage_round_trip)
.tooltip_label("Validate Storage Round-Trip")
.tooltip_description(validate_description)
.on_update(|checkbox_input: &CheckboxInput| PreferencesMessage::ValidateStorageRoundTrip { enabled: checkbox_input.checked }.into())
.for_label(validate_checkbox_id)
.widget_instance(),
TextLabel::new("Validate Storage Round-Trip")
.tooltip_label("Validate Storage Round-Trip")
.tooltip_description(validate_description)
.for_checkbox(validate_checkbox_id)
.widget_instance(),
];
rows.extend_from_slice(&[header, save_as_gdd, validate_storage_round_trip]);
}
// =============
// COMPATIBILITY
// =============