Skip to content

fix(study-library): stop doc-slide cross-slide bleed + data loss on fast slide-switch - #2117

Open
neerajhariyale wants to merge 3 commits into
mainfrom
fix/doc-slide-rapid-switch-bleed
Open

fix(study-library): stop doc-slide cross-slide bleed + data loss on fast slide-switch#2117
neerajhariyale wants to merge 3 commits into
mainfrom
fix/doc-slide-rapid-switch-bleed

Conversation

@neerajhariyale

Copy link
Copy Markdown
Contributor

Problem

The doc-slide editor is one shared Yoopta instance reused across slides. Switching slides fast let the auto-save-on-switch read the live editor after it had already loaded the incoming slide, writing one slide's body into the outgoing slide's DB row.

Confirmed prod case: the film "Lesson 1" content overwrote an unrelated "Document 2" slide (both draft + published), destroying Document 2's own content.

Fix

  • editorLoadedSlideIdRef — tracks which slide the shared editor actually holds; set synchronously right after every setEditorValue.
  • decideSwitchSave() (new pure, unit-tested guard) — both switch-save triggers route through it: save the live editor only when it still holds the outgoing slide; else fall back to that slide's last clean snapshot; else skip — never persist another slide's content.
  • All fallback-cache writers gated against empty/degraded content.
  • Removed legacy handleUnsavedDocIfNeeded (read the live editor without the guard — a latent bleed).
  • Disabled editor autoFocus to stop the Slate mount-focus crash.

Tests

switchSaveGuard.test.ts — 18 cases incl. the exact prod bleed, an exhaustive (previous × editorLoaded × cacheOwner) invariant sweep, degraded-never-cached, and a 5000-op fuzz. Verified green against the compiled logic.

Deploy note

Data loss on prod continues until this is merged AND the admin dashboard is redeployed.

🤖 Generated with Claude Code

…itch

Shared Yoopta editor is reused across slides; switching fast let the
auto-save-on-switch read the live editor after it had loaded the incoming
slide, writing one slide's body into the outgoing slide's row (e.g. film
'Lesson 1' overwrote an unrelated 'Document 2').

- Track the slide the editor actually holds (editorLoadedSlideIdRef).
- Route both switch-save triggers through decideSwitchSave() (pure, tested):
  save live only when the editor still holds the outgoing slide, else use
  that slide's last clean snapshot, else skip -- never persist another
  slide's content.
- Gate all fallback-cache writers against empty/degraded content.
- Remove legacy handleUnsavedDocIfNeeded (read live editor w/o guard).
- Disable editor autoFocus to stop the Slate mount-focus crash.

Adds switchSaveGuard.test.ts (18 cases incl. the prod bleed + fuzz).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codacy-production

Copy link
Copy Markdown
Contributor

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 55 complexity

Metric Results
Complexity 55

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 3, 2026

Copy link
Copy Markdown

Deploying frontend-admin-dashboard with  Cloudflare Pages  Cloudflare Pages

Latest commit: c0ca1b3
Status: ✅  Deploy successful!
Preview URL: https://d5ecb3bd.frontend-admin-dashboard.pages.dev
Branch Preview URL: https://fix-doc-slide-rapid-switch-b.frontend-admin-dashboard.pages.dev

View logs

neerajhariyale and others added 2 commits July 3, 2026 23:39
pick() returned T | undefined; assert the in-range index so it types as T.
Fixes the admin tsc build failure. Full project tsc now passes (0 errors).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…SYNC)

The Yoopta editor instance is shared across slides, so its undo stack
survived slide switches. Pressing Cmd+Z on the newly-loaded slide rewound
into the PREVIOUS slide's operations (or undid the setEditorValue load),
changing the current slide's content and flipping it to UNSYNC. Reset
editor.historyStack after every content load so undo is scoped to the
current slide's own edits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant