Skip to content

Notifications Rework 2#1673

Merged
prxt6529 merged 14 commits intomainfrom
notifications-rework-2
Dec 30, 2025
Merged

Notifications Rework 2#1673
prxt6529 merged 14 commits intomainfrom
notifications-rework-2

Conversation

@prxt6529
Copy link
Copy Markdown
Collaborator

@prxt6529 prxt6529 commented Dec 29, 2025

Summary by CodeRabbit

  • New Features

    • "Mark as unread" action on drops and an Unread Divider to highlight first unread messages.
  • Improvements

    • Unified unread badges with "99+" cap, deeplinking to the first-unread drop, and a mute indicator replacing badges when muted.
    • Mute/unmute controls added across wave headers, options, and message views; muted waves skip realtime unread updates.
  • API

    • Endpoints to mark drops unread and to mute/unmute waves.
  • Tests

    • Expanded coverage for unread, mute, navigation, and related UI flows.

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

Signed-off-by: prxt6529 <prxt@6529.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 29, 2025

📝 Walkthrough

Walkthrough

Threads per-wave unread and mute state through UI, API, contexts, hooks, and navigation; adds UnreadDivider context and mark‑as‑unread API/action; centralizes wave list logic in a new core hook; propagates firstUnreadDropSerialNo/serialNo through navigation and active‑wave APIs.

Changes

Cohort / File(s) Summary
Navigation helpers & callers
helpers/navigation.helpers.ts, components/waves/create-dm/CreateDirectMessage.tsx, components/user/user-page-header/UserPageHeaderClient.tsx
Add navigateToDirectMessage and switch DM navigation calls to it; small import/format tweaks.
Left sidebar & avatar UI
components/brain/left-sidebar/web/.../CollapsedWave.tsx, components/brain/left-sidebar/web/.../WaveAvatar.tsx, components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx, components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts, components/brain/left-sidebar/web/WebBrainLeftSidebarWave/index.tsx
Propagate firstUnreadDropSerialNo/serialNo into navigation; compute combined unread count (capped at 99+); show bell‑slash when muted; update deps.
Unread divider context & wiring
contexts/wave/UnreadDividerContext.tsx, 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, components/drops/view/DropsList.tsx, components/drops/view/UnreadDivider.tsx
Add UnreadDividerProvider/hooks; move unread-divider state into context; DropsList accepts unreadDividerSerialNo and inserts UnreadDivider; WaveDropsAll split into provider + inner and accepts isMuted.
Mark‑unread flow (API + UI)
openapi.yaml, components/waves/drops/WaveDropActionsMarkUnread.tsx, components/waves/drops/WaveDropActions.tsx, components/common/icons/MailUnreadIcon.tsx, components/waves/drops/WaveDropMobileMenu.tsx
Add POST /drops/{dropId}/mark-unread; new WaveDropActionsMarkUnread component (API call, query invalidation, set unread divider); add icon and include action in desktop & mobile menus; tests added.
Wave mute controls
components/waves/header/options/mute/WaveMute.tsx, components/waves/header/options/WaveHeaderOptions.tsx, components/waves/specs/WaveNotificationSettings.tsx, openapi.yaml
New WaveMute component and menu integration; add mute/unmute API endpoints; notification settings surface mute state and toggles; tests updated.
Enhanced waves list core & realtime/mute integration
contexts/wave/hooks/useEnhancedWavesListCore.ts, contexts/wave/hooks/useEnhancedWavesList.ts, contexts/wave/hooks/useEnhancedDmWavesList.ts, contexts/wave/hooks/useNewDropCounter.ts, contexts/wave/hooks/useWaveRealtimeUpdater.ts, contexts/wave/MyStreamContext.tsx, hooks/useWavesList.ts, hooks/useUnreadIndicator.ts
Add useEnhancedWavesListCore (exports MinimalWave); delegate existing list hooks to core; carry unread/new-drops, firstUnreadSerialNo, isMuted; realtime updater skips muted waves; add restoreWaveUnreadCount.
Wave drops UI & provider changes
components/waves/drops/wave-drops-all/*, components/waves/drops/WaveDropActionsOptions.tsx, components/waves/drop/SingleWaveDropChat.tsx
Move unread-divider state to provider/inner; pass unreadDividerSerialNo into DropsList; pass isMuted through to WaveDropsAll; minor tooltip/style tweaks.
Typing & websocket hooks
hooks/useWaveIsTyping.ts, hooks/useWaveWebSocket.ts
useWaveIsTyping gains disabled param and uses useWaveWebSocket(disabled ? "" : waveId); useWaveWebSocket tears down when waveId is falsy and sends subscription message on open.
Context/API surface & active-wave routing
contexts/wave/MyStreamContext.tsx, contexts/wave/hooks/useActiveWaveManager.ts, components/brain/my-stream/MyStreamWaveChat.tsx
ActiveWaveManager.set accepts optional serialNo; MyStreamContext exposes restoreWaveUnreadCount and isWaveMuted; initialDrop tracking uses waveId+serialNo.
Tests & mocks
__tests__/**/*, __tests__/utils/mockFactories.ts
Extensive tests and mocks added/updated for unread divider, mark‑unread, mute flows, serialNo routing, and new metrics fields; test factories extended with unread/muted fields and ES module shapes.

Sequence Diagram(s)

mermaid
sequenceDiagram
autonumber
participant User as User/Client
participant UI as WaveDropActionsMarkUnread
participant API as Backend (/drops/{dropId}/mark-unread)
participant CQ as React Query / Contexts
participant Unread as UnreadDividerContext

User->>UI: Click "Mark as unread"
UI->>UI: set loading, disable control
UI->>API: POST /drops/{dropId}/mark-unread
API-->>UI: 200 { your_unread_drops_count, first_unread_drop_serial_no? }
UI->>CQ: update unread counts & invalidate caches
alt response includes first_unread_drop_serial_no
UI->>Unread: setUnreadDividerSerialNo(first_unread_drop_serial_no)
end
UI->>User: show success toast; clear loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • ragnep
  • simo6529

Poem

🐇 I hopped the inbox, found a bell to hush,
Counters blinked, a pink divider blush,
I nudged a drop back into sight,
Mute snoozes bells through quiet night,
Rabbit cheers — unread counts now just right!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.83% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Notifications Rework 2' is vague and generic, using non-descriptive terminology that does not convey meaningful information about the specific changes made in this substantial changeset. Consider using a more descriptive title that highlights a primary change, such as 'Add unread drop tracking and wave mute functionality' or 'Implement drop-level unread markers and mute controls'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 325aa68 and 329ceeb.

📒 Files selected for processing (1)
  • components/waves/drops/wave-drops-all/index.tsx
🧰 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 /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • components/waves/drops/wave-drops-all/index.tsx
**/*.{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 add readonly before props in React components

Files:

  • components/waves/drops/wave-drops-all/index.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 use next/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.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
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.)
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

**/*.{ts,tsx}: Must pass tsc --noEmit for 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
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for 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 /> from next/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.tsx
🧠 Learnings (4)
📚 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/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-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/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 TypeScript and React functional components with hooks

Applied to files:

  • components/waves/drops/wave-drops-all/index.tsx
⏰ 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 (5)
components/waves/drops/wave-drops-all/index.tsx (5)

5-10: LGTM—imports properly organized.

The new imports for UnreadDividerProvider, useUnreadDivider, and WaveDropsScrollingOverlay are correctly added, and the import organization follows the project's conventions.

Also applies to: 20-22


50-50: LGTM—isMuted prop properly integrated.

The isMuted prop is correctly typed, defaulted, and propagated through both the outer and inner components to the useWaveIsTyping hook.

Also applies to: 62-62, 79-79, 334-334, 349-349


333-333: Past issue resolved—bottomPaddingClassName now properly forwarded.

The previous review flagged that bottomPaddingClassName wasn't being forwarded from the outer component. This is now correctly implemented: the prop is destructured at line 333 and passed to WaveDropsAllInner at line 348.

Also applies to: 348-348


325-353: LGTM—clean provider wrapping pattern.

The outer component correctly wraps WaveDropsAllInner with UnreadDividerProvider, using a keyed provider (line 339) to ensure fresh state per wave. All props are properly forwarded to the inner component.


73-74: The implementation is correct. The setUnreadDividerSerialNo from useState() is inherently stable in React and does not require wrapping in useCallback. React guarantees that setState functions returned from useState() maintain a stable reference across renders, so effects using this setter will not re-run unnecessarily due to the setter itself.


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.

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: 0

🧹 Nitpick comments (2)
contexts/wave/hooks/useEnhancedDmWavesList.ts (1)

9-39: Clarify/adjust interaction between local “cleared” state and server unread metrics

The clearedUnreadWaveIds + 1s timeout nicely model “wave has been viewed, treat existing unread as read” and the MinimalWave additions (unreadDropsCount, latestReadTimestamp) line up with the new API fields. One nuance:

  • Once a wave ID is in clearedUnreadWaveIds, you always return unreadDropsCount: 0 for that wave, even if wave.metrics.your_unread_drops_count later increases. In the happy path, new unread are surfaced via the WebSocket‑driven newDropsCount, but if WS events are missed (offline, tab throttling, reconnect gaps), metrics could indicate new unread while the local “cleared” flag keeps them hidden.

Consider either:

  • clearing clearedUnreadWaveIds for a wave when wave.metrics.your_unread_drops_count jumps above zero again, or
  • explicitly documenting that, after first view, DM unread relies solely on the live WebSocket counter for the rest of the session.

This would make the behavior more robust in degraded network scenarios.

Also applies to: 40-65

contexts/wave/hooks/useEnhancedWavesList.ts (1)

35-53: Consider cleanup strategy for the cleared set.

The clearedUnreadWaveIds Set grows indefinitely as users visit waves and is never pruned. While each entry is small and bounded by session activity, this is technically a memory leak.

💡 Potential cleanup strategies

Option 1: Store only the current cleared wave

