Conversation
WalkthroughThis pull request introduces a wave drops search feature with scroll coordination. It adds a WaveChatScrollContext provider for coordinating scroll-to-serialNo requests, a new WaveDropsSearchModal component for searching drops within a wave, an infinite search hook (useWaveDropsSearch), and integrates search UI into MyStreamWave tabs. URL parameter handling is simplified, and a new API endpoint for searching drops is added to the OpenAPI spec. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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: 0
🧹 Nitpick comments (1)
components/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsx (1)
140-183: Consider extracting shared header content to reduce duplication.The
WavePictureand wave title (h1) are rendered identically in both mobile and desktop branches. Extracting these into a small helper component or variable would reduce duplication and simplify future maintenance.+ const headerContent = ( + <> + <div className="tw-size-6 lg:tw-size-9 tw-flex-shrink-0 tw-ring-1 tw-ring-offset-1 tw-ring-offset-iron-950 tw-ring-white/30 tw-rounded-full"> + <WavePicture + name={wave.name} + picture={wave.picture} + contributors={wave.contributors_overview.map((c) => ({ + pfp: c.contributor_pfp, + }))} + /> + </div> + <h1 className="tw-ml-3 tw-text-sm lg:tw-text-xl tw-font-semibold tw-text-white/95 tw-tracking-tight tw-mb-0 tw-truncate"> + {wave.name} + </h1> + </> + ); + {isMobile ? ( <button type="button" onClick={() => setIsSearchOpen(true)} aria-label="Search messages in this wave" className="tw-flex tw-items-center tw-bg-transparent tw-border-0 tw-p-0 tw-text-left tw-min-w-0" > - <div className="tw-size-6 lg:tw-size-9 ..."> - <WavePicture ... /> - </div> - <h1 className="tw-ml-3 ..."> - {wave.name} - </h1> + {headerContent} </button> ) : ( <> - <div className="tw-size-6 lg:tw-size-9 ..."> - <WavePicture ... /> - </div> - <h1 className="tw-ml-3 ..."> - {wave.name} - </h1> + {headerContent} <button ...> <MagnifyingGlassIcon ... /> </button> </> )}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
generated/models/ApiDropWithoutWavesPageWithoutCount.tsis excluded by!**/generated/**generated/models/ObjectSerializer.tsis excluded by!**/generated/**package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (9)
components/brain/my-stream/MyStreamWave.tsx(2 hunks)components/brain/my-stream/MyStreamWaveChat.tsx(1 hunks)components/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsx(5 hunks)components/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsx(5 hunks)components/waves/drops/search/WaveDropsSearchModal.tsx(1 hunks)components/waves/drops/wave-drops-all/index.tsx(2 hunks)contexts/wave/WaveChatScrollContext.tsx(1 hunks)hooks/useWaveDropsSearch.ts(1 hunks)openapi.yaml(2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version
**/*.{ts,tsx,js,jsx}: Replace<img>elements with<Image />fromnext/imageto satisfy@next/next/no-img-elementESLint rule
Use<Link href="/path">from Next.js for internal navigation instead of plain HTML links to satisfy@next/next/no-html-link-for-pagesESLint rule
Files:
components/waves/drops/wave-drops-all/index.tsxcomponents/brain/my-stream/MyStreamWaveChat.tsxcomponents/waves/drops/search/WaveDropsSearchModal.tsxcomponents/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsxcontexts/wave/WaveChatScrollContext.tsxcomponents/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsxcomponents/brain/my-stream/MyStreamWave.tsxhooks/useWaveDropsSearch.ts
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always addreadonlybefore props in React components
Files:
components/waves/drops/wave-drops-all/index.tsxcomponents/brain/my-stream/MyStreamWaveChat.tsxcomponents/waves/drops/search/WaveDropsSearchModal.tsxcomponents/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsxcontexts/wave/WaveChatScrollContext.tsxcomponents/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsxcomponents/brain/my-stream/MyStreamWave.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use<Link>, images should usenext/image, and adopt Next's ESLint rules (Core Web Vitals)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Files:
components/waves/drops/wave-drops-all/index.tsxcomponents/brain/my-stream/MyStreamWaveChat.tsxcomponents/waves/drops/search/WaveDropsSearchModal.tsxcomponents/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsxcontexts/wave/WaveChatScrollContext.tsxcomponents/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsxcomponents/brain/my-stream/MyStreamWave.tsxhooks/useWaveDropsSearch.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Must passtsc --noEmittype checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") overReact.namespace usage (React.useMemo,React.useRef, etc.)
If thereact-hooks/exhaustive-depslint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic inuseEffectEvent
**/*.{ts,tsx}: Must passtsc --noEmitfor TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
UseuseEffectEventfor non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs:<Link>for internal links,next/imagefor images, adopt Next's ESLint rules
Use'use cache'directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace<img>elements with<Image />fromnext/image
Use<Link href="/path">for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with'use server'directive
Files:
components/waves/drops/wave-drops-all/index.tsxcomponents/brain/my-stream/MyStreamWaveChat.tsxcomponents/waves/drops/search/WaveDropsSearchModal.tsxcomponents/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsxcontexts/wave/WaveChatScrollContext.tsxcomponents/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsxcomponents/brain/my-stream/MyStreamWave.tsxhooks/useWaveDropsSearch.ts
🧠 Learnings (9)
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Remove unnecessary Effects; if Effect only derives state, compute during render instead
Applied to files:
components/waves/drops/wave-drops-all/index.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use `useEffectEvent` for non-reactive logic inside Effects to avoid unnecessary re-runs
Applied to files:
components/waves/drops/wave-drops-all/index.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx} : If the `react-hooks/exhaustive-deps` lint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic in `useEffectEvent`
Applied to files:
components/waves/drops/wave-drops-all/index.tsx
📚 Learning: 2025-11-25T08:35:58.729Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T08:35:58.729Z
Learning: Applies to **/*.{tsx,jsx} : Use FontAwesome for icons in React components
Applied to files:
components/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions
Applied to files:
components/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsxcomponents/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsx
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks
Applied to files:
components/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx} : Prefer direct named imports for React hooks and types (`import { useMemo, useRef, FC, etc. } from "react"`) over `React.` namespace usage (`React.useMemo`, `React.useRef`, etc.)
Applied to files:
components/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Applied to files:
components/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsx
📚 Learning: 2025-11-25T08:35:58.729Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-25T08:35:58.729Z
Learning: Applies to **/*.{tsx,jsx} : Use react-query for data fetching
Applied to files:
components/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsx
🧬 Code graph analysis (7)
components/waves/drops/wave-drops-all/index.tsx (1)
contexts/wave/WaveChatScrollContext.tsx (1)
useWaveChatScrollOptional(82-84)
components/brain/my-stream/MyStreamWaveChat.tsx (1)
helpers/navigation.helpers.ts (1)
getHomeFeedRoute(11-11)
components/waves/drops/search/WaveDropsSearchModal.tsx (2)
generated/models/ApiWave.ts (1)
ApiWave(27-179)hooks/useWaveDropsSearch.ts (1)
useWaveDropsSearch(38-85)
components/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsx (3)
contexts/wave/WaveChatScrollContext.tsx (1)
useWaveChatScrollOptional(82-84)components/waves/WavePicture.tsx (1)
WavePicture(63-122)components/waves/drops/search/WaveDropsSearchModal.tsx (1)
WaveDropsSearchModal(16-271)
components/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsx (2)
contexts/wave/WaveChatScrollContext.tsx (1)
useWaveChatScrollOptional(82-84)components/waves/WavePicture.tsx (1)
WavePicture(63-122)
components/brain/my-stream/MyStreamWave.tsx (2)
contexts/wave/WaveChatScrollContext.tsx (1)
WaveChatScrollProvider(26-80)components/brain/my-stream/tabs/MyStreamWaveTabs.tsx (1)
MyStreamWaveTabs(15-58)
hooks/useWaveDropsSearch.ts (5)
generated/models/ApiWave.ts (1)
ApiWave(27-179)generated/models/ApiWaveMin.ts (1)
ApiWaveMin(16-163)generated/models/ApiDropWithoutWavesPageWithoutCount.ts (1)
ApiDropWithoutWavesPageWithoutCount(16-51)helpers/waves/drop.helpers.ts (1)
ExtendedDrop(16-20)helpers/waves/wave-drops.helpers.ts (2)
mapToExtendedDrops(35-44)generateUniqueKeys(78-91)
⏰ 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 (12)
openapi.yaml (1)
2620-2662: Wave search endpoint and page schema look consistent with client usageThe new
/waves/{waveId}/searchdefinition andApiDropWithoutWavesPageWithoutCountschema align with the client hook (term/page/size,next+pagepagination andApiDropWithoutWave[]payload). I don’t see spec‑level issues here.Also applies to: 5284-5294
hooks/useWaveDropsSearch.ts (1)
13-85: Infinite wave‑search hook is correctly wired to the new API and helpersMapping
ApiWave → ApiWaveMin, query key construction, pagination viapage/next, and transformation throughmapToExtendedDrops/generateUniqueKeysare all consistent and look correct for the/waves/{waveId}/searchendpoint. No issues from a hooks/typing perspective.contexts/wave/WaveChatScrollContext.tsx (1)
3-84: Scroll coordination context is minimal and correctly handles registration and pending requestsThe provider and hooks manage a single wave scroll handler with sensible semantics (pending request replay, guarded unregister, optional consumer). The implementation is straightforward and sound for the intended single‑wave use.
components/waves/drops/wave-drops-all/index.tsx (1)
21-22: Wave chat scroll handler registration is correctly scoped and cleaned upRegistering
queueSerialTargetas the wave’s scroll handler when the context is available (with guarded cleanup) is a clean integration; dependencies look correct and this remains a no‑op when the provider isn’t present.Also applies to: 187-195
components/waves/drops/search/WaveDropsSearchModal.tsx (1)
1-271: Wave drop search modal is well‑structured and aligns with the hook/API behaviorDebounced querying, open/close lifecycle (click‑away, Escape, focus management), state handling (loading/error/empty/results), and selection flow (
onSelectSerialNothenonClose) are all coherent and matchuseWaveDropsSearch’s contract. I don’t see functional or accessibility issues here.components/brain/my-stream/MyStreamWave.tsx (1)
20-21: WaveChatScrollProvider is correctly introduced without disturbing existing behaviorWrapping the MyStream wave layout in
WaveChatScrollProviderkeeps hook ordering intact while enabling scroll coordination across tabs and content. The not‑found URL handling and stable key usage remain effectively unchanged.Also applies to: 98-115
components/brain/my-stream/tabs/MyStreamWaveTabsDefault.tsx (1)
1-149: Search modal + scroll behavior are cleanly integrated into default wave tabsThe new search state, WaveDropsSearchModal usage, and
handleSearchSelectlogic (prefer context scroll, fall back to URLserialNo+ replace) are coherent and correctly tied into the existing tab system and routing. Header tweaks for mobile/desktop look consistent with current patterns.components/brain/my-stream/MyStreamWaveChat.tsx (1)
39-60: No changes needed. The URL parameter cleanup works as intended and does not interfere with the deep link scroll behavior.components/brain/my-stream/tabs/MyStreamWaveTabsMeme.tsx (4)
21-28: LGTM!The new imports are appropriate and consistent with the existing patterns in this file. HeroIcons usage aligns with the other icons already imported.
48-49: LGTM!State and context hook are properly initialized. The optional nature of
waveChatScrollis correctly handled in thehandleSearchSelectfunction.
113-123: LGTM!The search selection handler is well-implemented:
- Correctly switches to CHAT tab before scrolling
- Uses the scroll context when available for smooth in-page scrolling
- Falls back to URL params when context is unavailable, preserving navigation history appropriately with
router.replace
228-233: LGTM!The
WaveDropsSearchModalis properly integrated with all required props correctly wired to local state and handlers.

Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.