fix(ui): stop page autosave from resetting the editor and crossing pages#322
fix(ui): stop page autosave from resetting the editor and crossing pages#322cavidelizade wants to merge 1 commit into
Conversation
Two problems in the page editor's autosave: 1. usePageEditor reseeded whenever initialHtml changed by exact-string inequality. After each body autosave, saveBodyNow fed the server's description_html back as initialHtml, so any normalization difference (or a keystroke landing during the ~1.5s save) reset the document and jumped the caret. Mirror DescriptionEditor's guard: compare normalized HTML and skip when the incoming value is what we last synced. The parent now also seeds the editor from a dedicated seedHtml that only changes on genuine document swaps (load, route change, version restore), never from an autosave round-trip. 2. The body/title debounce timers were cleared only on unmount. Navigating /pages/A -> /pages/B reused the component, so A's pending save could fire and its setPage() overwrite B's header/body. Flush the pending saves when the page identity changes (keyed on workspace/project/pageId) and guard saveBodyNow/saveTitleNow so an in-flight save that resolves after navigation doesn't touch the new page's state. Closes Devlaner#317 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 20 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@martian56 this fixes #317 — the page autosave was reseeding the editor on its own save round-trip (caret jumps / the odd dropped keystroke), and a pending save could fire against the wrong page after you navigated. One heads-up: I verified this with typecheck + lint and traced the logic carefully, but my local dev stack was down so I couldn't click through it live. If you can give the three flows in the PR description a quick manual pass before merging I'd appreciate it — happy to adjust if anything's off. |
Summary
Two related bugs in the page editor's autosave.
Linked issues
Closes #317
Type of change
fix:)Surface
apps/web/)What changed
1. Autosave round-trip reset the editor / jumped the caret.
usePageEditorreseeded wheneverinitialHtmlchanged by exact string inequality. After each body autosave,saveBodyNowfed the server'sdescription_htmlback asinitialHtml, so any normalization difference — or a keystroke landing during the ~1.5s save — reset the document and moved the cursor.DescriptionEditor's guard: compare normalized HTML and skip when the incoming value is what we last synced.seedHtmlstate that changes only on a genuine document swap (load, route change, version restore), never from an autosave round-trip.2. A pending save could cross pages.
The debounce timers were cleared only on unmount. Navigating
/pages/A → /pages/Breuses the component, so A's pending save could fire and itssetPage()overwrite B's header/body.workspace/project/pageId) so last-second edits aren't dropped.saveBodyNow/saveTitleNowwith apageRefso an in-flight save that resolves after navigation persists server-side but doesn't touch the newly-opened page's state.Why this approach
The root cause of (1) is that the editor's seed was coupled to the continuously-updated page body. Decoupling it (
seedHtml) means the only thing that can reseed the editor is an intentional document change — the normalize guard is then belt-and-suspenders. For (2), flushing on the identity change preserves edits and the route guard is what actually prevents the cross-page write.Test plan
npm run typecheck+npm run lint(with the i18n gate) passFlagging that I verified this by type-checking, linting and tracing the logic, but did not exercise it in a running app — worth a manual pass on the three flows above before merge.
AI assistance
Claude Code (Opus 4.8)— commits carry aCo-Authored-By:trailer