Links: Find in Folder… looks for missing linked files in a folder and its subfolders

Find in Folder… in Linked File Not Found and in the Links panel menu
looks in a folder the user picks, and in its subfolders, for the files
with the names of missing linked files, in any letter case. In the
Links panel menu it looks for the selected linked files when there are
any. It uses the folder search of the Missing Fonts dialog. Find
Linked Files lists each file it looks for with the files found for it.
A file with the size and contents saved with the link comes first. A
file of the saved size comes next when the link saved no hash or the
file is larger than 1 GB, and any other file of the name comes last.
Within each group, a file named in the same letter case comes first.
Then each file's folder names are compared with the saved path's, from
the innermost outward, up to the first one that differs, and a file
with more matching names comes before one with fewer. A file is chosen
when it is the only file found, or the only one with the saved
contents, and the user can choose another file or Don't Relink.

Relink relinks each file chosen, and each relink is one undo step.
With Copy into the document's folder, which shows for a saved
document, each image's file is copied next to the document first. The
file's name, then Name 2.png, Name 3.png and so on, are tried in turn
until one is free, which gets the copy, or is a file with the same
contents, which is used. A placed document is relinked where its file
is. The status line names the first file that fails to relink, and the
other files still relink. When Find Linked Files opens from Linked
File Not Found, the missing files left without a choice, and any that
fail to relink, go back to that dialog. On the web, Find in Folder… is
disabled in the Links panel menu, and links.findFiles can't start a
search.

- links.findFiles searches on separate threads and returns at once;
  links.findFiles {} reports the search, and {stop: true} stops it. It
  looks for at most 1,000 linked files at once: the active document's
  missing ones, or those of the objects it is given. It hashes a file
  only when a link of its name saved the file's size and a hash, and
  only when the file is 1 GB or smaller. It ends once every linked
  file has its same file, and it searches only the folders
  text.findFontFiles may search, with the same maxSeconds, depth and
  count limits.
- links.relink {copy} copies the file it is given into the saved
  document's folder and links images to the copy; a call that includes
  a placed document fails. Each name it writes is checked against the
  automation write root. text.addFontFiles and links.relink {copy}
  make their copies with fileio::copy_new, which never replaces a
  file. The text.addFontFiles params text and docs/mcp.md say which
  names are tried for a copy.
- vectorcraft-doc adds links::hash_reader, which hashes what a reader
  reads as hash_bytes hashes bytes.
- ui.findLinksInFolder is the Links panel's Find in Folder… for agents;
  docs/control-protocol.md lists the dialog's fields.

Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
This commit is contained in:
dotCooCoo
2026-10-12 08:16:41 +07:00
committed by bflatastic
parent b865547bc0
commit b3f832cbcd
28 changed files with 1769 additions and 85 deletions
+20
View File
@@ -449,6 +449,26 @@ Then, with the preference `updateLinks: "askWhenModified"`, modified linked file
the front and a linked file of the active document changed meanwhile (asked once per change of a file); with
`"automatically"` the files are read again at once, with `"manually"` the Links panel shows them as modified.
Find Linked Files: in the `missingLinks` dialog, `ui.dialog.set {field: "searchFolder", value}` then `ui.dialog.confirm`
is Find in Folder…: the dialog becomes `findLinks`, which looks in that folder and its subfolders for every file the
dialog still asks about (`links.findFiles`). Fields: `document` (the document's uid), `missing` (`[{name, path, ids}]`),
`modified`, `back`, `state` (empty, `searching`, `done`, `stopped` or `failed`), `search` (the search's `id`), `folder`,
`found` (`links.findFiles`'s `links`, with the files found), `searched`, `skipped`, `unreadable`, `stopped`, `error`,
`picks` (the file chosen for each row of `missing`, or null; with each search result, a row not chosen in the dialog
gets its only same file, else its only file found), `touched` (the rows whose file was chosen in the dialog; search
results leave their pick as it is), `copy` (Copy into the document's folder, shown for a saved document) and
`searchFolder`. `ui.dialog.set {field: "searchFolder", value}` then `ui.dialog.confirm` searches that folder and keeps
the dialog open. The fields change as frames draw the dialog; `links.findFiles {}` reports the search directly.
`ui.dialog.confirm` without `searchFolder` is Relink: each row with a file runs `links.relink {ids, path, copy}`, one
undo step each (`copy` for images only: a placed document is relinked where its file is), and it returns `{relinked,
failed}`; the status line names the first file that failed. With `back` (opened from `missingLinks`), the rows left
without a file and those that failed go back to that dialog, then the modified files are offered for update.
`ui.dialog.cancel` closes it and stops its search. `ui.findLinksInFolder {folder?, ids?}` (Find in Folder… in the Links
panel menu) asks for a folder (or takes `folder`), then opens the dialog for the files of `ids`, else of the selected
linked images and placed documents, else the missing ones; with nothing to look for, it fails with "No linked files to
look for" and asks for no folder. On the web, `ui.findLinksInFolder` is disabled, `links.findFiles` can't start a search
and the dialog doesn't open.
Missing fonts: once the missing linked file questions are answered, or at once when there are none, `app.open` of a
document whose type uses fonts that aren't available (`text.missingFonts`) opens the `missingFonts` dialog, one document
at a time, and so does `links.editOriginal` of a placed document. When another dialog takes its place (Import PDF for a