M4.53: Linked images remember their file and keep a preview; missing links ask Replace or Ignore, modified ones follow Update Links

A linked image (`ImageObject.link`, now a LinkInfo: absolute path, path relative to the document,
size, modification time, hash, page; old path strings still load) keeps a low-resolution preview
(`ImageBlob.proxy`, at most 256 px a side) that a native save writes in place of the pixels of
images only linked images show. Opening a native document reads the linked files again, looking
for each at its path, then relative to the document and by name in its folder: missing files
show their preview, modified ones are read again only with Update Links: Automatically.
`document.open` reports `missingLinks`, `modifiedLinks` and `updatedLinks`.

links.check reports each link's status, links.update reads modified files again and
links.relink points images at another file or at same-named files in a folder (each keeps its
bounds; one undo step). In the app, a document opened without its linked files asks about each
(Replace…, Ignore, Apply to All), then offers to update modified links when the preference asks.
The renderer caches previews apart from the file's pixels; the Eyedropper samples previews in
the object's pixel space.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bflatastic
2026-10-05 10:07:10 +07:00
co-authored by Claude Opus 5.5
parent 0c65fe77f3
commit 2e5ec7b251
39 changed files with 1586 additions and 96 deletions
+9
View File
@@ -253,3 +253,12 @@ agents) opens the `rasterEffectsSettings` dialog. Its fields are what `document.
`ui.dialog.confirm` runs it with them as one undo step; a bad value keeps the dialog open. Object → Rasterize… opens a
`command` dialog for `object.rasterize` whose fields (`ppi`, `colorModel`, `background`, `antiAlias`, `clippingMask`,
`addAround`) start from these settings.
Missing linked files: `app.open` of a document whose linked images' files can't be found (`document.open`'s
`missingLinks`) opens the `missingLinks` dialog for the first (fields `missing`: `[{name, path, ids}]`, `modified`,
`applyToAll`, `path`). `ui.dialog.set {field: "path", value}` then `ui.dialog.confirm` replaces it with that file
(`links.relink`; without `path` a file is picked), and with `applyToAll` the others are looked for by name in the same
folder; `ui.dialog.set {field: "discard", value: true}` then confirm ignores it (the images keep their preview), with
`applyToAll` the rest too. The next missing file is asked about after each answer; `ui.dialog.cancel` stops asking.
Then, with the preference `updateLinks: "askWhenModified"`, modified linked files are offered for update in a
`confirm` dialog whose `ui.dialog.confirm` runs `links.update`.