Merge main into #1419

# Conflicts:
#	docs/roadmap.md
This commit is contained in:
bflatastic
2026-10-29 10:30:12 +07:00
303 changed files with 11970 additions and 4445 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
use super::*;
use super::{DocState, Document, EngineError, NodeId, Result, Session, Value, json};
impl Session {
pub fn ds(&self) -> Result<&DocState> {
+26 -10
View File
@@ -1,4 +1,7 @@
use super::*;
use super::{
Arc, CommandSpec, Document, ENDS_PREVIEW, EngineError, Node, NodeId, PREVIEW_READ_ONLY, Result, Session, Value, bad, board, branches, cmd,
components, find_command, guard, library, normalize, params, textpreview,
};
/// Whether a command, or a batch wrapping one, imports a file passed as Base64 `data`.
fn command_carries_import_bytes(id: &str, params: &Value) -> bool {
@@ -48,7 +51,14 @@ impl Session {
.and_then(|v| self.check_instance_structure(id, &before).map(|()| v))
.and_then(|v| self.check_preview(id, &before).map(|()| v))
.and_then(|v| self.check_live_access(id, &before).map(|()| v))
.and_then(|v| self.check_finite_geometry(id, &before).map(|()| v));
.and_then(|v| self.check_finite_geometry(id, &before).map(|()| v))
// Normalising is part of the command: a panic in it rolls the edit back too (#1085).
.and_then(|v| {
guard::run(id, || {
self.normalize_edit(spec, &before);
Ok(v)
})
});
match &result {
Ok(_) => {
self.after_command(spec, before);
@@ -138,7 +148,19 @@ impl Session {
.map_err(|m| EngineError::Disabled(id.to_string(), m))
}
/// Bookkeeping after a successful command: normalise what changed, push undo, bump revision.
/// Normalise what a command changed in the document it ran on (text boxes, groups, instances,
/// auto layout…).
fn normalize_edit(&mut self, spec: &CommandSpec, before: &Option<(Arc<Document>, Vec<NodeId>, NodeId, u64)>) {
let Some((bdoc, _, _, uid)) = before else { return };
let Some(ds) = self.docs.iter_mut().find(|d| d.uid == *uid) else { return };
// Saving may adopt the chosen filename as the document title. The encoded snapshot is
// already final; normalising it again would detach it from the saved baseline.
if !Arc::ptr_eq(&ds.doc, bdoc) && !matches!(spec.id, "file.save" | "file.saveAs") {
normalize(ds.doc_mut(), bdoc);
}
}
/// Bookkeeping after a successful command (normalised already): push undo, bump revision.
fn after_command(&mut self, spec: &CommandSpec, before: Option<(Arc<Document>, Vec<NodeId>, NodeId, u64)>) {
let Some((bdoc, bsel, bpage, uid)) = before else {
if let Ok(ds) = self.ds_mut() {
@@ -147,13 +169,7 @@ impl Session {
return;
};
let Some(ds) = self.docs.iter_mut().find(|d| d.uid == uid) else { return };
let changed = !Arc::ptr_eq(&ds.doc, &bdoc);
// Saving may adopt the chosen filename as the document title. The encoded snapshot is
// already final; normalising it again would detach it from the saved baseline.
if changed && !matches!(spec.id, "file.save" | "file.saveAs") {
normalize(ds.doc_mut(), &bdoc);
}
let edit = changed && ds.interaction.is_none();
let edit = !Arc::ptr_eq(&ds.doc, &bdoc) && ds.interaction.is_none();
ds.clean_selection();
ds.revision += 1;
if edit {
+1 -1
View File
@@ -1,4 +1,4 @@
use super::*;
use super::{Arc, Clipboard, DocState, Document, Prefs, Session, background, cmd, library, live, plugins, tools};
impl Session {
/// A session with one new document.
+4 -1
View File
@@ -1,4 +1,7 @@
use super::*;
use super::{
Arc, BatchScope, BatchStep, DocState, Document, EngineError, HistoryEntry, Interaction, NodeId, PREVIEW_READ_ONLY, Result, Session, UiRequest,
Value, cmd, figcraft_collab, normalize, textpreview,
};
impl Session {
/// How many undo and redo steps the active document has (the user's own in a live session).