Conversation
WalkthroughThis PR adds an Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant WaveDrops as Wave Drops UI
participant useDeviceInfo as useDeviceInfo Hook
participant Backend
User->>WaveDrops: Open wave (on mobile)
WaveDrops->>useDeviceInfo: query isAppleMobile
useDeviceInfo-->>WaveDrops: true
Backend-->>WaveDrops: New drops arrive while user scrolled up
WaveDrops->>WaveDrops: Increment pendingDropsCount<br/>Filter from renderedWaveMessages
WaveDrops->>User: Show badge "N new messages"
User->>WaveDrops: Click reveal button
WaveDrops->>WaveDrops: Set visibleLatestSerial to newest<br/>Call revealPendingDrops
WaveDrops->>User: Render pending drops<br/>Scroll to bottom
sequenceDiagram
participant Component as useScrollBehavior
participant RAF as requestAnimationFrame
participant DOM as DOM refs
participant Observer as IntersectionObserver
Component->>RAF: schedule setupObserver
RAF->>DOM: check refs
alt refs not ready
RAF->>RAF: retry next frame (loop)
else refs ready
RAF->>Observer: create & observe
Component->>Component: attach scroll listener and call handleScroll
end
Component->>Component: unmount
Component->>Observer: disconnect
Component->>RAF: cancel pending RAF
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
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 |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx (1)
31-36: Avoid duplicating type definitions in tests.The local
DeviceInfotype definition duplicates the interface fromhooks/useDeviceInfo.ts. If the interface changes, this test will need manual updates.Import the type from the source instead:
+import useDeviceInfo, { type DeviceInfo } from '@/hooks/useDeviceInfo'; -import useDeviceInfo from '@/hooks/useDeviceInfo'; -type DeviceInfo = { - isApp: boolean; - isMobileDevice: boolean; - hasTouchScreen: boolean; - isAppleMobile: boolean; -}; const useDeviceInfoMock = useDeviceInfo as jest.MockedFunction<typeof useDeviceInfo>;Note: This assumes
DeviceInfois exported from the hook. If not, consider exporting it to improve type reusability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx(2 hunks)__tests__/components/header/HeaderSearchModal.test.tsx(1 hunks)__tests__/components/waves/drops/WaveDropsAll.test.tsx(6 hunks)__tests__/components/waves/drops/WaveDropsScrollBottomButton.test.tsx(1 hunks)__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx(1 hunks)__tests__/hooks/useDeviceInfo.test.ts(3 hunks)app/open-mobile/page.client.tsx(2 hunks)components/cookies/CookiesBanner.tsx(1 hunks)components/waves/drops/WaveDropsScrollBottomButton.tsx(1 hunks)components/waves/drops/wave-drops-all/index.tsx(7 hunks)components/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsx(3 hunks)components/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsx(3 hunks)hooks/useDeviceInfo.ts(3 hunks)hooks/useScrollBehavior.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx}: Do not include any comments in the code
Use react-query for data fetching
Always add readonly before props
Files:
__tests__/components/header/HeaderSearchModal.test.tsxhooks/useScrollBehavior.ts__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsxcomponents/waves/drops/wave-drops-all/index.tsxcomponents/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsxcomponents/cookies/CookiesBanner.tsx__tests__/components/waves/drops/WaveDropsScrollBottomButton.test.tsxapp/open-mobile/page.client.tsxcomponents/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsxcomponents/waves/drops/WaveDropsScrollBottomButton.tsx__tests__/hooks/useDeviceInfo.test.ts__tests__/components/waves/drops/WaveDropsAll.test.tsxhooks/useDeviceInfo.ts__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursorrules)
**/*.tsx: Use FontAwesome for icons
Use TailwindCSS for styling
Files:
__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsxcomponents/waves/drops/wave-drops-all/index.tsxcomponents/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsxcomponents/cookies/CookiesBanner.tsx__tests__/components/waves/drops/WaveDropsScrollBottomButton.test.tsxapp/open-mobile/page.client.tsxcomponents/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsxcomponents/waves/drops/WaveDropsScrollBottomButton.tsx__tests__/components/waves/drops/WaveDropsAll.test.tsx__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
__tests__/**
📄 CodeRabbit inference engine (tests/AGENTS.md)
Place Jest test suites under the
__tests__directory mirroring source folders (e.g., components, contexts, hooks, utils)
Files:
__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx__tests__/components/waves/drops/WaveDropsScrollBottomButton.test.tsx__tests__/hooks/useDeviceInfo.test.ts__tests__/components/waves/drops/WaveDropsAll.test.tsx__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
__tests__/components/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use
@testing-library/reactand@testing-library/user-eventfor React component tests
Files:
__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx__tests__/components/waves/drops/WaveDropsScrollBottomButton.test.tsx__tests__/components/waves/drops/WaveDropsAll.test.tsx
{app,pages}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Use NextJS features that match the current version
Files:
app/open-mobile/page.client.tsx
🧠 Learnings (11)
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Keep mock implementations minimal—only what’s necessary for the test scenarios
Applied to files:
__tests__/components/header/HeaderSearchModal.test.tsx__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx__tests__/components/waves/drops/WaveDropsAll.test.tsx__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Document non-obvious expected behaviour directly in the mock file
Applied to files:
__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx__tests__/components/waves/drops/WaveDropsAll.test.tsx__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Keep mocks up to date with the real implementations they represent
Applied to files:
__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx__tests__/components/waves/drops/WaveDropsAll.test.tsx__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Mock only external dependencies or heavy functionality; avoid over-mocking internal logic
Applied to files:
__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx__tests__/components/waves/drops/WaveDropsAll.test.tsx__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/*.{test,spec}.{js,jsx,ts,tsx} : In tests, use jest.mock('module') with a bare module specifier to load the corresponding manual mock
Applied to files:
__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx__tests__/components/waves/drops/WaveDropsAll.test.tsx__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Use Jest’s built-in mocking for module replacement; keep manual mocks simple and lightweight
Applied to files:
__tests__/components/waves/drops/WaveDropsAll.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Organise mocks to mirror the real module structure so import paths remain consistent
Applied to files:
__tests__/components/waves/drops/WaveDropsAll.test.tsx__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Name mock files to mirror the real module names so jest.mock('module') can pick them up automatically
Applied to files:
__tests__/components/waves/drops/WaveDropsAll.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Place manual mock modules under a __mocks__ directory so Jest can auto-resolve them
Applied to files:
__tests__/components/waves/drops/WaveDropsAll.test.tsx
📚 Learning: 2025-09-28T12:33:30.950Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:30.950Z
Learning: Applies to __tests__/components/**/*.{ts,tsx,js,jsx} : Use `testing-library/react` and `testing-library/user-event` for React component tests
Applied to files:
__tests__/components/waves/drops/WaveDropsAll.test.tsx
📚 Learning: 2025-09-28T12:33:07.561Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-09-28T12:33:07.561Z
Learning: Applies to __mocks__/**/__mocks__/**/*.{js,jsx,ts,tsx} : Review mocks periodically and remove unused mock modules
Applied to files:
__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
🧬 Code graph analysis (6)
__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx (1)
hooks/useDeviceInfo.ts (1)
useDeviceInfo(23-95)
components/waves/drops/wave-drops-all/index.tsx (1)
hooks/useDeviceInfo.ts (1)
useDeviceInfo(23-95)
components/cookies/CookiesBanner.tsx (2)
hooks/useDeviceInfo.ts (1)
useDeviceInfo(23-95)hooks/isMobileDevice.ts (1)
useIsMobileDevice(5-18)
__tests__/components/waves/drops/WaveDropsScrollBottomButton.test.tsx (1)
components/waves/drops/WaveDropsScrollBottomButton.tsx (1)
WaveDropsScrollBottomButton(10-73)
app/open-mobile/page.client.tsx (2)
app/open-mobile/page.tsx (1)
OpenMobilePage(5-7)hooks/useDeviceInfo.ts (1)
useDeviceInfo(23-95)
__tests__/components/waves/drops/WaveDropsAll.test.tsx (1)
__tests__/utils/editDropTestUtils.tsx (1)
createMockDrop(5-39)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (22)
hooks/useDeviceInfo.ts (1)
55-55: Apple mobile detection logic is correct.The implementation correctly identifies Apple mobile devices by checking UA patterns for iPhone/iPad/iPod and handling the edge case where iPads masquerade as Macintosh in desktop mode.
hooks/useScrollBehavior.ts (2)
80-121: Robust observer initialization with deferred setup.The RAF-based approach ensures the Intersection Observer is only created once both refs are available, preventing race conditions during component mount. Cleanup properly cancels pending RAF and disconnects the observer.
123-151: Robust scroll listener attachment with deferred setup.The deferred attachment pattern with RAF ensures the scroll listener is only added once the container is available, and the initial
handleScroll()call ensures state reflects the current scroll position. Cleanup is comprehensive.__tests__/components/header/HeaderSearchModal.test.tsx (1)
141-146: Mock updated correctly for new DeviceInfo field.The test mock now includes
isAppleMobile: false, maintaining consistency with the extended DeviceInfo interface.__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx (1)
41-46: Test mocks updated correctly.The mock values now include
isAppleMobile: false, maintaining consistency with the extended DeviceInfo interface.Also applies to: 72-77
__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx (1)
5-13: Mock updated correctly for new DeviceInfo field.The test mock now includes
isAppleMobile: false, maintaining consistency with the extended DeviceInfo interface.app/open-mobile/page.client.tsx (1)
9-9: Platform detection correctly centralized.Replacing inline iOS detection with
isAppleMobilefrom the hook centralizes device detection logic and eliminates code duplication. The conditional rendering logic correctly handles Apple mobile, Android, and fallback cases.Also applies to: 15-15, 46-50
components/cookies/CookiesBanner.tsx (1)
12-12: Platform detection correctly centralized.Replacing inline iOS detection with
isAppleMobilefrom the hook centralizes device detection logic. The styling conditionisApp && isAppleMobilecorrectly targets iOS app environments.Also applies to: 24-24
__tests__/hooks/useDeviceInfo.test.ts (3)
21-29: Test correctly asserts Apple mobile detection for iPhone.The assertion
expect(result.current.isAppleMobile).toBe(true)correctly validates that iPhone user agents are detected as Apple mobile devices.
31-39: Test correctly asserts Apple mobile detection for iPad in desktop mode.The assertion validates the edge case where iPads report as "Macintosh" with touch capabilities. The detection correctly identifies this as an Apple mobile device.
41-49: Test correctly asserts non-Apple mobile detection for desktop.The assertion
expect(result.current.isAppleMobile).toBe(false)correctly validates that generic desktop user agents are not detected as Apple mobile devices.__tests__/components/waves/drops/WaveDropsScrollBottomButton.test.tsx (1)
23-36: LGTM! Well-structured test for pending message reveal.The test properly verifies the new pending badge rendering and reveal handler invocation. The assertions clearly validate both the UI changes and the callback behavior.
components/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsx (1)
44-46: LGTM! Clean prop threading.The new props are properly typed with
readonlyand correctly forwarded to the child component.Also applies to: 65-67, 106-107
components/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsx (1)
40-42: LGTM! Proper prop forwarding with clear naming.The props are correctly threaded through to
WaveDropsScrollBottomButtonwith appropriate name mappings.Also applies to: 64-66, 101-102
components/waves/drops/wave-drops-all/index.tsx (4)
93-123: Solid implementation of deferred rendering state management.The state and effect properly handle the visibility window for Apple devices. The logic correctly defers new messages when the user is reading (not pinned to bottom) on Apple mobile.
One edge case to verify: when
latestSerialNobecomesnull(e.g., all drops removed),visibleLatestSerialis not reset. Ensure this behavior is intentional and handles the scenario correctly.
125-149: LGTM! Efficient filtering logic for Apple device rendering.The memo correctly filters drops based on the visibility threshold and handles drops without
serial_nogracefully by including them in the results.
151-166: LGTM! Accurate pending count calculation.The memo correctly counts only drops with numeric serial numbers that exceed the visibility threshold, providing the right count for the badge display.
185-193: LGTM! Clean reveal handler.The callback properly updates the visibility threshold to the newest serial and triggers a scroll to bottom, revealing all pending messages.
__tests__/components/waves/drops/WaveDropsAll.test.tsx (3)
38-46: LGTM! Comprehensive device info mock setup.The mock properly exposes all device info properties and allows per-test configuration through
setupMocksoptions, enabling flexible test scenarios.Also applies to: 173-178, 252-257
209-264: Excellent mock architecture for dynamic message updates.The mutable wave messages approach with getter/setter functions enables realistic testing of real-time message arrival scenarios. This is a clean solution for simulating dynamic data updates in tests.
592-648: LGTM! Thorough test coverage for Apple device deferred rendering.The test comprehensively validates the entire flow:
- Initial state verification (no pending)
- New message arrival simulation
- Deferred rendering confirmation
- Reveal interaction
- Final state validation
The use of fake timers and userEvent properly exercises asynchronous behavior.
components/waves/drops/WaveDropsScrollBottomButton.tsx (1)
6-27: LGTM! Well-structured dual-mode button logic.The component cleanly handles both pending message reveal and scroll-to-bottom functionality. The logic correctly prioritizes the reveal action when messages are pending.
|



Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Tests