Repository navigation
Description
Describe the bug
Two bugs in the PDF viewer's annotation editing (examples/pdf-server/src/mcp-app.ts, at 82221c0c).
1. Ctrl+Shift+Z never redoes. The keyboard handler (mcp-app.ts L3883) checks for a lowercase z:
if ((e.ctrlKey || e.metaKey) && e.key === "z") {
// ...
e.preventDefault();
if (e.shiftKey) {
redo();
} else {
undo();
}With Shift held, the browser reports e.key as "Z", so the condition is false whenever e.shiftKey is true: redo() can't be reached from the keyboard, and the viewer has no redo button.
2. A moved annotation that came from the PDF is never kept. Dragging an annotation that is already in the file (an imported one, such as a stamp) moves it on screen, and Ctrl+Z moves it back. Beyond that, all seen in Claude Desktop:
- The viewer doesn't count the move as a change: no
*before the file name and no Save button.computeDiff()(pdf-annotations.ts L315) returns only additions, removals and form edits. - Save doesn't write it: after a move and a new highlight, the saved file has the highlight, and the stamp at its old
/Rect.addAnnotationDicts()skips imported annotations, and its comment says "moving an imported annotation is still UI-only" (pdf-annotations.ts L527-L530). - Revert doesn't put it back: "Revert to what's in the PDF file" removes the highlight and leaves the stamp where it was dragged. The page scan puts the same
defobject into bothpdfBaselineAnnotationsandannotationMap(mcp-app.ts L2713 and L2716),applyMoveToDef()(L1508) changes that object in place, andresetToBaseline()(annotation-panel.ts L938) restores from that moved baseline. - A reload loses it: once the chat is scrolled until the viewer is far out of view and back, the stamp is back where the file has it, while the highlight is still there.
persistAnnotations()(mcp-app.ts L2745) stores only whatcomputeDiff()returns. get_screenshotshows it twice: where it was dragged and where the file has it, while the viewer on screen shows it once. After a move, the model sees a different page from the user.
Related: the header of pdf-annotations.ts (L8) says the stored changes hold "additions, removals, and modifications", but computeDiff() produces only additions and removals.
To Reproduce
Bug 1:
- Open a PDF in the viewer and add an annotation (a highlight, say).
- Press Ctrl+Z: the annotation goes away.
- Press Ctrl+Shift+Z: nothing happens.
Bug 2, with a PDF that already contains an annotation, such as a stamp:
- Drag the stamp somewhere else on the page: no
*before the file name, and no Save button. - Add a highlight, then save (we used
save_asto a new path, which builds the file the same way as the Save button): the file has the highlight, and the stamp at its old position. - Call
get_screenshotfor the page: the stamp appears twice. - Scroll the chat until the viewer is far out of view, then back: the stamp is back where the file has it, and the highlight is still there.
- Drag the stamp again, then click "Revert to what's in the PDF file" in the Annotations panel: the highlight goes, and the stamp stays where it was dragged.
Expected behavior
- Ctrl+Shift+Z redoes what Ctrl+Z undid. Comparing
e.key.toLowerCase() === "z"would do it, keepinge.shiftKeyto choose between undo and redo. - Either the move is saved (the annotation's
/Rectrewritten in place) and survives a reload, or the viewer doesn't let an imported annotation be dragged, or says the move won't be saved; Revert puts it back where the file has it; andget_screenshotshows the page the user sees.
Additional context
Seen in Claude Desktop 2.42304.0.0 on Windows 10 with pdf-viewer 2.0.0, which here carries the patches of the toolkit below; none of them touches the code bug 2 runs through. The handler for bug 1 is the same in 1.7.4 and 1.7.5. A fix for bug 1 that accepts "z" and "Z" is one of those patches, and with it Ctrl+Z undoes and Ctrl+Shift+Z redoes, Caps Lock on or off: https://github.com/tzipora-rose/pdf-local-read
Investigated and written in collaboration with Claudia in Claude Code.
Activity
pdf-server: make Ctrl/Cmd+Shift+Z redo in the viewer