-  const [clearedUnreadWaveIds, setClearedUnreadWaveIds] = useState<Set<string>>(
-    new Set()
-  );
+  const [clearedUnreadWaveId, setClearedUnreadWaveId] = useState<string | null>(null);

  const resetWaveUnreadCount = useCallback((waveId: string) => {
-    setClearedUnreadWaveIds((prev) => {
-      const next = new Set(prev);
-      next.add(waveId);
-      return next;
-    });
+    setClearedUnreadWaveId(waveId);
  }, []);

Then update the isCleared check in mapWave:

-      const isCleared = clearedUnreadWaveIds.has(wave.id);
+      const isCleared = clearedUnreadWaveId === wave.id;

Option 2: Implement LRU eviction or size limit
If multiple waves need to stay cleared simultaneously, consider capping the Set size or evicting old entries.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 766eecc and a1f97de.

⛔ Files ignored due to path filters (1)
  • generated/models/ApiWaveMetrics.ts is excluded by !**/generated/**
📒 Files selected for processing (10)
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • components/user/user-page-header/UserPageHeaderClient.tsx
  • components/waves/create-dm/CreateDirectMessage.tsx
  • contexts/wave/hooks/useEnhancedDmWavesList.ts
  • contexts/wave/hooks/useEnhancedWavesList.ts
  • contexts/wave/hooks/useNewDropCounter.ts
  • helpers/navigation.helpers.ts
  • hooks/useUnreadIndicator.ts
  • openapi.yaml
🧰 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 /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • helpers/navigation.helpers.ts
  • contexts/wave/hooks/useNewDropCounter.ts
  • components/user/user-page-header/UserPageHeaderClient.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • contexts/wave/hooks/useEnhancedWavesList.ts
  • contexts/wave/hooks/useEnhancedDmWavesList.ts
  • components/waves/create-dm/CreateDirectMessage.tsx
  • hooks/useUnreadIndicator.ts
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.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 use next/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:

  • helpers/navigation.helpers.ts
  • contexts/wave/hooks/useNewDropCounter.ts
  • components/user/user-page-header/UserPageHeaderClient.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • contexts/wave/hooks/useEnhancedWavesList.ts
  • contexts/wave/hooks/useEnhancedDmWavesList.ts
  • components/waves/create-dm/CreateDirectMessage.tsx
  • hooks/useUnreadIndicator.ts
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
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.)
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

**/*.{ts,tsx}: Must pass tsc --noEmit for 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
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for 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 /> from next/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:

  • helpers/navigation.helpers.ts
  • contexts/wave/hooks/useNewDropCounter.ts
  • components/user/user-page-header/UserPageHeaderClient.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • contexts/wave/hooks/useEnhancedWavesList.ts
  • contexts/wave/hooks/useEnhancedDmWavesList.ts
  • components/waves/create-dm/CreateDirectMessage.tsx
  • hooks/useUnreadIndicator.ts
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.tsx
**/*.{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 add readonly before props in React components

Files:

  • components/user/user-page-header/UserPageHeaderClient.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • components/waves/create-dm/CreateDirectMessage.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.tsx
🧠 Learnings (11)
📚 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:

  • contexts/wave/hooks/useNewDropCounter.ts
  • components/user/user-page-header/UserPageHeaderClient.tsx
  • contexts/wave/hooks/useEnhancedDmWavesList.ts
  • components/waves/create-dm/CreateDirectMessage.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.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 **/*.{ts,tsx,js,jsx} : Include all required imports and ensure proper naming of key components

Applied to files:

  • components/user/user-page-header/UserPageHeaderClient.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.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/user/user-page-header/UserPageHeaderClient.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} : Prefer Server Components over Client Components; use Server Functions/Server Actions (`'use server'`) for mutations

Applied to files:

  • components/user/user-page-header/UserPageHeaderClient.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/user/user-page-header/UserPageHeaderClient.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/user/user-page-header/UserPageHeaderClient.tsx
  • contexts/wave/hooks/useEnhancedWavesList.ts
📚 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/user/user-page-header/UserPageHeaderClient.tsx
  • contexts/wave/hooks/useEnhancedWavesList.ts
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.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:

  • contexts/wave/hooks/useEnhancedDmWavesList.ts
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Organize imports with one import per module in order: external → internal → types, with no duplicates

Applied to files:

  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)

Applied to files:

  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.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 framework APIs: `<Link>` for internal links, `next/image` for images, adopt Next's ESLint rules

Applied to files:

  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.tsx
🧬 Code graph analysis (3)
components/user/user-page-header/UserPageHeaderClient.tsx (2)
hooks/useDeviceInfo.ts (1)
  • useDeviceInfo (23-105)
helpers/navigation.helpers.ts (1)
  • navigateToDirectMessage (73-92)
components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx (1)
components/waves/WavePicture.tsx (1)
  • WavePicture (63-122)
components/waves/create-dm/CreateDirectMessage.tsx (1)
helpers/navigation.helpers.ts (1)
  • navigateToDirectMessage (73-92)
⏰ 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 (9)
openapi.yaml (1)

7967-7999: ApiWaveMetrics unread fields align with frontend usage

Adding your_latest_drop_timestamp, your_unread_drops_count, and your_latest_read_timestamp as required fields with number/int64 matches how the frontend now consumes wave.metrics for per-wave unread tracking. Just ensure the backend always populates non-null values for these fields to avoid runtime inconsistencies.

components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/CollapsedWave.tsx (1)

1-52: Collapsed wave styling/tooltip tweaks are safe

Switching to double-quoted class strings and a quoted "data-tooltip-id" key is purely stylistic; the hover/active styling and tooltip behavior remain unchanged.

contexts/wave/hooks/useNewDropCounter.ts (1)

167-181: Uncapped new-drop counter matches display-level badge cap

The increment change to count: currentCount + 1 removes the previous logical cap and relies on UI (e.g., WaveAvatar’s display cap) to clamp what’s shown. This keeps internal state accurate while preserving UX limits and does not introduce new race conditions given the existing functional setNewDropsCounts usage.

hooks/useUnreadIndicator.ts (1)

39-48: Unread indicator now correctly uses both server and local unread sources

Using (dm?.unreadDropsCount ?? 0) > 0 || (dm?.newDropsCount?.count ?? 0) > 0 ensures the badge appears for both persisted unread drops (from metrics) and new, session-local drops tracked via WebSocket, while still null‑safe.

helpers/navigation.helpers.ts (1)

73-92: Centralized DM navigation helper is consistent and reusable

navigateToDirectMessage correctly reuses getWaveRoute with isDirectMessage: true and switches between router.replace and router.push based on isApp, matching prior per-call logic and reducing duplication across callers.

components/waves/create-dm/CreateDirectMessage.tsx (1)

3-20: Create DM flow now correctly delegates navigation to helper

Using navigateToDirectMessage({ waveId: wave.id, router, isApp }) after createDirectMessageWave keeps behavior the same while aligning with the new centralized navigation helper. Imports and useState usage are consistent with the rest of the file.

Also applies to: 71-81

components/user/user-page-header/UserPageHeaderClient.tsx (1)

3-26: User header DM button correctly uses centralized navigation with app-awareness

Wiring isApp from useDeviceInfo into handleCreateDirectMessage and delegating to navigateToDirectMessage({ waveId: wave.id, router, isApp }) brings this entrypoint in line with the new DM navigation helper, while preserving loading state and error handling. The new imports and hook usages are consistent and type-safe.

Also applies to: 40-53, 127-154, 178-188

components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx (1)

26-64: LGTM! Badge logic is clear and correct.

The badge display logic appropriately prioritizes unreadDropsCount over newDropsCount.count, and the "99+" cap provides a clean UX for high counts. The conditional rendering and styling transitions are well-structured.

contexts/wave/hooks/useEnhancedWavesList.ts (1)

75-76: API types are confirmed; clarify the intentionality of unread count caching behavior.

The generated ApiWaveMetrics type correctly includes both your_unread_drops_count and your_latest_read_timestamp fields, so the API contract is satisfied.

The clearing behavior in the code is real: once a wave is added to clearedUnreadWaveIds (after becoming active for 1000ms), unreadDropsCount returns 0 and ignores subsequent API values until page refresh. This design appears intentional—the code delays the clear by 1000ms and stores the cleared state persistently. However, confirm with your team whether this caching behavior is the intended UX: new drops arriving during the session will not update the unread count until the next page load.

@prxt6529 prxt6529 changed the title Notifications Rework Notifications Rework 2 Dec 29, 2025
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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: 3

🧹 Nitpick comments (9)
__tests__/components/drops/view/UnreadDivider.test.tsx (1)

15-19: Consider using a more resilient selector and add accessibility tests.

The test uses class-based selectors (.tw-h-0\\.5.tw-bg-rose-500) which are fragile and tightly coupled to Tailwind implementation details. If styling changes, this test will break even if functionality is correct.

🔎 More resilient test approach

Consider using a test-specific attribute or role:

  it('renders horizontal lines', () => {
    const { container } = render(<UnreadDivider />);
-   const lines = container.querySelectorAll('.tw-h-0\\.5.tw-bg-rose-500');
+   const lines = container.querySelectorAll('[role="separator"]');
    expect(lines.length).toBe(2);
  });

Or query by semantic structure rather than styling classes.

Additionally, per coding guidelines for test files in __tests__/**/components/**/*.test.{ts,tsx}, consider adding accessibility tests for keyboard navigation and screen reader compatibility.

Based on learnings, accessibility testing should be included for component tests.

contexts/wave/hooks/useNewDropCounter.ts (1)

176-188: LGTM! Solid logic for tracking first unread serial number.

The implementation correctly:

  • Sets firstUnreadSerialNo to message.serial_no when null
  • Uses Math.min() to maintain the earliest unread serial number
  • Increments count unbounded (removed MAX_COUNT cap)

The unbounded count increment means badges could display very large numbers. If this is intentional (e.g., with capping at display time), this is fine. Otherwise, consider whether a maximum threshold should be enforced here.

components/waves/specs/WaveNotificationSettings.tsx (1)

45-73: Consider removing optimistic state update for consistency.

