improvement(rich-md-editor): streaming, performance, minor bugfixes#5148
improvement(rich-md-editor): streaming, performance, minor bugfixes#5148icecrasher321 wants to merge 12 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview
Rich markdown throttles full-document re-parses during large streams (~40KB+), and frontmatter is applied from the settled snapshot on change.
Reviewed by Cursor Bugbot for commit 6773fe9. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6773fe9. Configure here.
|
@greptile |
Greptile SummaryThis PR improves the rich-markdown streaming experience with smooth word-by-word pacing via
Confidence Score: 5/5Safe to merge. The changes are well-scoped, carefully commented, and backed by new unit tests. All core data paths (reconciliation, saves, dirty tracking) operate on the true reducer content, not the display-paced value. The streaming, pacing, and editor-lock changes are cleanly layered — text-editor-state.ts: the parallel reconciling path (lines 150-151) still evaluates Important Files Changed
Reviews (2): Last reviewed commit: "remove comments" | Re-trigger Greptile |
| if ( | ||
| isStreaming && | ||
| !prevIsStreamingRef.current && | ||
| content.length > RESUME_SKIP_THRESHOLD && | ||
| revealed < content.length | ||
| ) { | ||
| effectiveRevealed = content.length | ||
| revealedRef.current = content.length | ||
| setRevealed(content.length) | ||
| } | ||
| prevIsStreamingRef.current = isStreaming |
There was a problem hiding this comment.
setRevealed called during the render body
The new streaming-start snap (mirroring the existing snapOnNonAppend block below) calls setRevealed synchronously during the render phase, not inside a useEffect. React supports this derived-state pattern — it throws away the in-progress render and re-renders with the new state — but in React 18 concurrent mode, an interrupted render mutates prevIsStreamingRef.current before the committed render runs. If React discards the first render attempt and retries (e.g., a higher-priority update arrived), the ref is already set to isStreaming, so the committed render sees !prevIsStreamingRef.current === false and skips the snap even though revealed state is still 0. The net result is that the pre-existing document is paced from the beginning instead of snapping to full. This is an inherent limitation of the ref+setState-during-render pattern already used by snapOnNonAppend, so no new risk is introduced, but it is worth documenting why the correctness relies on there being no interleaved concurrent interruption between the two render attempts.
… on-screen for tall selections, restyle task-list checkbox
…ut while scrolling
A collapsed rail painted at the expanded width then animated to 51px on refresh: structure came from the cookie (server) while width came from independent cookie reads (blocking script + store), so any disagreement left the collapsed structure at the persisted expanded width until the store corrected it. Unify collapse into one derivation in WorkspaceChrome and drive the collapsed width from a server-rendered data-collapsed attribute via CSS (.sidebar-shell-outer[data-collapsed]) — the same cookie source as the structure, so width can never diverge from it. This is shadcn's documented pattern (data-attribute selectors over JS ternaries for collapsed dimensions). Also removes the redundant migratedCollapsed reconciliation (the store already seeds from the migrated cookie and hasHydrated flips in the same pre-paint effect) and the now-unused per-Sidebar derivation; Sidebar takes isCollapsed as a prop.
…obal command registry
… extract the shared toolbar button

Summary
Smooth streaming support, perf improvements, minor bugfixes
Type of Change
Testing
Tested manually
Checklist