Refactor persistence to combine document handling and workspace layout (#4031)

* Unify editor state persistence

* Review

* Fix

* Remove redundant DocumentDetails

* LoadDocumentContent indirection
This commit is contained in:
Timon
2026-04-19 09:31:21 +00:00
committed by GitHub
parent 2a2a60883d
commit 6c5e3c97f8
36 changed files with 562 additions and 699 deletions
@@ -0,0 +1,7 @@
mod persistent_state_message;
mod persistent_state_message_handler;
#[doc(inline)]
pub use persistent_state_message::{PersistentStateMessage, PersistentStateMessageDiscriminant};
#[doc(inline)]
pub use persistent_state_message_handler::{PersistentStateMessageContext, PersistentStateMessageHandler};
@@ -0,0 +1,30 @@
use crate::messages::frontend::utility_types::PersistedState;
use crate::messages::prelude::*;
#[impl_message(Message, PortfolioMessage, PersistentState)]
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum PersistentStateMessage {
ReadState,
WriteState,
LoadState {
state: PersistedState,
},
ReadDocument {
#[serde(rename = "documentId")]
document_id: DocumentId,
},
WriteDocument {
#[serde(rename = "documentId")]
document_id: DocumentId,
document: String,
},
DeleteDocument {
#[serde(rename = "documentId")]
document_id: DocumentId,
},
LoadDocument {
#[serde(rename = "documentId")]
document_id: DocumentId,
document: String,
},
}
@@ -0,0 +1,54 @@
use crate::messages::frontend::utility_types::PersistedState;
use crate::messages::portfolio::utility_types::WorkspacePanelLayout;
use crate::messages::prelude::*;
#[derive(Default, Debug, Clone, ExtractField)]
pub struct PersistentStateMessageHandler {
loaded: bool,
}
#[derive(ExtractField)]
pub struct PersistentStateMessageContext {
pub persisted_state: PersistedState,
}
#[message_handler_data]
impl MessageHandler<PersistentStateMessage, PersistentStateMessageContext> for PersistentStateMessageHandler {
fn process_message(&mut self, message: PersistentStateMessage, responses: &mut VecDeque<Message>, context: PersistentStateMessageContext) {
let PersistentStateMessageContext { persisted_state: state } = context;
match message {
PersistentStateMessage::ReadState => {
responses.add(FrontendMessage::TriggerPersistenceReadState);
}
PersistentStateMessage::WriteState => {
if !self.loaded && (state.documents.is_empty() && (state.workspace_layout == Some(WorkspacePanelLayout::default()) || state.workspace_layout.is_none())) {
return;
}
self.loaded = true;
responses.add(FrontendMessage::TriggerPersistenceWriteState { state });
}
PersistentStateMessage::LoadState { state } => {
self.loaded = true;
responses.add(PortfolioMessage::LoadPersistedState { state });
}
PersistentStateMessage::ReadDocument { document_id } => {
responses.add(FrontendMessage::TriggerPersistenceReadDocument { document_id });
}
PersistentStateMessage::WriteDocument { document_id, document } => {
responses.add(FrontendMessage::TriggerPersistenceWriteDocument { document_id, document });
}
PersistentStateMessage::DeleteDocument { document_id } => {
responses.add(FrontendMessage::TriggerPersistenceDeleteDocument { document_id });
}
PersistentStateMessage::LoadDocument { document_id, document } => {
responses.add(PortfolioMessage::LoadDocumentContent {
document_id,
document_serialized_content: document,
});
}
}
}
advertise_actions!(PersistentStateMessageDiscriminant;);
}