Skip to content

fix(file-preview): gate streaming animation to prevent file patch issue with scroll based re-render#4946

Merged
icecrasher321 merged 1 commit into
stagingfrom
fix/scroll-stream
Jun 10, 2026
Merged

fix(file-preview): gate streaming animation to prevent file patch issue with scroll based re-render#4946
icecrasher321 merged 1 commit into
stagingfrom
fix/scroll-stream

Conversation

@icecrasher321

Copy link
Copy Markdown
Collaborator

Summary

Stop streamed file previews from replaying the fade-in on already-visible text by stabilizing Streamdown's allowedTags identity and gating the per-char animation to from-scratch streams.

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 10, 2026 7:32pm

Request Review

@cursor

cursor Bot commented Jun 10, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Preview-only UI behavior in the file viewer; no auth, API, or data-path changes.

Overview
Fixes streamed markdown file previews replaying the per-character fade on text that is already on screen—especially during patch/in-place rewrites and scroll-driven re-renders.

useStreamAnimationGate turns Streamdown’s char animation on only for from-scratch streams (streaming starts with content length ≤ RESUME_SKIP_THRESHOLD, now exported from use-smooth-text so pacing and animation agree). The gate turns off when content updates are not appends (new string doesn’t start with the previous one), matching snapOnNonAppend behavior on smooth text reveal.

STREAMDOWN_ALLOWED_TAGS is a stable module-level allowedTags object instead of an inline literal, avoiding unnecessary identity churn on re-render.

Reviewed by Cursor Bugbot for commit 36ff136. Configure here.

@greptile-apps

greptile-apps Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes two sources of spurious re-animation in the file-preview panel: an unstable allowedTags object identity that caused Streamdown to re-render on every tick, and the per-character fade-in being applied to already-visible text during scroll-based re-renders or in-place patch rewrites.

  • STREAMDOWN_ALLOWED_TAGS is hoisted to module scope so the prop identity is stable across renders, eliminating unnecessary Streamdown remounts.
  • useStreamAnimationGate gates the STREAM_ANIMATION object to only fresh, from-scratch streams by tracking the isStreaming transition and latching off when a non-append content rewrite is detected mid-stream.
  • RESUME_SKIP_THRESHOLD is exported from use-smooth-text.ts so both the smooth-text hook and the new gate hook agree on what counts as "pre-existing" content.

Confidence Score: 5/5

Safe to merge — both changes are narrowly scoped to the file-preview streaming animation path and carry no risk to data or state persistence.

The STREAMDOWN_ALLOWED_TAGS hoisting is a straightforward referential-stability fix. The useStreamAnimationGate hook follows the same render-phase ref-mutation pattern already used by useSmoothText, the threshold is shared correctly via the new export, and the latch-off logic mirrors the snapOnNonAppend guard already in the smooth-text hook. No new state, no new network calls, and the change only affects animation — the worst case is a missing fade-in, not broken content.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/hooks/use-smooth-text.ts Exports RESUME_SKIP_THRESHOLD so the new animation-gate hook can share the same threshold; no logic changes to the hook itself.
apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx Adds STREAMDOWN_ALLOWED_TAGS module constant to stabilise the allowedTags prop identity, and introduces useStreamAnimationGate to gate the per-char fade-in to only fresh from-scratch streams, preventing replayed animation on scroll-based re-renders or in-place patch rewrites.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[New render: content, isStreaming] --> B{isStreaming changed?}
    B -- yes --> C{isStreaming = true AND\ncontent.length <= RESUME_SKIP_THRESHOLD?}
    C -- yes --> D[animateRef = true\nfresh stream from scratch]
    C -- no --> E[animateRef = false\nresume / pre-existing doc]
    B -- no --> F{isStreaming=true AND\nanimateRef=true AND\nnon-append content change?}
    F -- yes --> G[animateRef = false\npatch/rewrite detected — latch off]
    F -- no --> H[animateRef unchanged]
    D --> I[return isStreaming AND animateRef]
    E --> I
    G --> I
    H --> I
    I --> J{shouldAnimateStream?}
    J -- true --> K[Streamdown: animated=STREAM_ANIMATION]
    J -- false --> L[Streamdown: animated=false]
Loading

Reviews (1): Last reviewed commit: "fix(file-preview): gate streaming animat..." | Re-trigger Greptile

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 36ff136. Configure here.

@icecrasher321 icecrasher321 merged commit bc371b0 into staging Jun 10, 2026
14 checks passed
@icecrasher321 icecrasher321 deleted the fix/scroll-stream branch June 10, 2026 19:45
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