Refactor persistence: explicit save with live preview injection - #445
Conversation
Changes are no longer persisted on every input. Live CSS preview still updates instantly via injectLivePreview(); actual persistence (REST in WP mode, localStorage+hash in standalone) only happens when the user clicks Save or presses Ctrl+S. - persistence.ts: split persistOverrides into injectLivePreview (CSS-only) and saveOverrides (async explicit persist); remove debounce timer - App.svelte: track hasPendingChanges/saveState, wire handleSave + Ctrl+S - StudioHeader.svelte: add Save button with idle/saving/saved visual states Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MA1xz4tzW2uFeday7suPaG
|
Warning Review limit reached
Next review available in: 23 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 (3)
✨ 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 |
PR Summary by QodoRefactor overrides persistence: live preview injection + explicit Save flow Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
Context used✅ Compliance rules (platform):
6 rules 1.
|
Three bugs found by Qodo code review: 1. Undo/redo bypassed dirty state: hasPendingChanges was only set in setOverrides(), so handleUndo/handleRedo could change overrides without re-enabling the Save button after a clean save. 2. In-flight save race: handleSave() unconditionally cleared hasPendingChanges on completion, so edits made during the async REST call were silently marked clean. 3. setTimeout leak: the 2s saveState reset timer was never cancelled on component unmount. Fix: replace the hasPendingChanges boolean with a lastSavedSnapshot string and a $derived comparison against JSON.stringify(overrides). This makes dirty state react automatically to any overrides change (including undo/redo). In handleSave(), capture a snapshot string before the await and only update lastSavedSnapshot if overrides are still identical on completion. Store and clear the timer on unmount. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MA1xz4tzW2uFeday7suPaG
Summary
Refactor the persistence layer to separate live CSS preview (injected on every change) from explicit persistence (triggered only on user save). This gives users immediate visual feedback while maintaining control over when changes are actually saved to storage or the REST API.
Key Changes
Split persistence concerns:
persistOverrides()→injectLivePreview()(every change) +saveOverrides()(explicit save only)injectLivePreview()is now called in a reactive effect on every overrides changesaveOverrides()is an async function called only when user clicks Save or presses Ctrl+SAdd save state tracking in App.svelte:
hasPendingChanges: tracks whether there are unsaved modificationssaveState: tracks UI state ('idle' | 'saving' | 'saved')handleSave()Update StudioHeader with new Save button:
Simplify persistence.ts:
cancelPendingWpSave()and debounce timer logicpersistOverrides()functioninjectLivePreview()for reactive injectionsaveOverrides()as the explicit persistence entry pointImplementation Details
handleSave()logs warnings and resets to idle statehttps://claude.ai/code/session_01MA1xz4tzW2uFeday7suPaG