mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 05:24:44 +00:00
Status bar: a line about linked files keeps the open's notes listed
When a document opened with notes and with linked files that changed on
disk (Update Links: Manually) or, on the web, can't be read, the line
about the linked files replaced the "Opened with N notes" line, and the
notes could no longer be listed on hover or by a screen reader. The
status bar now shows the line about the linked files, then counts the
notes and names the first, and keeps the notes for that line.
- The Linked File Not Found and Find Linked Files dialogs keep the
open's notes (field `notes`), so the line about modified files shown
after them carries the notes of that open, not of an earlier one.
- File > New from Template... shows the notes of the file it opens, as
File > Open does.
- New message "{notice}. Opened with {n} note(s): {first}" in every
catalog that translates "Opened with {n} note(s): {first}".
Docs: docs/control-protocol.md, docs/target-app-parity.md.
This commit is contained in:
@@ -107,7 +107,7 @@ the two can still win that race.
|
||||
| `ui.render` | `{path?, scale?, artboard?, data?, traceViews?}` | render an artboard headlessly (PNG with the pixels of `app.export {format: "png", background: "white"}` at the same scale; `artboard`: its 0-based index, default the first; `traceViews: true`: Image Trace objects draw in their View, as on the canvas, instead of their tracing result): written to `path`, else (or with `data: true` as well) sent back as `pngBase64` |
|
||||
| `ui.render` | `{path?, scale?, artboard?, data?}` | render an artboard headlessly (PNG with the pixels of `app.export {format: "png", background: "white"}` at the same scale; `artboard`: its 0-based index, default the first): written to `path`, else (or with `data: true` as well) sent back as `pngBase64` |
|
||||
| `ui.resize` / `ui.focus` | | |
|
||||
| `app.open` / `app.save` / `app.export` / `app.quit` | `{path, importer?, params?}` / `{path?}` / `{path?, format?, artboard?, range?, scale?, …}` | `app.open` reads every format `document.open` reads (see `document.formats`) and returns its result (`{index, title, format, warnings, …}`; `warnings` say what didn't come in as it was, such as an EPS shown as its preview image and why its PostScript couldn't be read), or null when a dialog asks first or a library loads. The status bar (`ui.inspect` → `ui.status`) counts the `warnings` and names the first that says reading the file left something out (the notes that make Save ask before writing over it), else the first; with several, hovering it lists them in that order, as many as fit in the window (at most 30), then how many more. After `app.save`, and `app.export` with a `path`, the status bar counts the reply's `warnings` and names the first, and with several, hovering it lists them in the reply's order (a save's notes start with what the format loses). With `importer` (an importer plug-in's format id, `plugin.<id>`) it runs `file.openWith`: the file opens with that importer, also when a built-in format reads its extension, with the importer's parameters `params` (their defaults when omitted; no dialog asks for them). Without `importer`, `params` go to the importer that opens the file, and a built-in format does not read them. `app.export` encodes through the engine's `document.export` (same options; the document keeps its path) and writes `path` through the host; without `path` it returns `{dataBase64, format, bytes}`, as headless mode does. It refuses a key that no format takes, and an unknown key inside a PDF or EPS option object, before it writes anything (`docs/mcp.md`, Parameter keys). `app.save` refuses a key that no save format takes, beside the path or in `options`, the same way. `app.quit`, `file.close` and `file.closeAll` first open a `saveChanges` dialog for each modified document (they return `{"pending": "saveChanges"}`): `ui.dialog.confirm` saves, `ui.dialog.set {field: "discard", value: true}` then confirm discards, `ui.dialog.cancel` cancels the whole close or quit |
|
||||
| `app.open` / `app.save` / `app.export` / `app.quit` | `{path, importer?, params?}` / `{path?}` / `{path?, format?, artboard?, range?, scale?, …}` | `app.open` reads every format `document.open` reads (see `document.formats`) and returns its result (`{index, title, format, warnings, …}`; `warnings` say what didn't come in as it was, such as an EPS shown as its preview image and why its PostScript couldn't be read), or null when a dialog asks first or a library loads. The status bar (`ui.inspect` → `ui.status`), after a line about the document's linked files when there is one (Missing linked files below), counts the `warnings` and names the first that says reading the file left something out (the notes that make Save ask before writing over it), else the first; with several, hovering it lists them in that order, as many as fit in the window (at most 30), then how many more. After `app.save`, and `app.export` with a `path`, the status bar counts the reply's `warnings` and names the first, and with several, hovering it lists them in the reply's order (a save's notes start with what the format loses). With `importer` (an importer plug-in's format id, `plugin.<id>`) it runs `file.openWith`: the file opens with that importer, also when a built-in format reads its extension, with the importer's parameters `params` (their defaults when omitted; no dialog asks for them). Without `importer`, `params` go to the importer that opens the file, and a built-in format does not read them. `app.export` encodes through the engine's `document.export` (same options; the document keeps its path) and writes `path` through the host; without `path` it returns `{dataBase64, format, bytes}`, as headless mode does. It refuses a key that no format takes, and an unknown key inside a PDF or EPS option object, before it writes anything (`docs/mcp.md`, Parameter keys). `app.save` refuses a key that no save format takes, beside the path or in `options`, the same way. `app.quit`, `file.close` and `file.closeAll` first open a `saveChanges` dialog for each modified document (they return `{"pending": "saveChanges"}`): `ui.dialog.confirm` saves, `ui.dialog.set {field: "discard", value: true}` then confirm discards, `ui.dialog.cancel` cancels the whole close or quit |
|
||||
| `app.export` with `useArtboards` | `{path, useArtboards: true, range? \| artboards?, …}` | Export As: PNG, JPEG and WebP write one file per chosen artboard (default all; SVG does so for a `range`), `<path stem>-<artboard>.<ext>`, and return `{path, files: [path…]}`; a PDF keeps them as pages of `path`. `useArtboards: false` covers the bounds of the visible art. The menu's Export As… is `file.exportAs`: the `exportAs` dialog (`format`, `useArtboards`, `all`, `range`), then a save dialog and the format's options: `pngOptions` / `jpgOptions` / `webpOptions`, `svgOptions`, or `savePdf` for a PDF |
|
||||
| `ui.dialog.*` on `gradientStop` | `{field: "color" \| "opacity" \| "location", value}` | double-clicking a stop on the Gradient tool's annotator opens its popover (fields `index`, `x`, `y`, `tab`); set `color` (hex), `opacity` or `location` (percentages) and `ui.dialog.confirm` to apply them to the selected stop. `gradient.selectStop {index}` picks the stop the annotator, the panels and Delete/←/→ (`ui.key`) act on |
|
||||
| `engine.execute` `ui.savePdfDialog` | `{path?, preset?, range?, …document.exportPdf options}` | opens the Save PDF dialog (`file.export.pdf` with no params opens it too). Its fields are the `document.exportPdf` options: set `compatibility` with `ui.dialog.set {field: "compatibility", value: "1.5"}`, a whole section with `{field: "compression", value: {…}}`, the artboards with `__allArtboards: false` and `range`, the visible section with `__section` (General, Compression, Marks and Bleeds, Output, Advanced, Security, Summary). `useArtboards: false` opens it for one page of the visible art's bounds, as Export As with Use Artboards off does: the dialog has no Artboards section and its `__artBounds` field is true. `ui.dialog.confirm` writes `path` (else asks for one), returns `{path, bytes, warnings}` and opens the file when `viewAfterSaving` is set. With `useArtboards: false` it writes the page as `app.export` does and returns `{path, warnings}`, or `{background: true, status}` while Background Export writes it |
|
||||
@@ -645,7 +645,7 @@ agents) opens the `rasterEffectsSettings` dialog. Its fields are what `document.
|
||||
|
||||
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
|
||||
`notes` (the open's `warnings`), `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.
|
||||
@@ -653,11 +653,14 @@ Then, with the preference `updateLinks: "askWhenModified"`, modified linked file
|
||||
`confirm` dialog whose `ui.dialog.confirm` runs `links.update`. The same happens when the app's window comes back to
|
||||
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.
|
||||
After an open, the status bar's line about modified files (with `"manually"`) or, on the web, about files that can't
|
||||
be read comes first, followed by the line that counts the open's `warnings`; hovering it lists them as for any open.
|
||||
When the line about modified files follows the `missingLinks` dialog, it is followed by that dialog's `notes`.
|
||||
|
||||
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`,
|
||||
`modified`, `notes` (from `missingLinks`), `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
|
||||
|
||||
@@ -1652,6 +1652,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- On Windows, a document opened from a mapped network drive finds its links stored with the share's own path (`\\server\share\…`), as the same document opened from the share does; links on other computers stay missing.
|
||||
- On Windows, a link on a drive mapped to a network share other than the document's (`Y:\…`) is missing, with the reason that the path is on another computer, as a link stored with that share's own path is; links on this computer's drives and on the document's share are followed.
|
||||
- In the Links panel, Shift-click selects a range of links and Ctrl/Cmd-click adds or removes one.
|
||||
- When a document opens with notes and with linked files that changed on disk (Update Links: Manually) or, on the web, can't be read, the status bar shows the line about the linked files, then counts the notes and names the first, and hovering it lists the notes. The same holds when the line about modified files follows the Linked File Not Found dialog, and File › New from Template… shows the notes of the file it opens as File › Open does (`an_open_with_modified_links_keeps_link_notice_and_import_notes_reachable`, `new_from_template_preserves_open_warnings`, `an_open_with_unreadable_links_keeps_import_notes_reachable`, `modified_links_after_the_missing_ones_keep_the_open_notes`, `combined_open_and_link_status_lists_notes_on_hover_and_for_accessibility`).
|
||||
- Linked files another app changes while their document is open follow Preferences › File Handling › Update Links, as they do when it opens: Automatically reads them again (an Update Links undo step), Ask When Modified offers to, Manually leaves them modified in the Links panel. The desktop app compares the active document’s linked files by size and modification time every two seconds and when its window comes back to the front, on a worker thread; a file still being written is tried again (`links.updateChanged`).
|
||||
- A look at the linked files whose worker thread ends without a result, such as after a panic, no longer stops later looks: the app clears it, stops asking for a frame every 100 ms, and the next look starts on schedule (`crates/engine/src/tests/linkwatch.rs`, `crates/ui-egui/src/tests/place.rs`).
|
||||
- Import and paste, 2026-10-13: a multi-artboard `.ai` with notes beside its artboards opens from its editing data, a page's art past its artboard no longer lying over the page before it (#1528); a `.ai` gradient whose stops are listed upwards keeps each midpoint on the stop that starts its part of the ramp (#1530); SVG text on a path follows basic shapes (circle, ellipse, rect, line, polyline, polygon) as their SVG 2 equivalent paths (#1531, fixes #1527); PDFs whose alpha soft masks are drawn as images import with the mask instead of empty art (#1551); EPS and PostScript type set in Type 42 (TrueType) fonts imports at its size instead of 1000 times too large (#1553); PDF and EPS import keep a clipping path whose bounding box covers the page but whose shape doesn't (#1544, fixes #1542). Opening or placing a file with an image too large to decode says so, and the Links panel shows it on the row (#1540, part of #1479). Paste takes a PDF or EPS another app copied as editable vector art: from the macOS pasteboard (with SVG), EPS on Windows beside PDF, and `.eps` files copied in a file manager, with the new command `clipboard.importEps` (#1538, fixes #1499).
|
||||
|
||||
Reference in New Issue
Block a user