The implementation correctly handles mute/unmute with proper error handling and cache invalidation. However, line 53 performs an optimistic state update (setIsMuted(!isMuted)) before cache invalidation completes.

🔎 Recommended refactor to rely on query invalidation

Instead of optimistically updating state, let the useEffect at lines 41-43 handle state synchronization when the query refetches:

      if (isMuted) {
        await commonApiDelete({ endpoint: `waves/${wave.id}/mute` });
      } else {
        await commonApiPost({ endpoint: `waves/${wave.id}/mute`, body: {} });
      }
-     setIsMuted(!isMuted);
      queryClient.invalidateQueries({
        queryKey: [QueryKey.WAVE, { wave_id: wave.id }],
      });
      queryClient.invalidateQueries({
        queryKey: [QueryKey.WAVES_OVERVIEW],
      });

This ensures the UI state is driven by the server response rather than optimistic assumptions, preventing potential race conditions.

Alternatively, if optimistic updates are desired, consider adding error rollback in the catch block.

__tests__/components/waves/drops/WaveDropActions.test.tsx (1)

17-17: Mock added for new WaveDropActionsMarkUnread component.

The mock follows the established pattern. Consider adding a test case to verify the mark-unread button renders when connectedProfile exists and is not the author.

🔎 Suggested test case
it('renders mark-unread when user is not the author', () => {
  render(<WaveDropActions drop={baseDrop} activePartIndex={0} onReply={() => {}} onQuote={() => {}} />, { wrapper });
  expect(screen.getByTestId('mark-unread')).toBeInTheDocument();
});

it('hides mark-unread when author is current profile', () => {
  render(
    <AuthContext.Provider value={{ connectedProfile: { handle: 'bob' } } as any}>
      <WaveDropActions drop={baseDrop} activePartIndex={0} onReply={() => {}} onQuote={() => {}} />
    </AuthContext.Provider>
  );
  expect(screen.queryByTestId('mark-unread')).toBeNull();
});
__tests__/components/waves/header/options/mute/WaveMute.test.tsx (2)

1-1: Remove unused React import.

React 19 does not require importing React for JSX. The import can be removed.

🔎 Proposed fix
-import React from 'react';
 import { render, screen, waitFor } from '@testing-library/react';

99-111: Prefer data-testid over className selectors for spinner.

Using .querySelector('.spinner') couples tests to implementation details. Consider adding data-testid to the Spinner component or using a more semantic query.

Alternative approach

Instead of:

expect(screen.getByRole('menuitem').querySelector('.spinner')).toBeInTheDocument();

Use semantic queries or test IDs:

expect(screen.getByRole('status')).toBeInTheDocument();

This requires the Spinner component to have role="status" or a data-testid.

Also applies to: 113-125

__tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx (1)

123-134: Prefer semantic queries over className selectors for spinner.

Using .querySelector('.spinner') couples tests to implementation details. Consider using getByRole('status') or a data-testid attribute on the Spinner component for more robust tests.

Alternative approach
await waitFor(() => {
  expect(screen.getByRole('status')).toBeInTheDocument();
});

This requires the Spinner component to have role="status" for accessibility.

Also applies to: 136-148

contexts/wave/UnreadDividerContext.tsx (1)

29-38: Simplify redundant conditional in setter.

The if/else branches are identical—setUnreadDividerSerialNoState already handles both function and value arguments natively. This wrapper can be simplified.

🔎 Proposed simplification
  const setUnreadDividerSerialNo: SetUnreadDividerSerialNo = useCallback(
    (serialNo) => {
-      if (typeof serialNo === "function") {
-        setUnreadDividerSerialNoState(serialNo);
-      } else {
-        setUnreadDividerSerialNoState(serialNo);
-      }
+      setUnreadDividerSerialNoState(serialNo);
    },
    []
  );
contexts/wave/hooks/useEnhancedWavesListCore.ts (1)

181-211: Consider whether options.supportsPinning should trigger re-computation.

The options.supportsPinning is included in the final useMemo dependencies but the options object reference from the hook parameter may change on each render if the caller doesn't memoize it. Since the default is provided inline at line 46, consider destructuring supportsPinning at the top of the hook or documenting that callers should pass a stable options object.

#!/bin/bash
# Check how callers pass options to this hook
rg -n "useEnhancedWavesListCore" --type=ts -A2 -B1
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1f97de and 78c3b22.

⛔ Files ignored due to path filters (3)
  • generated/models/ApiMarkDropUnreadResponse.ts is excluded by !**/generated/**
  • generated/models/ApiWaveMetrics.ts is excluded by !**/generated/**
  • generated/models/ObjectSerializer.ts is excluded by !**/generated/**
📒 Files selected for processing (41)
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/useWaveRealtimeUpdater.test.ts
  • __tests__/utils/mockFactories.ts
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/index.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • components/common/icons/MailUnreadIcon.tsx
  • components/drops/view/DropsList.tsx
  • components/drops/view/UnreadDivider.tsx
  • components/waves/drops/WaveDropActions.tsx
  • components/waves/drops/WaveDropActionsMarkUnread.tsx
  • components/waves/drops/WaveDropActionsOptions.tsx
  • 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
  • components/waves/header/options/WaveHeaderOptions.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • components/waves/specs/WaveNotificationSettings.tsx
  • contexts/wave/MyStreamContext.tsx
  • contexts/wave/UnreadDividerContext.tsx
  • contexts/wave/hooks/useActiveWaveManager.ts
  • contexts/wave/hooks/useEnhancedDmWavesList.ts
  • contexts/wave/hooks/useEnhancedWavesList.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • contexts/wave/hooks/useNewDropCounter.ts
  • contexts/wave/hooks/useWaveRealtimeUpdater.ts
  • hooks/useWavesList.ts
  • openapi.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • openapi.yaml
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{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 /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • hooks/useWavesList.ts
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • contexts/wave/hooks/useWaveRealtimeUpdater.ts
  • __tests__/components/drops/view/DropsList.test.tsx
  • contexts/wave/hooks/useNewDropCounter.ts
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/index.tsx
  • components/drops/view/DropsList.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsx
  • components/waves/drops/WaveDropActionsMarkUnread.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • __tests__/utils/mockFactories.ts
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • components/waves/drops/WaveDropActionsOptions.tsx
  • contexts/wave/UnreadDividerContext.tsx
  • components/waves/header/options/WaveHeaderOptions.tsx
  • __tests__/useWaveRealtimeUpdater.test.ts
  • contexts/wave/hooks/useEnhancedWavesList.ts
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsx
  • components/drops/view/UnreadDivider.tsx
  • contexts/wave/hooks/useActiveWaveManager.ts
  • components/common/icons/MailUnreadIcon.tsx
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
  • contexts/wave/hooks/useEnhancedDmWavesList.ts
  • components/waves/drops/WaveDropActions.tsx
  • contexts/wave/MyStreamContext.tsx
  • components/waves/specs/WaveNotificationSettings.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{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 add readonly before props in React components

Files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/index.tsx
  • components/drops/view/DropsList.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsx
  • components/waves/drops/WaveDropActionsMarkUnread.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • components/waves/drops/WaveDropActionsOptions.tsx
  • contexts/wave/UnreadDividerContext.tsx
  • components/waves/header/options/WaveHeaderOptions.tsx
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsx
  • components/drops/view/UnreadDivider.tsx
  • components/common/icons/MailUnreadIcon.tsx
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
  • components/waves/drops/WaveDropActions.tsx
  • contexts/wave/MyStreamContext.tsx
  • components/waves/specs/WaveNotificationSettings.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.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 use next/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:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • hooks/useWavesList.ts
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • contexts/wave/hooks/useWaveRealtimeUpdater.ts
  • __tests__/components/drops/view/DropsList.test.tsx
  • contexts/wave/hooks/useNewDropCounter.ts
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/index.tsx
  • components/drops/view/DropsList.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsx
  • components/waves/drops/WaveDropActionsMarkUnread.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • __tests__/utils/mockFactories.ts
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • components/waves/drops/WaveDropActionsOptions.tsx
  • contexts/wave/UnreadDividerContext.tsx
  • components/waves/header/options/WaveHeaderOptions.tsx
  • __tests__/useWaveRealtimeUpdater.test.ts
  • contexts/wave/hooks/useEnhancedWavesList.ts
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsx
  • components/drops/view/UnreadDivider.tsx
  • contexts/wave/hooks/useActiveWaveManager.ts
  • components/common/icons/MailUnreadIcon.tsx
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
  • contexts/wave/hooks/useEnhancedDmWavesList.ts
  • components/waves/drops/WaveDropActions.tsx
  • contexts/wave/MyStreamContext.tsx
  • components/waves/specs/WaveNotificationSettings.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
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.)
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

**/*.{ts,tsx}: Must pass tsc --noEmit for 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
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for 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 /> from next/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:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • hooks/useWavesList.ts
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • contexts/wave/hooks/useWaveRealtimeUpdater.ts
  • __tests__/components/drops/view/DropsList.test.tsx
  • contexts/wave/hooks/useNewDropCounter.ts
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/index.tsx
  • components/drops/view/DropsList.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsx
  • components/waves/drops/WaveDropActionsMarkUnread.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • __tests__/utils/mockFactories.ts
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • components/waves/drops/WaveDropActionsOptions.tsx
  • contexts/wave/UnreadDividerContext.tsx
  • components/waves/header/options/WaveHeaderOptions.tsx
  • __tests__/useWaveRealtimeUpdater.test.ts
  • contexts/wave/hooks/useEnhancedWavesList.ts
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsx
  • components/drops/view/UnreadDivider.tsx
  • contexts/wave/hooks/useActiveWaveManager.ts
  • components/common/icons/MailUnreadIcon.tsx
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
  • contexts/wave/hooks/useEnhancedDmWavesList.ts
  • components/waves/drops/WaveDropActions.tsx
  • contexts/wave/MyStreamContext.tsx
  • components/waves/specs/WaveNotificationSettings.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/@(__tests__|*.test).{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Tests should live in __tests__/ or ComponentName.test.tsx; mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/useWaveRealtimeUpdater.test.ts
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Place tests in __tests__/ directory or as ComponentName.test.tsx alongside components

Files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/utils/mockFactories.ts
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/useWaveRealtimeUpdater.test.ts
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/useWaveRealtimeUpdater.test.ts
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use Jest + ts-jest for TypeScript testing

Files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/useWaveRealtimeUpdater.test.ts
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/utils/mockFactories.ts
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/useWaveRealtimeUpdater.test.ts
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
__tests__/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (tests/AGENTS.md)

__tests__/**/*.{ts,tsx,js}: Prefer for...of loops over forEach as it allows break/continue and works with async/await
Use array.at(-1) and array.at(-2) instead of index-based array access for negative indexing
Use String.prototype.replaceAll() instead of replace() for global string replacements
Use globalThis.fetch() instead of direct fetch() calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Use element.remove() instead of parent.removeChild(element) for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)

