ZenNotes 2.45.0: the arrow keys work in the [[ picker again, and a remote vault stays current behind any proxy
Two fixes so far. In the main editor, ↑/↓ closed the
[[,@and/menus instead of moving through them (only the Ctrl chords worked), and a self-hosted vault reached through a proxy that does not pass WebSockets froze at connect time, so Move to Trash failed with "404 Not Found" for a note another device had already renamed.
🐛 Fixes
-
The arrow keys navigate the
[[,@and/menus again. (#707 by @ArditZubaku, closes #739 by @OmnivorousKumquat) In the main editor and the pinned reference pane, ↓ and ↑ moved the caret while a completion menu was open, and the caret move closed the menu, so the only way to pick an item was Ctrl+N/Ctrl+P or Ctrl+J/Ctrl+K. Quick Capture and the template editor happened to work, which is why the bug looked random. The completion keymap was spread last into the editor's general keymap at default precedence, behind the default keymap's own ArrowUp/ArrowDown; it is now mounted at highest precedence next to the Ctrl navigation, the way the autocomplete package mounts its own keymap. Verified in the built app with Vim on and off: the arrows move the highlight, the menu stays open, Enter inserts, and Esc still closes the picker without leaving insert mode. Alongside it, both docs surfaces now call the thing "the [[ wikilink picker" and list the movement keys, and the picker's own footer leads with them (↑/↓ or Ctrl+J/K to move · Enter inserts · Type | to change display text · /path/to/note for exact links), so the answer is on screen the moment it opens.How to test locally:
npm run buildthen launchapps/desktop/out/main/index.jswithZENNOTES_USER_DATA_PATHandZENNOTES_CONFIG_DIRon scratch folders, open a note, type[[, press ↓. Before: the menu closes and the caret moves down a line. After: the highlight moves to the second note, the menu stays open, Enter inserts it. Same for@and/. -
A remote vault behind a proxy without WebSockets stays current, and a stale note says so. (#734 by @mptpro, Linux desktop against a Docker server) Move to Trash on a remote vault failed from the desktop with "Remote server request failed (404 Not Found) for /api/notes/trash: not found", while the web and Android apps trashed fine against the same server. Every client sends the same request; the 404 is the server's "no such file", so the desktop was asking about a note that no longer lived at the path it showed. A remote vault hears about changes made elsewhere through one WebSocket,
/api/watch; a reverse proxy or tunnel that does not pass the Upgrade handshake fails every attempt, and the desktop kept a list frozen at connect time. Two changes, mirrored in the desktop and web clients: while the change feed cannot stay connected, the app re-pulls the vault every 30 seconds (and warns once in the console); and a 404 for a path the app asked to change now names it, says it was moved, renamed, or deleted from another device, and refreshes the list, so the stale row is gone by the time the toast is read. A 404 on a read keeps its plain answer, which is how remote databases learn a file is absent. The self-hosting docs say what a proxy needs for instant updates.How to test locally:
cd apps/server && go build -o /tmp/zennotes-server ./cmd/zennotes-server, start it withZENNOTES_BIND=127.0.0.1:7878 ZENNOTES_VAULT_PATH=/path/to/vault ZENNOTES_CONFIG_PATH=/tmp/zs.json ZENNOTES_AUTH_TOKEN=tok /tmp/zennotes-server, and put a proxy in front that forwards HTTP but ends upgrades (a 12-line Nodehttp.createServerwith anupgradehandler that writesHTTP/1.1 404is enough). Connect the desktop to the proxy URL, then rename a note from outside:curl -X POST -H 'Authorization: Bearer tok' -H 'Content-Type: application/json' -d '{"path":"inbox/Note.md","title":"Renamed"}' http://127.0.0.1:7878/api/notes/rename. Before: the desktop keeps "Note" forever, and Move to Trash on it fails with the 404 toast and the row stays. After: trashing the old row right away says "The server has nothing at inbox/Note.md any more: it was moved, renamed, or deleted from another device. The list has been refreshed." and the sidebar shows "Renamed"; leave it alone instead and the rename appears on its own within 30 seconds.
🧰 For contributors
completionKeymapExtensioninpackages/app-core/src/lib/cm-completion-nav.tsis the filtered completion keymap atPrec.highest; mount it next tocompletionNavKeymapinstead of spreadingcompletionKeymapForEditorinto akeymap.of([...]).cm-completion-nav-arrows.test.tsfails on the old wiring.packages/shared-domain/src/remote-workspace-messages.tsholdsstalePathMessage(path)andREMOTE_CHANGE_POLL_MS, shared by the desktopRemoteServerClient(newonStalePathoption,watchVaultChangesgainspollWhileDownMs) and the webhttp-bridge(RESYNC_EVENT,startWatchPolling). Desktop tests cover the polling fallback, the stale 404 message, and the untouched read 404 (#556).- The [[ picker footer text lives in
packages/app-core/src/styles/index.cssas a::aftercontent string.
Local-first and keyboard-first, as always.