Skip to content

Scroll jump 160426#2291

Merged
simo6529 merged 4 commits into
mainfrom
scroll-jump-160426
Apr 17, 2026
Merged

Scroll jump 160426#2291
simo6529 merged 4 commits into
mainfrom
scroll-jump-160426

Conversation

@simo6529
Copy link
Copy Markdown
Collaborator

@simo6529 simo6529 commented Apr 17, 2026

Summary by CodeRabbit

  • New Features

    • Implemented hydration suspension for light-drop data fetching during active scrolling and target-based operations, improving performance and stability when navigating large drop lists.
  • Tests

    • Added comprehensive test coverage for serial target hydration suspension behavior during fetch and reveal operations.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

📝 Walkthrough

Walkthrough

The PR introduces a light-drop hydration suspension mechanism that prevents fetching LIGHT-type drops when the component is actively scrolling or tracking an active serial target. A new suspendLightDropHydration prop is threaded through the drops hierarchy and conditionally prevents IntersectionObserver-triggered fetches in VirtualScrollWrapper. Supporting changes update serial scroll tracking with new async state management and ref handling.

Changes

Cohort / File(s) Summary
Test Suite
__tests__/components/waves/drops/WaveDropsAll.test.tsx
Added three new tests validating suspendLightDropHydration behavior: hydration suspension during LIGHT target fetch rejection, release after failed reveal, and release after scroll settle timeout.
Hydration Suspension Prop Threading
components/drops/view/DropsList.tsx, components/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsx, components/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsx
Added optional suspendLightDropHydration prop and forwarded it through the component hierarchy to reach VirtualScrollWrapper.
IntersectionObserver Conditional Logic
components/waves/drops/VirtualScrollWrapper.tsx
Added suspendLightDropHydration prop; LIGHT fetch via fetchAroundSerialNo now only triggers when element is in view AND suspension is not enabled. Extended effect dependency list to include suspension flag and related parameters.
Serial Scroll Async State Management
components/waves/drops/wave-drops-all/hooks/useWaveDropsSerialScroll.ts
Refactored ref types from MutableRefObject to RefObject; introduced activeScrollTargetRef for in-flight tracking; added clearSerialTargetIfCurrent() for conditional target clearing; updated fetchAndScrollToDrop to capture active serial state and handle failed reveals; enhanced effect cleanup to manage pending settle timeouts.
Scroll State Coordination
components/waves/drops/wave-drops-all/index.tsx
Wired suspendLightDropHydration prop to WaveDropsContent, enabling suspension when actively scrolling or tracking a serial target.
Configuration
config/nextConfig.ts
Updated allowed dev origin IP from 192.168.1.133 to 172.20.10.3.

Sequence Diagram(s)

sequenceDiagram
    participant WaveDropsAll as WaveDropsAll
    participant VirtualScrollWrapper as VirtualScrollWrapper
    participant IntersectionObserver as IntersectionObserver
    participant FetchAPI as Fetch Service

    WaveDropsAll->>WaveDropsAll: Determine suspendLightDropHydration<br/>(isScrolling || serialTarget !== null)
    WaveDropsAll->>VirtualScrollWrapper: Pass suspendLightDropHydration prop

    VirtualScrollWrapper->>IntersectionObserver: Register element with observer

    Note over IntersectionObserver: Element enters viewport
    IntersectionObserver->>IntersectionObserver: Check: isInView && !suspendLightDropHydration

    alt Not Suspended (isInView && !suspendLightDropHydration)
        IntersectionObserver->>FetchAPI: Call fetchAroundSerialNo(waveId, dropSerialNo)
        FetchAPI-->>IntersectionObserver: Fetch response
    else Suspended (isInView && suspendLightDropHydration)
        IntersectionObserver->>IntersectionObserver: Skip fetch - hydration suspended
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • PR #1866: Both PRs modify useWaveDropsSerialScroll.ts hook, updating serial-target tracking and scroll/fetch/reveal control flow.
  • PR #2137: Both PRs update IntersectionObserver dependency handling and effect wiring across wave drops components.
  • PR #2130: Both PRs modify wave drops components (WaveDropsAll, WaveDropsContent, WaveDropsMessageListSection) and related scroll/reveal behavior tests.

