[Frontend] Wiki draft review: the body autosave "Saved" indicator is wiped on the next render #539

Closed
opened 2026-09-06 20:21:30 +00:00 by claude-bot · 1 comment
Collaborator

Found while doing #182, which fixed the identical defect on the stat block autosave indicator in the same file and deliberately left this one alone.

In webapp/frontend/src/pages/WikiDraftReview.jsx (around line 411) the body autosave effect writes setSaveState(s => s === "saving" ? s : "idle") whenever the form is clean, and it re-runs on draft, which the successful save has just replaced. So "Saved" is set and overwritten with "idle" on the very next render: the autosave looks as though it did nothing, which is the one thing a silent background save must never look like. Since #182 the two indicators on that page disagree: the stat block's says "Saved" until the next edit, the body's still flashes.

Why it was not folded into #182: the compiler rule did not flag this effect (it bails, almost certainly because the dirtiness test reads lastSyncedRef.current), and fixing it honestly means promoting lastSyncedRef to state, which also changes isDirtyAgainst and the pre-approve flush in handleApprove. That is a real refactor of the autosave path with 24 tests around it, for a cosmetic gain, and belongs with the wiki-and-review lane of the v4.4.0 rebuild (#535 phase 5b), where the design system's async-progress pattern replaces both indicators anyway.

Acceptance:

  • After a body autosave lands, the indicator reads "Saved" until the next edit, matching the stat block's behaviour.
  • lastSyncedRef is state (or the dirtiness comparison is otherwise render-visible) so the compiler rule can analyse the effect; no eslint-disable.
  • The 24 existing tests pass unchanged; one new test asserts "Saved" persists across the re-render that follows setDraft.
Found while doing #182, which fixed the identical defect on the **stat block** autosave indicator in the same file and deliberately left this one alone. In `webapp/frontend/src/pages/WikiDraftReview.jsx` (around line 411) the body autosave effect writes `setSaveState(s => s === "saving" ? s : "idle")` whenever the form is clean, and it re-runs on `draft`, which the successful save has just replaced. So "Saved" is set and overwritten with "idle" on the very next render: the autosave looks as though it did nothing, which is the one thing a silent background save must never look like. Since #182 the two indicators on that page disagree: the stat block's says "Saved" until the next edit, the body's still flashes. Why it was not folded into #182: the compiler rule did not flag this effect (it bails, almost certainly because the dirtiness test reads `lastSyncedRef.current`), and fixing it honestly means promoting `lastSyncedRef` to state, which also changes `isDirtyAgainst` and the pre-approve flush in `handleApprove`. That is a real refactor of the autosave path with 24 tests around it, for a cosmetic gain, and belongs with the wiki-and-review lane of the v4.4.0 rebuild (#535 phase 5b), where the design system's async-progress pattern replaces both indicators anyway. Acceptance: - [ ] After a body autosave lands, the indicator reads "Saved" until the next edit, matching the stat block's behaviour. - [ ] `lastSyncedRef` is state (or the dirtiness comparison is otherwise render-visible) so the compiler rule can analyse the effect; no `eslint-disable`. - [ ] The 24 existing tests pass unchanged; one new test asserts "Saved" persists across the re-render that follows `setDraft`.
Author
Collaborator

Checked against main (2b077778), 2 October: moot. WikiDraftReview.jsx no longer exists; the page is webapp/frontend/src/pages/wiki/Draft.jsx (lane 8).

  • The indicator is derived, not stored, so there is nothing for a later render to wipe: Draft.jsx:756 const saveState = saving ? "saving" : saveFailed ? "failed" : dirty ? "dirty" : "saved";, and SaveLine shows "Saved at HH:MM" until the form is dirty again.
  • synced is state now, not lastSyncedRef, which is the refactor this issue asked for.
  • Covered by Draft.test.jsx "saves an edit to the draft by itself, and says so".

One thing not literally met: the autosave effect still carries an eslint-disable-next-line react-hooks/exhaustive-deps (the deps rule, not the compiler rule this issue named). Closing.

Checked against main (2b077778), 2 October: **moot**. `WikiDraftReview.jsx` no longer exists; the page is `webapp/frontend/src/pages/wiki/Draft.jsx` (lane 8). - The indicator is derived, not stored, so there is nothing for a later render to wipe: `Draft.jsx:756` `const saveState = saving ? "saving" : saveFailed ? "failed" : dirty ? "dirty" : "saved";`, and `SaveLine` shows "Saved at HH:MM" until the form is dirty again. - `synced` is state now, not `lastSyncedRef`, which is the refactor this issue asked for. - Covered by `Draft.test.jsx` "saves an edit to the draft by itself, and says so". One thing not literally met: the autosave effect still carries an `eslint-disable-next-line react-hooks/exhaustive-deps` (the deps rule, not the compiler rule this issue named). Closing.
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#539
No description provided.