Clean up autosave persistence (#3115)

* Set auto save state to false on document rename

* Update open document list on transaction commit and aboard

* Use current network to compute hash

Was using the last element in undo
Before artworks where not auto saved when the had no undo history

* Refactor persistence
This commit is contained in:
Timon
2025-09-02 13:27:38 +00:00
committed by GitHub
parent b5ebe78f5e
commit 083dfa5f49
9 changed files with 93 additions and 83 deletions
@@ -1,4 +1,4 @@
use super::utility_types::{FrontendDocumentDetails, MouseCursorIcon};
use super::utility_types::{DocumentDetails, MouseCursorIcon, OpenDocument};
use crate::messages::app_window::app_window_message_handler::AppWindowPlatform;
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::node_graph::utility_types::{
@@ -90,13 +90,15 @@ pub enum FrontendMessage {
font: Font,
},
TriggerImport,
TriggerIndexedDbRemoveDocument {
TriggerPersistenceRemoveDocument {
#[serde(rename = "documentId")]
document_id: DocumentId,
},
TriggerIndexedDbWriteDocument {
TriggerPersistenceWriteDocument {
#[serde(rename = "documentId")]
document_id: DocumentId,
document: String,
details: FrontendDocumentDetails,
details: DocumentDetails,
},
TriggerLoadFirstAutoSaveDocument,
TriggerLoadRestAutoSaveDocuments,
@@ -308,7 +310,7 @@ pub enum FrontendMessage {
},
UpdateOpenDocumentsList {
#[serde(rename = "openDocuments")]
open_documents: Vec<FrontendDocumentDetails>,
open_documents: Vec<OpenDocument>,
},
UpdatePropertiesPanelLayout {
#[serde(rename = "layoutTarget")]
+10 -5
View File
@@ -2,13 +2,18 @@ use crate::messages::portfolio::document::utility_types::document_metadata::Laye
use crate::messages::prelude::*;
#[derive(PartialEq, Eq, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct FrontendDocumentDetails {
#[serde(rename = "isAutoSaved")]
pub is_auto_saved: bool,
pub struct OpenDocument {
pub id: DocumentId,
pub details: DocumentDetails,
}
#[derive(PartialEq, Eq, Clone, Debug, serde::Serialize, serde::Deserialize, specta::Type)]
pub struct DocumentDetails {
pub name: String,
#[serde(rename = "isSaved")]
pub is_saved: bool,
pub name: String,
pub id: DocumentId,
#[serde(rename = "isAutoSaved")]
pub is_auto_saved: bool,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
@@ -952,6 +952,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
self.path = None;
self.set_save_state(false);
self.set_auto_save_state(false);
responses.add(PortfolioMessage::UpdateOpenDocumentsList);
responses.add(NodeGraphMessage::UpdateNewNodeGraph);
@@ -1301,6 +1302,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
}
self.network_interface.finish_transaction();
self.document_redo_history.clear();
responses.add(PortfolioMessage::UpdateOpenDocumentsList);
}
DocumentMessage::AbortTransaction => {
responses.add(DocumentMessage::RepeatedAbortTransaction { undo_count: 1 });
@@ -1316,6 +1318,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
self.network_interface.finish_transaction();
responses.add(OverlaysMessage::Draw);
responses.add(PortfolioMessage::UpdateOpenDocumentsList);
}
DocumentMessage::ToggleLayerExpansion { id, recursive } => {
let layer = LayerNodeIdentifier::new(id, &self.network_interface);
@@ -1975,16 +1978,16 @@ impl DocumentMessageHandler {
Some(previous_network)
}
pub fn current_hash(&self) -> Option<u64> {
self.document_undo_history.iter().last().map(|network| network.document_network().current_hash())
pub fn current_hash(&self) -> u64 {
self.network_interface.document_network().current_hash()
}
pub fn is_auto_saved(&self) -> bool {
self.current_hash() == self.auto_saved_hash
Some(self.current_hash()) == self.auto_saved_hash
}
pub fn is_saved(&self) -> bool {
self.current_hash() == self.saved_hash
Some(self.current_hash()) == self.saved_hash
}
pub fn is_graph_overlay_open(&self) -> bool {
@@ -1993,7 +1996,7 @@ impl DocumentMessageHandler {
pub fn set_auto_save_state(&mut self, is_saved: bool) {
if is_saved {
self.auto_saved_hash = self.current_hash();
self.auto_saved_hash = Some(self.current_hash());
} else {
self.auto_saved_hash = None;
}
@@ -2001,7 +2004,7 @@ impl DocumentMessageHandler {
pub fn set_save_state(&mut self, is_saved: bool) {
if is_saved {
self.saved_hash = self.current_hash();
self.saved_hash = Some(self.current_hash());
} else {
self.saved_hash = None;
}
@@ -6,7 +6,7 @@ use crate::consts::{DEFAULT_DOCUMENT_NAME, DEFAULT_STROKE_WIDTH, FILE_EXTENSION}
use crate::messages::animation::TimingInformation;
use crate::messages::debug::utility_types::MessageLoggingVerbosity;
use crate::messages::dialog::simple_dialogs;
use crate::messages::frontend::utility_types::FrontendDocumentDetails;
use crate::messages::frontend::utility_types::{DocumentDetails, OpenDocument};
use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::DocumentMessageContext;
use crate::messages::portfolio::document::graph_operation::utility_types::TransformIn;
@@ -187,13 +187,13 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
}
PortfolioMessage::AutoSaveDocument { document_id } => {
let document = self.documents.get(&document_id).unwrap();
responses.add(FrontendMessage::TriggerIndexedDbWriteDocument {
responses.add(FrontendMessage::TriggerPersistenceWriteDocument {
document_id,
document: document.serialize_document(),
details: FrontendDocumentDetails {
is_auto_saved: document.is_auto_saved(),
is_saved: document.is_saved(),
id: document_id,
details: DocumentDetails {
name: document.name.clone(),
is_saved: document.is_saved(),
is_auto_saved: document.is_auto_saved(),
},
})
}
@@ -216,7 +216,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
}
for document_id in &self.document_ids {
responses.add(FrontendMessage::TriggerIndexedDbRemoveDocument { document_id: *document_id });
responses.add(FrontendMessage::TriggerPersistenceRemoveDocument { document_id: *document_id });
}
responses.add(PortfolioMessage::DestroyAllDocuments);
@@ -242,7 +242,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
// Actually delete the document (delay to delete document is required to let the document and properties panel messages above get processed)
responses.add(PortfolioMessage::DeleteDocument { document_id });
responses.add(FrontendMessage::TriggerIndexedDbRemoveDocument { document_id });
responses.add(FrontendMessage::TriggerPersistenceRemoveDocument { document_id });
// Send the new list of document tab names
responses.add(PortfolioMessage::UpdateOpenDocumentsList);
@@ -1044,11 +1044,13 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
.document_ids
.iter()
.filter_map(|id| {
self.documents.get(id).map(|document| FrontendDocumentDetails {
is_auto_saved: document.is_auto_saved(),
is_saved: document.is_saved(),
self.documents.get(id).map(|document| OpenDocument {
id: *id,
name: document.name.clone(),
details: DocumentDetails {
is_auto_saved: document.is_auto_saved(),
is_saved: document.is_saved(),
name: document.name.clone(),
},
})
})
.collect::<Vec<_>>();