Suggested reviewers

  • ragnep
  • prxt6529

Poem

🐰 A rabbit hops through drops of light,
Suspending fetches mid-scroll flight,
When active targets dance in sight,
No hydration blooms—just smooth delight,
✨ The observer now bows polite!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Scroll jump 160426' is vague and does not clearly convey the main purpose of the changeset. While it may reference an issue number, it lacks descriptive information about what changes are being made. Consider using a more descriptive title that summarizes the main change, such as 'Suspend light drop hydration during scroll target operations' or 'Add hydration suspension for scroll-to-target flow'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch scroll-jump-160426

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Apr 17, 2026

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarQube Cloud

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 53072cc7f9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@simo6529
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/waves/drops/VirtualScrollWrapper.tsx (1)

111-158: ⚠️ Potential issue | 🟡 Minor

fetchAroundSerialNo has stable identity; queuing prevents duplicate requests for the same serial.

Two observations on the expanded effect:

  1. Effect churn is not a concern: fetchAroundSerialNo is wrapped in useCallback with dependencies [cancelAbort, _processAroundSerialNoQueue], both of which are themselves useCallback-wrapped with stable or empty dependencies. The transitive chain is solid—the effect won't unnecessarily rebuild due to function identity changes.

  2. Duplicate fetches are mostly mitigated: The useWavePagination queuing system (in _processAroundSerialNoQueue) prevents re-fetching the same (waveId, serialNo) pair:

    • Only one fetch per waveId runs concurrently (guarded by isFetching).
    • Subsequent calls for the same serial are coalesced to the latest pending request.
    • The determineSerialToFetch function avoids redundant fetches by checking the last successfully fetched range.

    However, when suspendLightDropHydration transitions true → false, the observer recreates and fires callbacks for all in-view LIGHT drops. If multiple drops have different serial numbers, each triggers its own fetch. This is likely intentional (independent content), but confirm that the concurrent request rate is acceptable downstream. No test coverage exists for this toggle scenario.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/waves/drops/VirtualScrollWrapper.tsx` around lines 111 - 158, The
effect can fire many LIGHT-drop fetches when suspendLightDropHydration flips
from true→false; add a small debounce/batch guard in VirtualScrollWrapper's
useEffect so inView && type === DropSize.LIGHT calls to fetchAroundSerialNo are
coalesced briefly (e.g., microtask/setTimeout 50–100ms) before invoking
fetchAroundSerialNo, or gate calls behind a per-wave "hydrationResumed" flag to
avoid simultaneous spikes; also add a test covering the
suspendLightDropHydration toggle to assert that useWavePagination's
queue/_processAroundSerialNoQueue handles the burst without duplicate work and
that fetchAroundSerialNo is only called once per unique (waveId, dropSerialNo)
within the debounce window.
🧹 Nitpick comments (1)
components/drops/view/DropsList.tsx (1)

274-296: Consider only forwarding the flag to LIGHT drops.

suspendLightDropHydration is forwarded to every VirtualScrollWrapper (FULL and LIGHT) and is part of the wrapper's useEffect deps. Each flip of the flag therefore tears down and recreates the IntersectionObserver for every drop in the list, even FULL drops where the flag has no effect. For long conversations with hundreds of items, each target-scroll (flag goes true → false on settle) incurs 2×N observer recreations.

Minor win — only pay the dep-churn cost where it's meaningful:

♻️ Proposed refactor
           <VirtualScrollWrapper
             scrollContainerRef={getItemData.scrollContainerRef}
             dropSerialNo={drop.serial_no}
             waveId={drop.type === DropSize.FULL ? drop.wave.id : drop.waveId}
             type={drop.type}
-            suspendLightDropHydration={suspendLightDropHydration}
+            suspendLightDropHydration={
+              drop.type === DropSize.LIGHT ? suspendLightDropHydration : false
+            }
           >

This keeps the flag stable (false) for FULL drops so their observer effect isn't invalidated when suspension toggles.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/drops/view/DropsList.tsx` around lines 274 - 296, The
suspendLightDropHydration flag is being passed to every VirtualScrollWrapper
causing its useEffect (and IntersectionObserver) to tear down/recreate for all
drops; only LIGHT drops need this prop. Change the prop passed to
VirtualScrollWrapper so it evaluates to suspendLightDropHydration only when
drop.type === DropSize.LIGHT (otherwise pass a stable false), i.e. update the
component invocation around VirtualScrollWrapper to compute the prop per-drop
and avoid forwarding suspendLightDropHydration for FULL drops; this keeps
VirtualScrollWrapper's deps stable for FULL drops and prevents unnecessary
observer churn.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@config/nextConfig.ts`:
- Line 17: The commit replaced a shared dev IP in the allowedDevOrigins array
with a personal hotspot address; revert this accidental change by restoring the
original entry (replace "172.20.10.3" with the prior "192.168.1.133") or,
better, change allowedDevOrigins to load from an environment variable (e.g.,
parse process.env.ALLOWED_DEV_ORIGINS as a comma-separated list with a safe
default array) so individual developer LAN IPs are not committed; update the
variable/constant named allowedDevOrigins accordingly and ensure any type/format
expectations still hold where allowedDevOrigins is used.

---

Outside diff comments:
In `@components/waves/drops/VirtualScrollWrapper.tsx`:
- Around line 111-158: The effect can fire many LIGHT-drop fetches when
suspendLightDropHydration flips from true→false; add a small debounce/batch
guard in VirtualScrollWrapper's useEffect so inView && type === DropSize.LIGHT
calls to fetchAroundSerialNo are coalesced briefly (e.g., microtask/setTimeout
50–100ms) before invoking fetchAroundSerialNo, or gate calls behind a per-wave
"hydrationResumed" flag to avoid simultaneous spikes; also add a test covering
the suspendLightDropHydration toggle to assert that useWavePagination's
queue/_processAroundSerialNoQueue handles the burst without duplicate work and
that fetchAroundSerialNo is only called once per unique (waveId, dropSerialNo)
within the debounce window.

---

Nitpick comments:
In `@components/drops/view/DropsList.tsx`:
- Around line 274-296: The suspendLightDropHydration flag is being passed to
every VirtualScrollWrapper causing its useEffect (and IntersectionObserver) to
tear down/recreate for all drops; only LIGHT drops need this prop. Change the
prop passed to VirtualScrollWrapper so it evaluates to suspendLightDropHydration
only when drop.type === DropSize.LIGHT (otherwise pass a stable false), i.e.
update the component invocation around VirtualScrollWrapper to compute the prop
per-drop and avoid forwarding suspendLightDropHydration for FULL drops; this
keeps VirtualScrollWrapper's deps stable for FULL drops and prevents unnecessary
observer churn.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3373d668-452c-4c4b-a4f8-a4ec4ae85f2b

📥 Commits

Reviewing files that changed from the base of the PR and between 593a202 and 53072cc.

📒 Files selected for processing (8)
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • components/drops/view/DropsList.tsx
  • components/waves/drops/VirtualScrollWrapper.tsx
  • components/waves/drops/wave-drops-all/hooks/useWaveDropsSerialScroll.ts
  • components/waves/drops/wave-drops-all/index.tsx
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsx
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsx
  • config/nextConfig.ts

Comment thread config/nextConfig.ts
@simo6529 simo6529 merged commit 7b94e57 into main Apr 17, 2026
8 checks passed
@simo6529 simo6529 deleted the scroll-jump-160426 branch April 17, 2026 10:59
@coderabbitai coderabbitai Bot mentioned this pull request May 8, 2026
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.

2 participants