[Frontend] Shelf tonight-notes: the auto-save debounce is cancelled on unmount without flushing #536

Closed
opened 2026-09-06 20:03:13 +00:00 by claude-bot · 2 comments
Collaborator

Found while doing #464.

TonightNotes in webapp/frontend/src/pages/SessionShelf.jsx (around lines 234–236) auto-saves on a 1.5 s debounce (#410) and clears the pending timer on unmount without flushing it. Navigating away within 1.5 s of the last keystroke therefore loses those characters today: the timer is cancelled, the save never fires, and nothing asks.

Adding the new in-app prompt (useUnsavedChangesPrompt, #464) there would only surface the loss, not prevent it: accepting the confirm still discards. The right fix is to flush the pending save on unmount (and on beforeunload, with navigator.sendBeacon or a synchronous path if the API allows), after which the prompt becomes near-unreachable on that field and is not needed.

Severity: low in practice (the window is 1.5 s, the field is a GM's live notes), but it is a genuine data-loss path in a milestone line whose promise is that data is never lost.

Acceptance:

  • Unmounting TonightNotes with a pending debounce writes the pending text before the component goes away.
  • A test that types, navigates within the debounce window, and asserts the save request was made with the final text; confirmed to fail without the flush.
  • BeatNotesEditor (:59) is a straightforward candidate for useUnsavedChangesPrompt if wanted; decide in the same change.
Found while doing #464. `TonightNotes` in `webapp/frontend/src/pages/SessionShelf.jsx` (around lines 234–236) auto-saves on a 1.5 s debounce (#410) and clears the pending timer on unmount **without flushing it**. Navigating away within 1.5 s of the last keystroke therefore loses those characters today: the timer is cancelled, the save never fires, and nothing asks. Adding the new in-app prompt (`useUnsavedChangesPrompt`, #464) there would only surface the loss, not prevent it: accepting the confirm still discards. The right fix is to flush the pending save on unmount (and on `beforeunload`, with `navigator.sendBeacon` or a synchronous path if the API allows), after which the prompt becomes near-unreachable on that field and is not needed. Severity: low in practice (the window is 1.5 s, the field is a GM's live notes), but it is a genuine data-loss path in a milestone line whose promise is that data is never lost. Acceptance: - [ ] Unmounting `TonightNotes` with a pending debounce writes the pending text before the component goes away. - [ ] A test that types, navigates within the debounce window, and asserts the save request was made with the final text; confirmed to fail without the flush. - [ ] `BeatNotesEditor` (`:59`) is a straightforward candidate for `useUnsavedChangesPrompt` if wanted; decide in the same change.
Author
Collaborator

Checked against main (2b077778), 2 October: still there, in the rebuilt component. webapp/frontend/src/pages/table/TonightNotes.jsx (used by Stage.jsx and TableCard.jsx) clears its debounce timer on unmount without sending. Blur now saves at once and beforeunload asks on a tab close, but neither covers the field leaving the page inside the app: the opened card closing, or the stage moving to another card (it is keyed by the card).

The other editor this issue named, the prep Beats editor, is fine: it sits inside pages/prep/useSheet.js, which sends on unmount.

Picking it up: branch fix/536-tonight-notes-flush-on-unmount. The clean-up sends a waiting save to the card it was typed on; new TonightNotes.test.jsx (unmount inside the debounce, a change of card, nothing waiting, typed and put back, the debounce still saving by itself).

Checked against main (2b077778), 2 October: **still there**, in the rebuilt component. `webapp/frontend/src/pages/table/TonightNotes.jsx` (used by `Stage.jsx` and `TableCard.jsx`) clears its debounce timer on unmount without sending. Blur now saves at once and `beforeunload` asks on a tab close, but neither covers the field leaving the page inside the app: the opened card closing, or the stage moving to another card (it is keyed by the card). The other editor this issue named, the prep Beats editor, is fine: it sits inside `pages/prep/useSheet.js`, which sends on unmount. Picking it up: branch `fix/536-tonight-notes-flush-on-unmount`. The clean-up sends a waiting save to the card it was typed on; new `TonightNotes.test.jsx` (unmount inside the debounce, a change of card, nothing waiting, typed and put back, the debounce still saving by itself).
Author
Collaborator

Done in PR #1035, merged to main on 2026-10-02 after its CI re-run went green (the first run's red was the runner's disk filling, not the change).

TonightNotes.jsx now sends a waiting save from its unmount clean-up, to the card it was typed on, and sends nothing when nothing is waiting or the text is back as it was. Five new tests in TonightNotes.test.jsx; the browser checks are in the PR body. No follow-ups.

Done in PR #1035, merged to main on 2026-10-02 after its CI re-run went green (the first run's red was the runner's disk filling, not the change). `TonightNotes.jsx` now sends a waiting save from its unmount clean-up, to the card it was typed on, and sends nothing when nothing is waiting or the text is back as it was. Five new tests in `TonightNotes.test.jsx`; the browser checks are in the PR body. No follow-ups.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rbrooks/Quest-Board#536
No description provided.