Files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/utils/mockFactories.ts
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/useWaveRealtimeUpdater.test.ts
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use semantic HTML elements (<label>, <output>) over ARIA attributes when possible; every form control must have a label

Files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
🧠 Learnings (25)
📚 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 **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/utils/mockFactories.ts
  • __tests__/components/waves/specs/WaveNotificationSettings.test.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 **/@(__tests__|*.test).{ts,tsx} : Tests should live in `__tests__/` or `ComponentName.test.tsx`; mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Use testing-library/react + user-event for React component tests

Applied to files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)

Applied to files:

  • __tests__/components/waves/drops/WaveDropActions.test.tsx
  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/useWaveRealtimeUpdater.test.ts
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Test high-risk areas including happy path workflows, invalid input errors, edge cases/boundaries, component & API interactions, and performance/security when relevant

Applied to files:

  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Test accessibility with keyboard navigation and screen reader compatibility

Applied to files:

  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.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 **/__tests__/**/*.{ts,tsx} : Place tests in `__tests__/` directory or as `ComponentName.test.tsx` alongside components

Applied to files:

  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : All tests must live in `__tests__`, mirroring source folders (`components`, `contexts`, `hooks`, `utils`)

Applied to files:

  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/{components,contexts,hooks}/**/*.{ts,tsx} : Use semantic HTML elements (`<label>`, `<output>`) over ARIA attributes when possible; every form control must have a label

Applied to files:

  • __tests__/components/waves/header/options/mute/WaveMute.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Write tests following Arrange – Act – Assert pattern with one behaviour per test and clear, descriptive names

Applied to files:

  • __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Keep tests independent, deterministic, and fast with production-like data

Applied to files:

  • __tests__/components/drops/view/DropsList.test.tsx
  • __tests__/components/waves/drops/WaveDropActionsMarkUnread.test.tsx
  • __tests__/utils/mockFactories.ts
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • __tests__/helpers/navigation.helpers.test.ts
📚 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/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx
  • components/common/icons/MailUnreadIcon.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
📚 Learning: 2025-11-25T08:37:21.058Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-11-25T08:37:21.058Z
Learning: Applies to __mocks__/**/__mocks__/** : Document expected behaviour in the mock file when it is not obvious

Applied to files:

  • __tests__/utils/mockFactories.ts
  • __tests__/components/waves/drops/WaveDropsAll.test.tsx
📚 Learning: 2025-11-25T08:37:21.058Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __mocks__/AGENTS.md:0-0
Timestamp: 2025-11-25T08:37:21.058Z
Learning: Applies to __mocks__/**/__mocks__/** : Keep mock implementations minimal – enough to satisfy test scenarios

Applied to files:

  • __tests__/utils/mockFactories.ts
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Use `element.remove()` instead of `parent.removeChild(element)` for DOM manipulation

Applied to files:

  • __tests__/components/waves/drops/WaveDropsAll.test.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:

  • contexts/wave/UnreadDividerContext.tsx
  • __tests__/components/waves/specs/WaveNotificationSettings.test.tsx
  • contexts/wave/MyStreamContext.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.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} : Always add `readonly` before props in React components

Applied to files:

  • components/common/icons/MailUnreadIcon.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx} : Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Applied to files:

  • __tests__/helpers/navigation.helpers.test.ts
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/app/api/**/__tests__/**/*.test.{ts,tsx,js} : API integration tests should be located in `app/api`

Applied to files:

  • __tests__/helpers/navigation.helpers.test.ts
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Organize imports with one import per module in order: external → internal → types, with no duplicates

Applied to files:

  • __tests__/helpers/navigation.helpers.test.ts
📚 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 app/**/page.{ts,tsx} : Export `generateMetadata` in App Router routes using the `getAppMetadata` helper from '@/components/providers/metadata'

Applied to files:

  • __tests__/helpers/navigation.helpers.test.ts
📚 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/brain/my-stream/MyStreamWaveChat.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:

  • __tests__/components/waves/specs/WaveNotificationSettings.test.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:

  • contexts/wave/MyStreamContext.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:

  • contexts/wave/MyStreamContext.tsx
🧬 Code graph analysis (16)
__tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx (1)
contexts/wave/hooks/useActiveWaveManager.ts (1)
  • useActiveWaveManager (37-82)
__tests__/contexts/wave/UnreadDividerContext.test.tsx (1)
contexts/wave/UnreadDividerContext.tsx (3)
  • useUnreadDivider (55-61)
  • UnreadDividerProvider (21-53)
  • useUnreadDividerOptional (63-65)
components/drops/view/DropsList.tsx (1)
components/waves/drops/VirtualScrollWrapper.tsx (1)
  • VirtualScrollWrapper (56-181)
components/brain/left-sidebar/web/WebBrainLeftSidebarWave/subcomponents/WaveAvatar.tsx (1)
components/waves/WavePicture.tsx (1)
  • WavePicture (63-122)
components/waves/drops/WaveDropActionsMarkUnread.tsx (5)
generated/models/ApiDrop.ts (1)
  • ApiDrop (28-229)
components/auth/Auth.tsx (1)
  • useAuth (95-97)
contexts/wave/UnreadDividerContext.tsx (1)
  • useUnreadDividerOptional (63-65)
contexts/wave/MyStreamContext.tsx (1)
  • useMyStream (263-269)
generated/models/ApiMarkDropUnreadResponse.ts (1)
  • ApiMarkDropUnreadResponse (15-43)
components/waves/header/options/mute/WaveMute.tsx (2)
generated/models/ApiWave.ts (1)
  • ApiWave (27-179)
components/auth/Auth.tsx (1)
  • useAuth (95-97)
components/waves/header/options/WaveHeaderOptions.tsx (1)
components/waves/header/options/mute/WaveMute.tsx (1)
  • WaveMute (11-68)
__tests__/useWaveRealtimeUpdater.test.ts (1)
contexts/wave/hooks/useWaveRealtimeUpdater.ts (1)
  • useWaveRealtimeUpdater (38-324)
components/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsx (1)
contexts/wave/UnreadDividerContext.tsx (1)
  • useUnreadDivider (55-61)
contexts/wave/hooks/useActiveWaveManager.ts (1)
helpers/navigation.helpers.ts (1)
  • getWaveRoute (19-59)
__tests__/helpers/navigation.helpers.test.ts (1)
helpers/navigation.helpers.ts (2)
  • getWaveRoute (19-59)
  • getWaveHomeRoute (61-71)
__tests__/components/waves/specs/WaveNotificationSettings.test.tsx (1)
generated/models/ApiWave.ts (1)
  • ApiWave (27-179)
components/waves/drops/WaveDropActions.tsx (1)
components/waves/drops/WaveDropActionsMarkUnread.tsx (1)
  • WaveDropActionsMarkUnread (20-103)
components/waves/specs/WaveNotificationSettings.tsx (2)
generated/models/ApiWave.ts (1)
  • ApiWave (27-179)
contexts/SeizeSettingsContext.tsx (1)
  • useSeizeSettings (118-126)
contexts/wave/hooks/useEnhancedWavesListCore.ts (2)
contexts/wave/hooks/useNewDropCounter.ts (2)
  • MinimalWaveNewDropsCount (12-16)
  • getNewestTimestamp (18-35)
generated/models/ApiWave.ts (1)
  • ApiWave (27-179)
components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx (1)
helpers/navigation.helpers.ts (1)
  • getWaveRoute (19-59)
⏰ 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)

Comment thread __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
Comment thread components/brain/my-stream/MyStreamWaveChat.tsx Outdated
Comment thread components/waves/drops/WaveDropActionsMarkUnread.tsx Outdated
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: 2

🧹 Nitpick comments (4)
__tests__/components/drops/view/UnreadDivider.test.tsx (2)

15-19: Consider testing structure semantically rather than via Tailwind classes.

Querying by specific Tailwind CSS classes (.tw-h-0\.5.tw-bg-rose-500) makes the test brittle—if styling changes but the visual divider remains, the test breaks. Consider using a more semantic approach:

  • Add data-testid="divider-line" to each line element in the component, then query by test ID
  • Verify the component's semantic structure (e.g., check for role or container elements) instead of implementation details
🔎 Proposed refactor using data-testid
 it('renders horizontal lines', () => {
-  const { container } = render(<UnreadDivider />);
-  const lines = container.querySelectorAll(String.raw`.tw-h-0\.5.tw-bg-rose-500`);
+  render(<UnreadDivider />);
+  const lines = screen.getAllByTestId('divider-line');
   expect(lines.length).toBe(2);
 });

Then update the component to add data-testid="divider-line" to each horizontal line element.


4-20: Add accessibility tests for keyboard navigation and screen reader compatibility.

The component should verify that the divider doesn't break keyboard navigation and is appropriately exposed (or hidden) to assistive technologies. Consider adding tests for:

  • Proper ARIA role or landmark (e.g., separator role if semantically a divider)
  • Ensure the divider doesn't trap focus or interfere with tab order
  • Verify screen reader announcement (if applicable) or that decorative elements are properly hidden from accessibility tree

Based on learnings, as per coding guidelines for __tests__/**/components/**/*.test.{ts,tsx}.

