Link the margin notes from the notes, and let them be hidden

The linking went the wrong way round. A remark in the margin is short by design;
when there is more to say about that passage it belongs in the notes beside the
document — and it has to be possible to say *which* passage. So the pins are
offered to the editor's `@` menu exactly like notes and notebooks are, labelled
with their page, and following one scrolls the document to the spot and opens the
remark. Pins are unhidden first: a link leading to something invisible would read
as broken.

A pin link is the same node with kind "pin", and is deliberately kept out of the
links reported to the server. Its target is a marker inside this note's own
overlay, so no note has that id, and reporting it would fill the backlink table
with rows matching nothing.

They can also be hidden altogether. Reading a document as it was printed is a
normal thing to want; the toolbar takes the markers and the column away together
and the page takes the width back.

The other direction — making a note out of a remark — is removed, along with its
picker and the pin's noteId: 357 lines fewer than before. The unmount flush it
turned up stays, since a drawing save was genuinely being dropped by navigating
away inside its debounce.

218 unit tests, 231 browser checks across eleven suites.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Opus 5 committed 2026-08-10 20:00:46 +02:00
1 parent 502aecfc92
commit 4c1b632029
13 files changed
+239 -484

No files matched your search

+16 -18
View File
@@ -304,7 +304,7 @@ failure distinguished by comparing an error's `.message` to a magic string.
Failures now carry a typed `SyncError.code`; `.message` still holds the same
string, so the remaining JavaScript callers are unaffected.
The 215 unit tests concentrate on the same places, and several exist because the
The 218 unit tests concentrate on the same places, and several exist because the
bug they cover actually happened:
- a queue entry that fails must stay queued, with an attempt counter
@@ -332,7 +332,7 @@ docker compose -f docker-compose.dev.yml up -d --build # must be running
| `search-attachments` | 12 | body-only matches, ranking, umlauts; images as blob URLs, not inline bytes |
| `history` | 10 | a large deletion is snapshotted, restoring works, restoring is itself undoable |
| `drawing` | 7 | strokes survive the poller, and match across four viewport widths |
| `pdf` | 80 | import, page proportions, lazy loading, and reading with the network off |
| `pdf` | 82 | import, page proportions, lazy loading, and reading with the network off |
| `attachments-lifecycle` | 10 | a picture is kept while any version shows it, and freed once none does |
| `conflict` | 10 | a late write wins but the state it buries survives as a version |
| `export` | 21 | the downloaded bytes are real Markdown, ZIP and PNG, unpacked and read back |
@@ -795,24 +795,22 @@ handling rather than assuming:
notes was therefore stored as `NULL` — every note on it lost on the next save.
Both now ask about strokes *and* pins.
**A remark can become a note of its own.** "Notiz anlegen" on a card makes one,
titles it from what was written, and goes there; the pin keeps its id, so the
passage leads to that note ever after. The note is created with a link back to
the document, so the connection reads in both directions and the document lists
it among its backlinks — a note born from a passage should not be a note with
nothing on it saying which passage. An existing note can be linked instead, and a
link can be let go of without touching the note.
**The margin notes can be linked from the notes.** A remark in the margin is
short by design; when there is more to say about that passage it belongs in the
notes beside the document — and it has to be possible to say *which* passage. So
the pins are offered to the editor's `@` menu exactly like notes and notebooks
are, labelled with their page, and following one scrolls the document to the spot
and opens the remark. They are unhidden first: a link that led to something
invisible would read as broken.
Two things had to be fixed for that to work at all, both of them older than the
feature:
A pin link is the same node with `kind: "pin"`, and is deliberately left out of
the links reported to the server. Its target is a marker inside this note's own
overlay, so no note has that id, and reporting it would fill the backlink table
with rows that match nothing.
- `openLinkTarget` finds a note's notebook by looking it up in the notes list,
and a note created in the same tick is not in the copy that callback closed
over — so jumping to it went nowhere. Creating one now navigates by the
notebook it already knows.
- A drawing save waits 700ms for the next stroke. Leaving the document inside
that window dropped it, which is exactly what turning a remark into a note
does. The viewer now flushes a pending write when it unmounts.
**They can be hidden.** Reading the document as it was printed is a normal thing
to want; the toolbar toggles the markers and the column together, and the page
takes the width back while they are away.
They come along when the document is exported with annotations: each becomes a
numbered marker plus a small box with its text, placed on whichever side of the