M6: Dev Mode: compare changes against any saved version

This commit is contained in:
bflatastic
2026-10-15 20:04:31 +07:00
parent 96d62f2653
commit 4c7cf899f4
17 changed files with 313 additions and 62 deletions
+1 -1
View File
@@ -337,7 +337,7 @@ fn version_index(cmd: &str, ds: &DocState, p: &Value) -> Result<usize> {
if i < ds.versions.len() { Ok(i) } else { Err(bad(cmd, format!("no version at index {i}"))) }
}
fn read_version(v: &Version) -> Result<Arc<Document>> {
pub(crate) fn read_version(v: &Version) -> Result<Arc<Document>> {
v.document().map_err(|e| EngineError::Other(format!("version “{}” can't be read: {e}", v.name)))
}
+22 -6
View File
@@ -34,7 +34,7 @@ pub fn specs() -> Vec<CommandSpec> {
spec!(
"dev.compare",
"Compare changes",
"{id? (default the first selected layer), show? (open the compare view in the app)} → {id, name, changed, snapshot, added, removed, modified, truncated, changes: [{id, name, type, change: added|removed|changed, depth, layers, properties?: [{section, property, before, after, text}]}]} what changed in a ready-for-dev frame or section since it was marked (`snapshot` is false when that isn't known: a file from before snapshots were kept)",
"{id? (default the first selected layer), version? (a version id from version.list: compare with that saved version instead; any top-level frame or section), show? (open the compare view in the app)} → {id, name, changed, snapshot, added, removed, modified, truncated, version: {id, name, time} | null, changes: [{id, name, type, change: added|removed|changed, depth, layers, properties?: [{section, property, before, after, text}]}]} what changed in a ready-for-dev frame or section since it was marked, or since the version (`snapshot` is false when that isn't known: a file from before snapshots were kept)",
false,
compare
),
@@ -104,14 +104,30 @@ fn resolve_change(s: &mut Session, p: &Value) -> Result<Value> {
fn compare(s: &mut Session, p: &Value) -> Result<Value> {
let cmd = "dev.compare";
let id = targets(s, p).first().copied().ok_or_else(|| bad(cmd, "select a frame or section or pass `id`"))?;
let doc = s.doc()?;
let version = match get(p, "version") {
None | Some(Value::Null) => None,
Some(Value::String(v)) => Some(v.clone()),
Some(_) => return Err(bad(cmd, "version: a version id (version.list)")),
};
let ds = s.ds()?;
let doc = &ds.doc;
let n = doc.node(id).ok_or_else(|| bad(cmd, "no such layer"))?;
if !has_status(doc, id) || n.dev_status != DevStatus::ReadyForDev {
return Err(bad(cmd, "compare a frame or section marked ready for dev"));
if !has_status(doc, id) {
return Err(bad(cmd, "compare a top-level frame or a section"));
}
let v = serde_json::to_value(crate::devcompare::compare(doc, id)).unwrap_or(Value::Null);
let (cmp, against) = match &version {
Some(v) => {
let ver = ds.versions.iter().find(|x| x.id == *v).ok_or_else(|| bad(cmd, format!("no version `{v}`")))?;
let before = crate::cmd::file::read_version(ver)?;
(crate::devcompare::compare_with(&before, doc, id), json!({"id": ver.id, "name": ver.name, "time": ver.time}))
}
None if n.dev_status != DevStatus::ReadyForDev => return Err(bad(cmd, "compare a frame or section marked ready for dev, or pass `version`")),
None => (crate::devcompare::compare(doc, id), Value::Null),
};
let mut v = serde_json::to_value(cmp).unwrap_or(Value::Null);
v["version"] = against;
if boolean(p, "show") == Some(true) {
s.request_ui("view.devCompare", json!({"id": id}));
s.request_ui("view.devCompare", json!({"id": id, "version": version}));
}
Ok(v)
}