🔎 Example accessibility test
it('is accessible and does not interfere with keyboard navigation', () => {
  render(<UnreadDivider />);
  const separator = screen.getByRole('separator', { hidden: true });
  expect(separator).toBeInTheDocument();
});

Adjust the role query based on the actual semantic structure of the UnreadDivider component.

__tests__/components/waves/header/WaveHeaderOptions.test.tsx (1)

22-22: Consider adding explicit type for better type safety.

The wave fixture uses as any which bypasses type checking. While acceptable in tests, an explicit interface or type would catch potential mismatches with the actual Wave type.

🔎 Example type-safe alternative
+type TestWave = Pick<Wave, 'id' | 'metrics'>;
+
-const wave = { id: 'w1', metrics: { muted: false } } as any;
+const wave: TestWave = { id: 'w1', metrics: { muted: false } };
components/waves/specs/WaveNotificationSettings.tsx (1)

16-18: Rename props interface to match component purpose.

The interface WaveRatingProps doesn't match the component name WaveNotificationSettings. This naming mismatch could confuse future developers.

🔎 Proposed fix
-interface WaveRatingProps {
+interface WaveNotificationSettingsProps {
   readonly wave: ApiWave;
 }

-export default function WaveNotificationSettings({ wave }: WaveRatingProps) {
+export default function WaveNotificationSettings({ wave }: WaveNotificationSettingsProps) {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 78c3b22 and 8aff57d.

📒 Files selected for processing (7)
  • __tests__/components/drops/view/UnreadDivider.test.tsx
  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • components/waves/specs/WaveNotificationSettings.tsx
  • contexts/wave/UnreadDividerContext.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/contexts/wave/UnreadDividerContext.test.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • contexts/wave/UnreadDividerContext.tsx
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{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 /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • components/waves/specs/WaveNotificationSettings.tsx
  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • __tests__/components/drops/view/UnreadDivider.test.tsx
**/*.{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 add readonly before props in React components

Files:

  • components/waves/specs/WaveNotificationSettings.tsx
  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.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 use next/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/specs/WaveNotificationSettings.tsx
  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • __tests__/components/drops/view/UnreadDivider.test.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
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.)
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

**/*.{ts,tsx}: Must pass tsc --noEmit for 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
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for 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 /> from next/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/specs/WaveNotificationSettings.tsx
  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • __tests__/components/drops/view/UnreadDivider.test.tsx
**/@(__tests__|*.test).{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Tests should live in __tests__/ or ComponentName.test.tsx; mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Place tests in __tests__/ directory or as ComponentName.test.tsx alongside components

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use Jest + ts-jest for TypeScript testing

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
__tests__/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (tests/AGENTS.md)

__tests__/**/*.{ts,tsx,js}: Prefer for...of loops over forEach as it allows break/continue and works with async/await
Use array.at(-1) and array.at(-2) instead of index-based array access for negative indexing
Use String.prototype.replaceAll() instead of replace() for global string replacements
Use globalThis.fetch() instead of direct fetch() calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Use element.remove() instead of parent.removeChild(element) for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use semantic HTML elements (<label>, <output>) over ARIA attributes when possible; every form control must have a label

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.tsx
🧠 Learnings (13)
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)

Applied to files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.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 **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Use testing-library/react + user-event for React component tests

Applied to files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.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 **/@(__tests__|*.test).{ts,tsx} : Tests should live in `__tests__/` or `ComponentName.test.tsx`; mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/components/drops/view/UnreadDivider.test.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:

  • __tests__/components/waves/header/WaveHeaderOptions.test.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:

  • contexts/wave/hooks/useEnhancedWavesListCore.ts
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/{components,contexts,hooks}/**/*.{ts,tsx} : Use semantic HTML elements (`<label>`, `<output>`) over ARIA attributes when possible; every form control must have a label

Applied to files:

  • __tests__/components/drops/view/UnreadDivider.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Test high-risk areas including happy path workflows, invalid input errors, edge cases/boundaries, component & API interactions, and performance/security when relevant

Applied to files:

  • __tests__/components/drops/view/UnreadDivider.test.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 **/__tests__/**/*.{ts,tsx} : Place tests in `__tests__/` directory or as `ComponentName.test.tsx` alongside components

Applied to files:

  • __tests__/components/drops/view/UnreadDivider.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Test accessibility with keyboard navigation and screen reader compatibility

Applied to files:

  • __tests__/components/drops/view/UnreadDivider.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx} : Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Applied to files:

  • __tests__/components/drops/view/UnreadDivider.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Write tests following Arrange – Act – Assert pattern with one behaviour per test and clear, descriptive names

Applied to files:

  • __tests__/components/drops/view/UnreadDivider.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : All tests must live in `__tests__`, mirroring source folders (`components`, `contexts`, `hooks`, `utils`)

Applied to files:

  • __tests__/components/drops/view/UnreadDivider.test.tsx
🧬 Code graph analysis (2)
components/waves/specs/WaveNotificationSettings.tsx (2)
generated/models/ApiWave.ts (1)
  • ApiWave (27-179)
contexts/SeizeSettingsContext.tsx (1)
  • useSeizeSettings (118-126)
contexts/wave/hooks/useEnhancedWavesListCore.ts (4)
contexts/wave/hooks/useEnhancedDmWavesList.ts (1)
  • MinimalWave (6-6)
contexts/wave/hooks/useEnhancedWavesList.ts (1)
  • MinimalWave (6-6)
contexts/wave/hooks/useNewDropCounter.ts (2)
  • MinimalWaveNewDropsCount (12-16)
  • getNewestTimestamp (18-35)
generated/models/ApiWave.ts (1)
  • ApiWave (27-179)
⏰ 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 (8)
__tests__/components/waves/header/WaveHeaderOptions.test.tsx (4)

4-4: LGTM!

The React Query imports are correctly added to provide the necessary context for components that use react-query hooks.


18-20: Consistent mock pattern for test isolation.

The WaveMute mock follows the same pattern as WaveDelete, enabling proper test isolation and prop verification.


24-31: LGTM!

The createWrapper helper follows React Query testing best practices by creating a fresh QueryClient with retry disabled for each test, preventing test pollution and ensuring deterministic behavior.


35-39: LGTM!

The test correctly uses the wrapper to provide React Query context and adds an appropriate assertion to verify the new mute option appears alongside the delete option.

contexts/wave/hooks/useEnhancedWavesListCore.ts (2)

176-184: LGTM!

Sorting by latest drop timestamp descending correctly surfaces recently active waves. The memo dependencies are correct.


186-216: LGTM!

The return memo properly includes all dependencies and exposes a stable API. The conditional pinning wiring based on supportsPinning is clean.

components/waves/specs/WaveNotificationSettings.tsx (2)

29-30: LGTM! State management correctly handles mute synchronization.

The combination of local state (lines 29-30) and sync effect (lines 41-43) provides a good balance between immediate UI feedback and server consistency. The optimistic update pattern ensures responsive UX while staying synchronized with backend state.

Also applies to: 41-43


45-72: LGTM! Mute functionality is well-implemented.

The implementation demonstrates solid patterns:

  • Error handling (lines 60-68): Contextual error messages differentiate mute vs unmute failures
  • Query invalidation (lines 54-59): Correctly targets both specific wave and overview caches
  • Loading states (line 30, 46, 70): Prevents race conditions from concurrent clicks
  • Accessibility (line 179): Proper aria-label for screen readers
  • Dependencies (line 72): All callback dependencies are correctly specified

The conditional rendering (lines 165-196) provides clear UX when a wave is muted.

Also applies to: 161-196

Comment thread __tests__/components/waves/header/WaveHeaderOptions.test.tsx Outdated
Comment thread contexts/wave/hooks/useEnhancedWavesListCore.ts
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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: 0

♻️ Duplicate comments (1)
contexts/wave/hooks/useEnhancedWavesListCore.ts (1)

156-156: The isPinned property access is now correct.

This addresses the previous review comment about using wave.pinned instead of the non-existent wave.isPinned.

🧹 Nitpick comments (2)
components/waves/header/options/mute/WaveMute.tsx (1)

23-50: Consider using Promise.all for cache invalidations.

The two invalidateQueries calls are independent and can run in parallel.

🔎 Proposed refactor
-      queryClient.invalidateQueries({
-        queryKey: [QueryKey.WAVE, { wave_id: wave.id }],
-      });
-      queryClient.invalidateQueries({
-        queryKey: [QueryKey.WAVES_OVERVIEW],
-      });
+      await Promise.all([
+        queryClient.invalidateQueries({
+          queryKey: [QueryKey.WAVE, { wave_id: wave.id }],
+        }),
+        queryClient.invalidateQueries({
+          queryKey: [QueryKey.WAVES_OVERVIEW],
+        }),
+      ]);
contexts/wave/hooks/useEnhancedWavesListCore.ts (1)

110-111: Simplify redundant type annotation.

The type ApiWave & { pinned?: boolean } is redundant since ApiWave already has pinned: boolean. The intersection with an optional version doesn't change the effective type.

🔎 Proposed fix
   const mapWave = useCallback(
-    (wave: ApiWave & { pinned?: boolean }): MinimalWave => {
+    (wave: ApiWave): MinimalWave => {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8aff57d and f633439.

📒 Files selected for processing (8)
  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • components/waves/drops/WaveDropActionsMarkUnread.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • contexts/wave/MyStreamContext.tsx
  • contexts/wave/hooks/useActiveWaveManager.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • components/waves/drops/WaveDropActionsMarkUnread.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • tests/contexts/wave/UnreadDividerContext.test.tsx
  • contexts/wave/hooks/useActiveWaveManager.ts
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{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 /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • contexts/wave/MyStreamContext.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.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 add readonly before props in React components

Files:

  • contexts/wave/MyStreamContext.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • __tests__/components/waves/header/WaveHeaderOptions.test.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 use next/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:

  • contexts/wave/MyStreamContext.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
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.)
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

**/*.{ts,tsx}: Must pass tsc --noEmit for 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
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for 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 /> from next/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:

  • contexts/wave/MyStreamContext.tsx
  • components/waves/header/options/mute/WaveMute.tsx
  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
**/@(__tests__|*.test).{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Tests should live in __tests__/ or ComponentName.test.tsx; mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Place tests in __tests__/ directory or as ComponentName.test.tsx alongside components

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use Jest + ts-jest for TypeScript testing

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
__tests__/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (tests/AGENTS.md)

__tests__/**/*.{ts,tsx,js}: Prefer for...of loops over forEach as it allows break/continue and works with async/await
Use array.at(-1) and array.at(-2) instead of index-based array access for negative indexing
Use String.prototype.replaceAll() instead of replace() for global string replacements
Use globalThis.fetch() instead of direct fetch() calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Use element.remove() instead of parent.removeChild(element) for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use semantic HTML elements (<label>, <output>) over ARIA attributes when possible; every form control must have a label

Files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
🧠 Learnings (10)
📚 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:

  • contexts/wave/MyStreamContext.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:

  • contexts/wave/MyStreamContext.tsx
  • __tests__/components/waves/header/WaveHeaderOptions.test.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:

  • contexts/wave/MyStreamContext.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 **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)

Applied to files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Use testing-library/react + user-event for React component tests

Applied to files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Test accessibility with keyboard navigation and screen reader compatibility

Applied to files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.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 **/*.{ts,tsx,js,jsx} : Do not include any comments in the code; it should be self-explanatory

Applied to files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx} : Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Applied to files:

  • __tests__/components/waves/header/WaveHeaderOptions.test.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:

  • __tests__/components/waves/header/WaveHeaderOptions.test.tsx
🧬 Code graph analysis (2)
components/waves/header/options/mute/WaveMute.tsx (2)
generated/models/ApiWave.ts (1)
  • ApiWave (27-179)
components/auth/Auth.tsx (1)
  • useAuth (95-97)
contexts/wave/hooks/useEnhancedWavesListCore.ts (3)
contexts/wave/hooks/useEnhancedDmWavesList.ts (2)
  • MinimalWave (6-6)
  • useEnhancedDmWavesList (9-68)
contexts/wave/hooks/useNewDropCounter.ts (2)
  • MinimalWaveNewDropsCount (12-16)
  • getNewestTimestamp (18-35)
generated/models/ApiWave.ts (1)
  • ApiWave (27-179)
⏰ 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 (14)
components/waves/header/options/mute/WaveMute.tsx (3)

1-10: LGTM!

Imports are well-organized with proper separation between external and internal modules.


11-21: LGTM!

Props correctly use readonly as per coding guidelines, and the component setup is clean.


52-67: LGTM!

The button correctly handles loading states, uses proper accessibility attributes (role="menuitem"), and prevents event propagation.

__tests__/components/waves/header/WaveHeaderOptions.test.tsx (2)

24-31: LGTM!

The createWrapper helper follows best practices by creating a fresh QueryClient per test invocation with retry: false to prevent flaky tests.


33-47: LGTM!

Test correctly verifies that both mute and delete options are rendered when the menu opens, and that the menu closes on click-away and escape key press.

contexts/wave/MyStreamContext.tsx (4)

120-131: LGTM!

The refs pattern is correctly used to avoid stale closures in isWaveMuted. The callback has no dependencies since it reads from refs that are always current.


44-44: LGTM!

The interface extension adds the new restoreWaveUnreadCount capability to the waves context.


49-56: LGTM!

The updated set signature uses an options object pattern which is extensible and maintains backward compatibility since the options parameter is optional.


184-260: LGTM!

The context value construction and memoization dependencies are comprehensive and correctly include the new restoreWaveUnreadCount properties for both waves and direct messages.

contexts/wave/hooks/useEnhancedWavesListCore.ts (5)

13-25: LGTM!

The MinimalWave interface is well-defined with all necessary fields for UI rendering including the new unread/muted state properties.


58-77: LGTM!

State management for cleared and forced unread counts is correctly implemented. The resetWaveUnreadCount properly clears both the cleared set and any forced count for the wave.


97-108: LGTM!

The debounced clearing of unread indicators with proper cleanup prevents flickering when navigating between waves and ensures the timeout is cancelled if the active wave changes before the delay completes.


122-145: LGTM!

The unread count calculation logic correctly handles the priority of states: cleared > forced > websocket new drops > API count. The firstUnreadDropSerialNo computation properly takes the minimum between API and websocket values when both exist.


186-216: LGTM!

The return value is properly memoized with all necessary dependencies, and the conditional pinning support correctly returns no-op functions when pinning is disabled.

Signed-off-by: prxt6529 <prxt@6529.io>
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: 0

♻️ Duplicate comments (1)
contexts/wave/hooks/useEnhancedWavesListCore.ts (1)

110-161: Fix conflicting type annotation for wave parameter.

Line 111 declares wave: ApiWave & { pinned?: boolean }, which creates a type conflict because ApiWave already defines pinned: boolean (non-optional). The intersection type with { pinned?: boolean } (optional) is contradictory and unnecessary.

🔎 Proposed fix
  const mapWave = useCallback(
-    (wave: ApiWave & { pinned?: boolean }): MinimalWave => {
+    (wave: ApiWave): MinimalWave => {
      const wsData = newDropsCounts[wave.id];
🧹 Nitpick comments (4)
hooks/useWaveWebSocket.ts (2)

45-48: Remove placeholder fallback URL and fail fast instead.

The fallback to "wss://default-fallback-url" violates the coding guideline: "fail fast if base origin is unavailable; do not fall back to placeholder origins". This placeholder could mask configuration issues.

🔎 Proposed fix to fail fast
-    const url =
-      publicEnv.WS_ENDPOINT ??
-      publicEnv.API_ENDPOINT?.replace("https://api", "wss://ws") ??
-      "wss://default-fallback-url";
+    const url =
+      publicEnv.WS_ENDPOINT ??
+      publicEnv.API_ENDPOINT?.replace("https://api", "wss://ws");
+
+    if (!url) {
+      console.error("WebSocket endpoint not configured");
+      setReadyState(WebSocket.CLOSED);
+      return;
+    }

As per coding guidelines, URLs should fail fast when the base origin is unavailable.


34-98: Consider removing inline comments per style guidelines.

The coding guidelines specify: "Do not include any comments in the code; it should be self-explanatory". While the comments aid understanding, consider whether the code can be made self-documenting through better naming or structure.

As per coding guidelines, code should be self-explanatory without comments.

hooks/useWaveIsTyping.ts (1)

11-136: Consider removing inline comments per style guidelines.

The coding guidelines specify: "Do not include any comments in the code; it should be self-explanatory". While the section dividers and inline comments aid understanding, consider whether clearer naming or structure could replace them.

As per coding guidelines, code should be self-explanatory without comments.

components/waves/drops/wave-drops-all/index.tsx (1)

58-58: Prefer direct import of FC type.

The coding guidelines recommend importing React types directly rather than using the React. namespace.

🔎 Suggested refactor

Update the import statement:

-import { useCallback, useEffect, useMemo, useRef, useState } from "react";
+import { useCallback, useEffect, useMemo, useRef, useState, FC } from "react";

Then update the component declarations:

-const WaveDropsAllInner: React.FC<WaveDropsAllInnerProps> = ({
+const WaveDropsAllInner: FC<WaveDropsAllInnerProps> = ({
-const WaveDropsAll: React.FC<WaveDropsAllProps> = ({
+const WaveDropsAll: FC<WaveDropsAllProps> = ({

As per coding guidelines: "Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") over React. namespace usage."

Also applies to: 334-334

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f633439 and 58d2cc5.

📒 Files selected for processing (9)
  • __tests__/contexts/wave/UnreadDividerContext.test.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • components/waves/drop/SingleWaveDropChat.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • contexts/wave/hooks/useNewDropCounter.ts
  • hooks/useWaveIsTyping.ts
  • hooks/useWaveWebSocket.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • tests/contexts/wave/UnreadDividerContext.test.tsx
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{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 /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • components/waves/drop/SingleWaveDropChat.tsx
  • hooks/useWaveIsTyping.ts
  • contexts/wave/hooks/useNewDropCounter.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • hooks/useWaveWebSocket.ts
  • components/waves/drops/wave-drops-all/index.tsx
**/*.{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 add readonly before props in React components

Files:

  • components/waves/drop/SingleWaveDropChat.tsx
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • components/waves/drops/wave-drops-all/index.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 use next/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/drop/SingleWaveDropChat.tsx
  • hooks/useWaveIsTyping.ts
  • contexts/wave/hooks/useNewDropCounter.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • hooks/useWaveWebSocket.ts
  • components/waves/drops/wave-drops-all/index.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
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.)
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

**/*.{ts,tsx}: Must pass tsc --noEmit for 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
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for 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 /> from next/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/drop/SingleWaveDropChat.tsx
  • hooks/useWaveIsTyping.ts
  • contexts/wave/hooks/useNewDropCounter.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
  • hooks/useWaveWebSocket.ts
  • components/waves/drops/wave-drops-all/index.tsx
**/@(__tests__|*.test).{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Tests should live in __tests__/ or ComponentName.test.tsx; mock external dependencies and APIs in tests

Files:

  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Place tests in __tests__/ directory or as ComponentName.test.tsx alongside components

Files:

  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use Jest + ts-jest for TypeScript testing

Files:

  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Files:

  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
__tests__/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (tests/AGENTS.md)

__tests__/**/*.{ts,tsx,js}: Prefer for...of loops over forEach as it allows break/continue and works with async/await
Use array.at(-1) and array.at(-2) instead of index-based array access for negative indexing
Use String.prototype.replaceAll() instead of replace() for global string replacements
Use globalThis.fetch() instead of direct fetch() calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Use element.remove() instead of parent.removeChild(element) for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)

Files:

  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use semantic HTML elements (<label>, <output>) over ARIA attributes when possible; every form control must have a label

Files:

  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
🧠 Learnings (2)
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)

Applied to files:

  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Keep tests independent, deterministic, and fast with production-like data

Applied to files:

  • __tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx
🧬 Code graph analysis (3)
hooks/useWaveIsTyping.ts (1)
hooks/useWaveWebSocket.ts (1)
  • useWaveWebSocket (27-119)
contexts/wave/hooks/useEnhancedWavesListCore.ts (2)
contexts/wave/hooks/useNewDropCounter.ts (2)
  • MinimalWaveNewDropsCount (12-16)
  • getNewestTimestamp (18-35)
generated/models/ApiWave.ts (1)
  • ApiWave (27-179)
components/waves/drops/wave-drops-all/index.tsx (2)
hooks/useVirtualizedWaveDrops.ts (1)
  • useVirtualizedWaveDrops (17-91)
contexts/wave/UnreadDividerContext.tsx (2)
  • useUnreadDivider (46-54)
  • UnreadDividerProvider (23-44)
⏰ 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 (24)
hooks/useWaveWebSocket.ts (2)

19-26: LGTM! Clear documentation of hook behavior.

The JSDoc accurately describes the subscription message behavior and the new waveId parameter semantics, including the disable-by-empty-string pattern.


35-42: LGTM! Proper lifecycle management for disabled state.

The empty waveId guard correctly tears down any existing connection and prevents new connections when the hook should be disabled. The cleanup logic properly closes the socket and updates state.

hooks/useWaveIsTyping.ts (2)

56-68: LGTM! Clean disabled flag implementation.

The new disabled parameter is well-documented and correctly implemented:

  • Backwards compatible with default value false
  • Properly leverages the empty waveId handling in useWaveWebSocket
  • Clear JSDoc explains the purpose (e.g., for muted waves)

74-77: LGTM! Correct dependency array.

The addition of disabled to the dependency array is correct. The effect should reset the typing state when either the wave changes or the disabled flag toggles.

__tests__/contexts/wave/hooks/useEnhancedWavesList.test.tsx (4)

21-79: LGTM! Test fixtures properly updated.

The test fixtures now include the unread-related fields (your_unread_drops_count, your_latest_read_timestamp, first_unread_drop_serial_no, muted), and the change from isPinned to pinned correctly aligns with the ApiWave model structure.


81-118: LGTM! Comprehensive test coverage for unread state mapping.

The test validates that unreadDropsCount, latestReadTimestamp, and firstUnreadDropSerialNo are correctly mapped from wave metrics, ensuring the core hook properly exposes unread state to consumers.


120-155: LGTM! Muted state mapping validated.

The test confirms that isMuted is correctly derived from wave.metrics.muted, which is essential for proper UI behavior of muted waves.


157-191: LGTM! Null handling for firstUnreadDropSerialNo verified.

The test ensures that when first_unread_drop_serial_no is undefined in metrics, the mapped field correctly becomes null, maintaining type safety and avoiding undefined values in the UI.

contexts/wave/hooks/useNewDropCounter.ts (3)

12-16: LGTM! Interface extended with firstUnreadSerialNo.

The firstUnreadSerialNo field correctly tracks the earliest unread drop, enabling precise navigation to the first unread message in the UI.


58-91: LGTM! Reset logic properly initializes firstUnreadSerialNo.

Both resetWaveNewDropsCount and resetAllWavesNewDropsCount correctly set firstUnreadSerialNo to null when clearing unread state, maintaining consistency across reset operations.


116-196: LGTM! WebSocket handling correctly maintains firstUnreadSerialNo.

The logic properly:

  • Returns early and refetches when wave is not found (Line 128)
  • Skips processing for muted waves (Line 131)
  • Preserves firstUnreadSerialNo for owner messages and active visible waves (Lines 149, 168)
  • Computes the minimum serial number for new unread drops (Lines 187-190), ensuring the field always points to the earliest unread message
contexts/wave/hooks/useEnhancedWavesListCore.ts (5)

13-25: LGTM! MinimalWave interface properly defines enriched wave structure.

The interface includes all necessary fields for UI rendering, including the new unread state fields (unreadDropsCount, latestReadTimestamp, firstUnreadDropSerialNo, isMuted), enabling comprehensive wave state management.


66-95: LGTM! Unread state management utilities.

resetWaveUnreadCount and restoreWaveUnreadCount provide fine-grained control over per-wave unread state, supporting both clearing and restoring with optional forced counts.


97-108: LGTM! Debounced unread clearing on active wave change.

The 1-second delay before clearing unread state for the active wave provides a better UX by allowing brief navigation away without losing unread indicators.


122-145: LGTM! Comprehensive unread count computation.

The logic correctly handles multiple scenarios:

  • Cleared state: unreadDropsCount = 0
  • Forced count: adds WebSocket drops to forced baseline
  • New WebSocket drops: adds to API unread count
  • Default: uses API unread count

This provides flexible unread state management across different use cases.


176-188: LGTM! Sorting respects muted state.

Waves are sorted with muted waves pushed to the bottom, then by latest drop timestamp. This ensures important conversations remain visible while de-emphasizing muted content.

components/waves/drop/SingleWaveDropChat.tsx (4)

19-22: LGTM: Interface follows guidelines.

The props interface correctly uses readonly modifiers as required by the coding guidelines for React components.


24-77: LGTM: Clean component logic and state management.

The hook usage, memoization, and state management follow React best practices. Dependencies are correctly specified and the logic is well-structured.


79-149: LGTM: Well-structured responsive layout.

The JSX structure properly handles responsive design with TailwindCSS, includes mobile-specific considerations (keyboard adjustments, safe area insets), and maintains clean component composition.


120-120: Property access is type-safe and guaranteed.

The metrics.muted property is a required (non-optional) field in both ApiWave and ApiWaveMetrics, so accessing wave.metrics.muted without optional chaining is correct and will always be present. TypeScript compilation will enforce this safety.

components/waves/drops/wave-drops-all/index.tsx (4)

29-56: LGTM! Well-structured interface definitions.

The addition of isMuted prop and the new WaveDropsAllInnerProps interface are well-designed. Using ReturnType to extract types from useVirtualizedWaveDrops is a good pattern that ensures type consistency between the hook and component props.


58-93: LGTM! Proper context integration.

The component correctly consumes the UnreadDividerProvider context via useUnreadDivider, and the isMuted prop is properly passed through to useWaveIsTyping.


113-154: LGTM! Solid unread divider state management.

The unread divider logic is well-implemented with proper state transitions:

  • Tracks when new drops arrive while user is scrolled up
  • Preserves the divider position at the first unread drop
  • Clears the divider when user scrolls back to bottom
  • Properly resets on wave or initialDrop changes

The use of refs (prevLatestSerialNoRef, wasNotAtBottomRef) and functional state updates prevents race conditions, and all effect dependencies are correct.


334-366: LGTM! Clean component composition pattern.

The outer wrapper correctly:

  • Extracts hook state from useVirtualizedWaveDrops
  • Wraps the inner component with UnreadDividerProvider
  • Uses a keyed provider (unread-divider-${waveId}) to ensure clean remounting on wave changes
  • Delegates all props and hook results to the inner component

This architecture enables proper context isolation and makes the component more testable.

Signed-off-by: prxt6529 <prxt@6529.io>
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

🧹 Nitpick comments (1)
__tests__/components/waves/drop/SingleWaveDropChat.test.tsx (1)

4-126: LGTM! Mock enhancements and test coverage are solid.

The ES module mock structure (__esModule: true) correctly handles default exports for Jest. The extended window.matchMedia mock with addEventListener, removeEventListener, and dispatchEvent improves API compatibility. Test cases are independent, deterministic, and properly verify component behavior including reply/reset actions and keyboard-driven padding adjustments.

Optional: Consider stronger typing for test data.

While any types are common in tests, you could improve type safety with more specific types or utility types like Pick<Wave, 'id'> for test fixtures. This remains a minor, deferrable refinement.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58d2cc5 and 2fa68a2.

📒 Files selected for processing (3)
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • components/waves/drop/SingleWaveDropChat.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • components/waves/drop/SingleWaveDropChat.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{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 /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/*.{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 add readonly before props in React components

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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 use next/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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
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.)
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

**/*.{ts,tsx}: Must pass tsc --noEmit for 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
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for 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 /> from next/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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/@(__tests__|*.test).{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Tests should live in __tests__/ or ComponentName.test.tsx; mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Place tests in __tests__/ directory or as ComponentName.test.tsx alongside components

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use Jest + ts-jest for TypeScript testing

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (tests/AGENTS.md)

__tests__/**/*.{ts,tsx,js}: Prefer for...of loops over forEach as it allows break/continue and works with async/await
Use array.at(-1) and array.at(-2) instead of index-based array access for negative indexing
Use String.prototype.replaceAll() instead of replace() for global string replacements
Use globalThis.fetch() instead of direct fetch() calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Use element.remove() instead of parent.removeChild(element) for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use semantic HTML elements (<label>, <output>) over ARIA attributes when possible; every form control must have a label

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
🧠 Learnings (13)
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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 **/@(__tests__|*.test).{ts,tsx} : Tests should live in `__tests__/` or `ComponentName.test.tsx`; mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Organize imports with one import per module in order: external → internal → types, with no duplicates

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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 **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Test high-risk areas including happy path workflows, invalid input errors, edge cases/boundaries, component & API interactions, and performance/security when relevant

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Use testing-library/react + user-event for React component tests

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/{components,contexts,hooks}/**/*.{ts,tsx} : Use semantic HTML elements (`<label>`, `<output>`) over ARIA attributes when possible; every form control must have a label

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Keep tests independent, deterministic, and fast with production-like data

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Use `String.prototype.replaceAll()` instead of `replace()` for global string replacements

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Test accessibility with keyboard navigation and screen reader compatibility

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
🧬 Code graph analysis (1)
__tests__/components/waves/drop/SingleWaveDropChat.test.tsx (1)
components/waves/drop/SingleWaveDropChat.tsx (1)
  • SingleWaveDropChat (24-150)
⏰ 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)

Comment thread __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
Signed-off-by: prxt6529 <prxt@6529.io>
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: 0

♻️ Duplicate comments (1)
__tests__/components/waves/drop/SingleWaveDropChat.test.tsx (1)

1-2: Reorder imports: external libraries before internal modules.

The import order violates the coding guideline. External library imports should precede internal module imports.

Based on learnings, organize imports with one import per module in order: external → internal → types.

🧹 Nitpick comments (4)
__tests__/components/waves/drop/SingleWaveDropChat.test.tsx (4)

11-11: Consider removing the comment for self-explanatory code.

The variable names mockKeyboardVisible and mockGetContainerStyle clearly indicate the mock's purpose.

As per coding guidelines, code should be self-explanatory without comments.

🔎 Proposed change
-
-// Mock useAndroidKeyboard with configurable values
 let mockKeyboardVisible = false;

58-58: Consider removing the comment for self-explanatory code.

The mock setup for globalThis.matchMedia is clear from the implementation itself.

As per coding guidelines, code should be self-explanatory without comments.

🔎 Proposed change
-
-// Mock globalThis.matchMedia for useDeviceInfo hook
 Object.defineProperty(globalThis, "matchMedia", {

102-102: Consider removing the redundant comment.

The test description and assertion already clearly convey that getContainerStyle should be called with paddingBottom: "0px".

As per coding guidelines, code should be self-explanatory without comments.

🔎 Proposed change
 
-    // getContainerStyle should have been called with paddingBottom: "0px"
     expect(mockGetContainerStyle).toHaveBeenCalledWith(

118-118: Consider removing the redundant comment.

The test description and assertion already clearly convey that getContainerStyle should be called with safe-area-inset-bottom padding.

As per coding guidelines, code should be self-explanatory without comments.

🔎 Proposed change
 
-    // getContainerStyle should have been called with paddingBottom: safe-area-inset-bottom
     expect(mockGetContainerStyle).toHaveBeenCalledWith(
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2fa68a2 and 222683a.

📒 Files selected for processing (1)
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{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 /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/*.{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 add readonly before props in React components

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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 use next/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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
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.)
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

**/*.{ts,tsx}: Must pass tsc --noEmit for 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
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for 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 /> from next/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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/@(__tests__|*.test).{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Tests should live in __tests__/ or ComponentName.test.tsx; mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Place tests in __tests__/ directory or as ComponentName.test.tsx alongside components

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use Jest + ts-jest for TypeScript testing

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (tests/AGENTS.md)

__tests__/**/*.{ts,tsx,js}: Prefer for...of loops over forEach as it allows break/continue and works with async/await
Use array.at(-1) and array.at(-2) instead of index-based array access for negative indexing
Use String.prototype.replaceAll() instead of replace() for global string replacements
Use globalThis.fetch() instead of direct fetch() calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Use element.remove() instead of parent.removeChild(element) for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (tests/AGENTS.md)

Use semantic HTML elements (<label>, <output>) over ARIA attributes when possible; every form control must have a label

Files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
🧠 Learnings (16)
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Organize imports with one import per module in order: external → internal → types, with no duplicates

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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 **/@(__tests__|*.test).{ts,tsx} : Tests should live in `__tests__/` or `ComponentName.test.tsx`; mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/{components,contexts,hooks}/**/*.{ts,tsx} : Use semantic HTML elements (`<label>`, `<output>`) over ARIA attributes when possible; every form control must have a label

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Test high-risk areas including happy path workflows, invalid input errors, edge cases/boundaries, component & API interactions, and performance/security when relevant

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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 **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Use testing-library/react + user-event for React component tests

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Use `String.prototype.replaceAll()` instead of `replace()` for global string replacements

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Test accessibility with keyboard navigation and screen reader compatibility

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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 **/*.{ts,tsx,js,jsx} : Include all required imports and ensure proper naming of key components

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx} : Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : All tests must live in `__tests__`, mirroring source folders (`components`, `contexts`, `hooks`, `utils`)

Applied to files:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.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:

  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
🧬 Code graph analysis (1)
__tests__/components/waves/drop/SingleWaveDropChat.test.tsx (1)
components/waves/drop/SingleWaveDropChat.tsx (1)
  • SingleWaveDropChat (24-150)
⏰ 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 (10)
__tests__/components/waves/drop/SingleWaveDropChat.test.tsx (10)

4-9: LGTM!

The mock setup for useCapacitor and LayoutContext is clean and correctly structured.


15-22: LGTM!

The useAndroidKeyboard mock correctly implements all required properties with configurable test values.


24-32: LGTM!

The wave-drops-all mock correctly uses ES module format and captures props for test inspection.


34-39: LGTM!

The CreateDropWaveWrapper mock correctly exports both the component and context with appropriate test structure.


41-56: LGTM!

The PrivilegedDropCreator mock properly uses ES module format and exposes props through data attributes for test verification.


59-71: LGTM!

The globalThis.matchMedia mock comprehensively implements the MediaQueryList interface with all necessary methods.


73-79: LGTM!

The test setup properly resets mock state in beforeEach to ensure test isolation.


80-93: LGTM!

The test correctly verifies reply and reset actions using captured props and data attribute assertions.


95-109: LGTM!

The test correctly verifies that keyboard visibility applies zero padding to the container.


111-125: LGTM!

The test correctly verifies that when the keyboard is hidden, safe-area-inset-bottom padding is applied.

Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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: 2

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6baecd and 0e9a858.

📒 Files selected for processing (8)
  • __tests__/components/waves/drop/SingleWaveDropChat.test.tsx
  • components/waves/drop/SingleWaveDropChat.tsx
  • components/waves/drops/WaveDropActions.tsx
  • components/waves/drops/WaveDropActionsOptions.tsx
  • components/waves/drops/WaveDropMobileMenu.tsx
  • 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
🚧 Files skipped from review as they are similar to previous changes (5)
  • components/waves/drops/WaveDropActionsOptions.tsx
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsMessageListSection.tsx
  • tests/components/waves/drop/SingleWaveDropChat.test.tsx
  • components/waves/drops/WaveDropActions.tsx
  • components/waves/drops/wave-drops-all/subcomponents/WaveDropsContent.tsx
🧰 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 /> from next/image to satisfy @next/next/no-img-element ESLint rule
Use <Link href="/path"> from Next.js for internal navigation instead of plain HTML links to satisfy @next/next/no-html-link-for-pages ESLint rule

Files:

  • components/waves/drops/WaveDropMobileMenu.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/waves/drop/SingleWaveDropChat.tsx
**/*.{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 add readonly before props in React components

Files:

  • components/waves/drops/WaveDropMobileMenu.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/waves/drop/SingleWaveDropChat.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 use next/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/WaveDropMobileMenu.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/waves/drop/SingleWaveDropChat.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Must pass tsc --noEmit type checking
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.)
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

**/*.{ts,tsx}: Must pass tsc --noEmit for 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
Use useEffectEvent for non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs: <Link> for internal links, next/image for 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 /> from next/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/WaveDropMobileMenu.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/waves/drop/SingleWaveDropChat.tsx
🧠 Learnings (3)
📚 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/waves/drops/WaveDropMobileMenu.tsx
  • 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 TypeScript and React functional components with hooks

Applied to files:

  • components/waves/drops/WaveDropMobileMenu.tsx
  • 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: TypeScript + React functional components with hooks; follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)

Applied to files:

  • components/waves/drops/WaveDropMobileMenu.tsx
  • components/waves/drops/wave-drops-all/index.tsx
🧬 Code graph analysis (2)
components/waves/drops/WaveDropMobileMenu.tsx (1)
components/waves/drops/WaveDropActionsMarkUnread.tsx (1)
  • WaveDropActionsMarkUnread (22-151)
components/waves/drops/wave-drops-all/index.tsx (6)
hooks/useVirtualizedWaveDrops.ts (1)
  • useVirtualizedWaveDrops (17-91)
__mocks__/react-use.js (1)
  • React (2-2)
contexts/wave/UnreadDividerContext.tsx (2)
  • useUnreadDivider (46-54)
  • UnreadDividerProvider (23-44)
hooks/useWaveIsTyping.ts (1)
  • useWaveIsTyping (63-139)
components/waves/drops/wave-drops-all/hooks/useWaveDropsSerialScroll.ts (1)
  • useWaveDropsSerialScroll (38-287)
helpers/waves/wave.helpers.ts (1)
  • isWaveDirectMessage (15-25)
⏰ 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 (4)
components/waves/drops/WaveDropMobileMenu.tsx (2)

3-4: LGTM! Import organization is clean.

The import statements are properly organized and all imports are utilized within the component. The addition of WaveDropActionsMarkUnread supports the new mark-as-unread functionality.

Also applies to: 8-8, 10-11, 13-13


249-253: LGTM! Mark-as-unread integration is correct.

The WaveDropActionsMarkUnread component is properly integrated with the correct props:

  • drop provides the necessary drop data
  • isMobile={true} matches the mobile menu context
  • onMarkUnread={closeMenu} ensures the menu closes after the action completes

The component handles its own visibility logic (returning null for authors or when no profile is connected), so no parent-level conditional is needed.

components/waves/drop/SingleWaveDropChat.tsx (1)

101-101: LGTM! Correct mute state propagation.

The addition correctly passes the wave's mute state to WaveDropsAll using safe navigation and an appropriate fallback.

components/waves/drops/wave-drops-all/index.tsx (1)

124-163: LGTM! Well-structured unread divider state management.

The logic correctly handles:

  • Resetting state when wave or initial drop changes
  • Setting the divider when new messages arrive while scrolled up
  • Clearing the divider when the user scrolls back to the bottom

The use of refs to track previous state and scroll position is appropriate.

Comment thread components/waves/drops/wave-drops-all/index.tsx
Comment thread components/waves/drops/wave-drops-all/index.tsx
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
@sonarqubecloud
Copy link
Copy Markdown

@prxt6529 prxt6529 merged commit 2f8a1d1 into main Dec 30, 2025
8 checks passed
This was referenced Dec 31, 2025
@coderabbitai coderabbitai Bot mentioned this pull request Jan 7, 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