Skip to content

Unread divider fix#1688

Merged
prxt6529 merged 7 commits intomainfrom
unread-divider-fix
Dec 31, 2025
Merged

Unread divider fix#1688
prxt6529 merged 7 commits intomainfrom
unread-divider-fix

Conversation

@prxt6529
Copy link
Copy Markdown
Collaborator

@prxt6529 prxt6529 commented Dec 31, 2025

Summary by CodeRabbit

  • New Features

    • Unread-divider is now threaded through navigation and components so URLs can preserve and restore the first-unread position.
  • Bug Fixes

    • Fixes unread-count and first-unread determination after clearing a wave when new messages arrive.
  • Refactor

    • Improved wave navigation and state handling for more reliable unread-marker behavior and consistent jump-to-unread across views.

✏️ 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 31, 2025

📝 Walkthrough

Walkthrough

Threads a new optional divider (first-unread drop serial) through navigation and state: getWaveRoute/useWaveNavigation and active-wave APIs accept/divert divider, MyStreamWave/Chat surface firstUnreadSerialNo and parse divider, WaveDropsAll accepts dividerSerialNo prop and initializes unread-divider from it; enhanced-waves handling updated for cleared waves. (47 words)

Changes

Cohort / File(s) Summary
Left Sidebar Navigation
components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
Compute href with extraParams.divider from wave.firstUnreadDropSerialNo; replace activeWave.set with setActiveWave and call it with a second-param divider; minor import/order and formatting tweaks.
Web Navigation Hook
components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
setActiveWave options type extended to include `divider?: number
MyStream Wave Components
components/brain/my-stream/MyStreamWave.tsx, components/brain/my-stream/MyStreamWaveChat.tsx
MyStreamWave derives and passes firstUnreadSerialNo to chat; MyStreamWaveChat accepts firstUnreadSerialNo, parses divider query param (falls back to firstUnreadSerialNo), tracks dividerSerialNo in state, and forwards dividerTarget to drops rendering.
Wave Rendering
components/waves/drops/wave-drops-all/index.tsx
Add `dividerSerialNo?: number
Active Wave Navigation Context
contexts/wave/hooks/useActiveWaveManager.ts, contexts/wave/MyStreamContext.tsx
Add `divider?: number
Enhanced Waves List Logic
contexts/wave/hooks/useEnhancedWavesListCore.ts
Add wasCleared handling: when a cleared wave receives new WS drops, prefer WS-first firstUnreadDropSerialNo and use WS-only unread count logic.
Create Drop Content (load change)
components/waves/CreateDropContent.tsx
Replace Suspense-wrapped TermsSignatureFlow with Next.js dynamic import (loading: () => null); formatting/indent-only changes elsewhere.
Tests
__tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
Update expectations to include divider field in setActiveWave call and divider query param included in generated href when applicable.

Sequence Diagram

sequenceDiagram
    autonumber
    participant User
    participant LSidebar as Left Sidebar (BrainLeftSidebarWave)
    participant Nav as useWaveNavigation / ActiveWaveManager
    participant WaveChat as MyStreamWaveChat
    participant Drops as WaveDropsAll

    User->>LSidebar: click wave item
    LSidebar->>LSidebar: read wave.firstUnreadDropSerialNo
    LSidebar->>Nav: setActiveWave(waveId, { serialNo, divider })
    Nav->>Nav: build URL with divider as query param (when provided)
    Nav-->>WaveChat: route/component updated (URL includes divider)
    WaveChat->>WaveChat: parse divider from URL or use firstUnreadSerialNo
    WaveChat->>Drops: render with dividerSerialNo prop
    Drops->>Drops: initialize unread-divider from dividerSerialNo
    Drops-->>User: render drops with divider marker
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • ragnep

Poem

🐇✨ I hop from sidebar to stream so bright,
I tuck a little divider in sight.
First unread marked, a quiet little sign,
Guiding readers back through every line.
Hooray — one small hop, one clearer find!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Unread divider fix' directly describes the main changes in the PR, which focus on introducing divider-related props and logic for tracking unread drops across multiple components.
✨ Finishing touches
  • 📝 Generate docstrings

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.

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

Caution

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

⚠️ Outside diff range comments (1)
components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts (1)

7-10: Type definition is out of sync with actual usage.

The setActiveWave callback type doesn't include divider in its options, but line 84 passes divider. Update the type to match actual usage:

🔎 Proposed fix
   readonly setActiveWave: (
     waveId: string | null,
-    options?: { isDirectMessage?: boolean; serialNo?: number | null }
+    options?: { isDirectMessage?: boolean; serialNo?: number | null; divider?: number | null }
   ) => void;
🧹 Nitpick comments (1)
components/brain/my-stream/MyStreamWave.tsx (1)

48-48: Remove comment per coding guidelines.

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

🔎 Proposed fix
-  // Get enhanced data from the waves list (has correct WS-updated values)
   const enhancedData = useMemo(() => {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0c23a0 and 5d025bd.

📒 Files selected for processing (7)
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/brain/my-stream/MyStreamWave.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • contexts/wave/hooks/useActiveWaveManager.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{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}: Remove unnecessary Effects. If the Effect's only job is to derive or sync internal state, calculate during render or use useMemo instead.
Use useEffectEvent for non-reactive logic inside Effects to read the latest props/state without turning them into dependencies or causing unnecessary re-runs.
Use explicit caching with "use cache" directive at the top of Server Components, routes, or functions. Configure cacheComponents: true in next.config.ts as needed.

**/*.{ts,tsx,js,jsx}: Remove unnecessary Effects; if the Effect only derives state, compute during render instead
Use useEffectEvent when listening to external events but needing the latest props/state without re-running the Effect
Move data fetching from client Effects to Server Components; mutations go through Server Actions ('use server')

Files:

  • components/brain/my-stream/MyStreamWave.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • contexts/wave/hooks/useActiveWaveManager.ts
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/my-stream/MyStreamWaveChat.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

**/*.{tsx,jsx}: Use internal links via <Link> component from Next.js instead of <a> tags
Replace <img> elements with <Image /> from next/image

Files:

  • components/brain/my-stream/MyStreamWave.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Run npm run lint to ensure code satisfies ESLint (Next's Core Web Vitals + React Hooks). Code must pass linting before completing any task.

**/*.{js,ts,jsx,tsx}: Code must satisfy ESLint with Next's Core Web Vitals and React Hooks rules by running npm run lint
Do not add eslint-disable comments unless explicitly instructed; prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions

Files:

  • components/brain/my-stream/MyStreamWave.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • contexts/wave/hooks/useActiveWaveManager.ts
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

**/*.{jsx,tsx}: Replace <img> elements with <Image /> from next/image to comply with Next.js ESLint rule @next/next/no-img-element.
Use <Link href="/path"> from Next.js for internal navigation instead of raw <a> tags to comply with @next/next/no-html-link-for-pages.

Files:

  • components/brain/my-stream/MyStreamWave.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Use TypeScript with React functional components and hooks. Follow existing code style and naming conventions.

Files:

  • components/brain/my-stream/MyStreamWave.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • contexts/wave/hooks/useActiveWaveManager.ts
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with React functional components and hooks

Files:

  • components/brain/my-stream/MyStreamWave.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • contexts/wave/hooks/useActiveWaveManager.ts
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer direct named imports from React (useMemo, useRef, FC) over React. namespace usage

Files:

  • components/brain/my-stream/MyStreamWave.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • contexts/wave/hooks/useActiveWaveManager.ts
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/waves/drops/wave-drops-all/index.tsx
  • components/brain/my-stream/MyStreamWaveChat.tsx
**/*.{ts,js}

📄 CodeRabbit inference engine (AGENTS.md)

When parsing Seize URLs or similar, fail fast if base origin is unavailable instead of falling back to placeholder origins

Files:

  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • contexts/wave/hooks/useEnhancedWavesListCore.ts
  • contexts/wave/hooks/useActiveWaveManager.ts
🧠 Learnings (1)
📚 Learning: 2025-12-30T14:32:19.339Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T14:32:19.339Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : Prefer direct named imports from React (`useMemo`, `useRef`, `FC`) over `React.` namespace usage

Applied to files:

  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
🧬 Code graph analysis (2)
contexts/wave/hooks/useActiveWaveManager.ts (1)
helpers/navigation.helpers.ts (1)
  • getWaveRoute (19-59)
components/brain/my-stream/MyStreamWaveChat.tsx (2)
generated/models/ApiWave.ts (1)
  • ApiWave (27-179)
helpers/navigation.helpers.ts (1)
  • getHomeFeedRoute (11-11)
⏰ 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 (13)
contexts/wave/hooks/useActiveWaveManager.ts (1)

47-68: LGTM!

The divider handling is well-integrated into the URL building flow. The nullish check before string conversion properly excludes the param when not provided.

components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts (1)

45-52: LGTM!

The URL construction correctly sets both serialNo and divider params when firstUnreadDropSerialNo exists, maintaining consistency with navigation behavior across the PR.

components/brain/my-stream/MyStreamWave.tsx (1)

49-57: LGTM!

The enhanced data retrieval cleanly extracts both newDropsCount and firstUnreadSerialNo from the waves list, correctly handling the fallback to directMessages.list.

components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx (2)

65-77: LGTM!

The route construction correctly includes the divider extraParam when firstUnreadDropSerialNo is available, maintaining consistency with the navigation pattern established in this PR.


100-104: LGTM!

The divider is correctly passed to activeWave.set alongside serialNo, enabling consistent divider tracking when switching waves.

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

126-136: LGTM!

The wasCleared && hasNewWsDrops condition correctly handles the edge case where new WebSocket drops arrive after a user clears unread state. Using only wsFirstUnread in this case prevents stale API data from incorrectly marking older drops as unread.


143-144: LGTM!

Consistent with the firstUnreadDropSerialNo logic above—when the wave was cleared and new WS drops exist, the count should only reflect the new WS drops, not the stale API metrics.

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

48-48: LGTM!

The new dividerSerialNo prop provides external control over the unread divider position, enabling the fix for consistent divider behavior when navigating to waves.


113-117: LGTM!

The effect correctly resets the unread divider state when waveId or dividerSerialNo changes, ensuring the divider is properly initialized on wave navigation.


323-339: LGTM!

The UnreadDividerProvider is correctly initialized with dividerSerialNo ?? null, and the prop is properly threaded to WaveDropsAllInner for the inner effect to synchronize state.

components/brain/my-stream/MyStreamWaveChat.tsx (3)

50-56: LGTM!

The scrollTarget and dividerTarget computation correctly separates scroll position from divider position, with proper fallback to firstUnreadSerialNo when no explicit divider state exists for the current wave.


69-82: LGTM!

The divider parsing logic correctly handles:

  1. Explicit divider query param → parsed value
  2. Missing/invalid divider → fallback to firstUnreadSerialNo

This ensures consistent divider positioning whether arriving via URL navigation or direct wave selection.


144-154: LGTM!

The prop mapping is correct: scrollTarget drives the initial scroll position (initialDrop) while dividerTarget drives the visual unread divider (dividerSerialNo), allowing independent control of scroll vs. divider behavior.

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

Caution

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

⚠️ Outside diff range comments (1)
contexts/wave/MyStreamContext.tsx (1)

47-58: Fix type inconsistency for the divider parameter across context and hook files.

The divider parameter type is inconsistent:

  • MyStreamContext.tsx (line 55): divider?: number | string | null
  • useWaveNavigation.ts (line 12): divider?: number | null
  • useActiveWaveManager.ts: divider?: number | string | null

Since actual usages only pass numbers (e.g., firstUnreadDropSerialNo), align all type definitions to divider?: number | null for consistency. Update MyStreamContext and useActiveWaveManager to remove the string type option.

🧹 Nitpick comments (2)
components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts (1)

85-89: Consider the use of undefined vs null for optional divider values.

The divider is set to undefined when nextWaveId is falsy, but the type signature allows number | null. Ensure consistent handling of missing values throughout the codebase - prefer either null or undefined consistently.

components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx (1)

49-57: Consider separating formatting changes from functional changes.

These string slicing changes appear to be pure formatting with no behavioral impact. While not incorrect, mixing formatting changes with functional changes can make PRs harder to review. Consider using a separate commit for formatter output or style-only changes.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d025bd and 2bdd007.

📒 Files selected for processing (4)
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/waves/CreateDropContent.tsx
  • contexts/wave/MyStreamContext.tsx
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{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}: Remove unnecessary Effects. If the Effect's only job is to derive or sync internal state, calculate during render or use useMemo instead.
Use useEffectEvent for non-reactive logic inside Effects to read the latest props/state without turning them into dependencies or causing unnecessary re-runs.
Use explicit caching with "use cache" directive at the top of Server Components, routes, or functions. Configure cacheComponents: true in next.config.ts as needed.

**/*.{ts,tsx,js,jsx}: Remove unnecessary Effects; if the Effect only derives state, compute during render instead
Use useEffectEvent when listening to external events but needing the latest props/state without re-running the Effect
Move data fetching from client Effects to Server Components; mutations go through Server Actions ('use server')

Files:

  • contexts/wave/MyStreamContext.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/waves/CreateDropContent.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

**/*.{tsx,jsx}: Use internal links via <Link> component from Next.js instead of <a> tags
Replace <img> elements with <Image /> from next/image

Files:

  • contexts/wave/MyStreamContext.tsx
  • components/waves/CreateDropContent.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Run npm run lint to ensure code satisfies ESLint (Next's Core Web Vitals + React Hooks). Code must pass linting before completing any task.

**/*.{js,ts,jsx,tsx}: Code must satisfy ESLint with Next's Core Web Vitals and React Hooks rules by running npm run lint
Do not add eslint-disable comments unless explicitly instructed; prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions

Files:

  • contexts/wave/MyStreamContext.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/waves/CreateDropContent.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

**/*.{jsx,tsx}: Replace <img> elements with <Image /> from next/image to comply with Next.js ESLint rule @next/next/no-img-element.
Use <Link href="/path"> from Next.js for internal navigation instead of raw <a> tags to comply with @next/next/no-html-link-for-pages.

Files:

  • contexts/wave/MyStreamContext.tsx
  • components/waves/CreateDropContent.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Use TypeScript with React functional components and hooks. Follow existing code style and naming conventions.

Files:

  • contexts/wave/MyStreamContext.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/waves/CreateDropContent.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with React functional components and hooks

Files:

  • contexts/wave/MyStreamContext.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/waves/CreateDropContent.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer direct named imports from React (useMemo, useRef, FC) over React. namespace usage

Files:

  • contexts/wave/MyStreamContext.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • components/waves/CreateDropContent.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{ts,js}

📄 CodeRabbit inference engine (AGENTS.md)

When parsing Seize URLs or similar, fail fast if base origin is unavailable instead of falling back to placeholder origins

Files:

  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
🧠 Learnings (3)
📚 Learning: 2025-12-30T14:32:19.339Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T14:32:19.339Z
Learning: Applies to **/*.{tsx,ts,jsx,js} : Prefer direct named imports from React (`useMemo`, `useRef`, `FC`) over `React.` namespace usage

Applied to files:

  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
📚 Learning: 2025-12-30T14:31:52.994Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-30T14:31:52.994Z
Learning: Fix issues with modernization aligned to React 19.2, React Compiler, and Next.js 16 conventions. Do not add `// eslint-disable` comments unless explicitly instructed.

Applied to files:

  • components/waves/CreateDropContent.tsx
📚 Learning: 2025-12-30T14:32:19.339Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T14:32:19.339Z
Learning: Applies to **/*.{tsx,ts} : Use TypeScript with React functional components and hooks

Applied to files:

  • components/waves/CreateDropContent.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
🧬 Code graph analysis (2)
components/waves/CreateDropContent.tsx (7)
app/layout.tsx (1)
  • metadata (23-23)
components/waves/drops/normalizeDropMarkdown.ts (1)
  • exportDropMarkdown (80-89)
components/drops/create/lexical/transformers/MentionTransformer.ts (1)
  • MENTION_TRANSFORMER (4-32)
components/drops/create/lexical/transformers/HastagTransformer.ts (1)
  • HASHTAG_TRANSFORMER (4-32)
components/drops/create/lexical/transformers/ImageTransformer.ts (1)
  • IMAGE_TRANSFORMER (4-22)
components/drops/create/lexical/transformers/EmojiTransformer.ts (1)
  • EMOJI_TRANSFORMER (6-27)
helpers/Helpers.ts (1)
  • MAX_DROP_UPLOAD_FILES (27-27)
components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx (2)
helpers/Helpers.ts (2)
  • isValidEthAddress (262-263)
  • formatAddress (32-47)
helpers/navigation.helpers.ts (2)
  • getWaveHomeRoute (61-71)
  • 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)
🔇 Additional comments (8)
components/waves/CreateDropContent.tsx (5)

77-80: LGTM! Appropriate use of dynamic import for modal component.

The switch from Suspense-wrapped static import to Next.js dynamic() is a good pattern for code-splitting this terms modal. Using loading: () => null is appropriate since the component appears on demand via a custom event.

If TermsSignatureFlow is purely client-side (wallet signing logic), you could optionally add ssr: false to skip server-side rendering entirely, though the current approach works correctly.


82-103: LGTM! Good use of readonly for immutable fields.

The readonly modifiers correctly distinguish between immutable fields (id, type, required) and mutable fields (key, value). This aligns with TypeScript best practices.


379-382: Formatting changes only.

These are whitespace/indentation adjustments with no functional impact.

Also applies to: 407-411


988-996: LGTM! Proper useCallback implementation.

The callback is correctly memoized with isWideContainer as a dependency, which is appropriate since it's referenced in the conditional logic.


495-506: Formatting changes and dynamic component usage look good.

The remaining changes are whitespace/indentation adjustments. The <TermsSignatureFlow /> at line 1199 correctly uses the dynamically imported component.

Also applies to: 648-664, 1199-1199

components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx (2)

69-77: Implementation looks correct for adding divider to route.

The conditional addition of extraParams with the divider value is correctly implemented. The string conversion is appropriate for URL parameters, and the logic properly handles the case when firstUnreadDropSerialNo is absent.

Note: The same serialNo and divider redundancy concern mentioned in useWaveNavigation.ts applies here.


113-117: LGTM: setActiveWave call correctly includes divider option.

The addition of the divider parameter to the setActiveWave call is consistent with the PR's objective to track first-unread drop serial numbers through navigation.

components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts (1)

51-54: Parameters serve different purposes and are not redundant.

serialNo and divider are intentionally set to the same value but serve distinct purposes. serialNo is used for navigation and scroll targeting to a specific drop, while divider indicates where the unread divider should be rendered in the UI. This pattern is reflected throughout the codebase (e.g., in MyStreamWaveChat.tsx where InitialDropState contains separate serialNo and dividerSerialNo fields, and in wave-drops-all/index.tsx where dividerSerialNo is passed to UnreadDividerProvider).

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

🧹 Nitpick comments (1)
components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx (1)

98-127: Consider clarifying the relationship between serialNo and divider.

Both serialNo and divider are set to wave.firstUnreadDropSerialNo when nextWaveId is truthy. If these values are intentionally coupled (i.e., the unread divider always corresponds to the serial number to navigate to), this is fine. However, if they could diverge in future use cases, consider adding a brief inline explanation or extracting to a named variable for clarity.

The modifier key handling (meta, ctrl, shift, alt, middle-click) is comprehensive and correctly allows native browser navigation behavior.

🔎 Optional: Extract shared value for clarity
      const nextWaveId = wave.id === activeWaveId ? null : wave.id;
+      const unreadSerial = nextWaveId ? wave.firstUnreadDropSerialNo : null;
      setActiveWave(nextWaveId, {
        isDirectMessage,
-        serialNo: nextWaveId ? wave.firstUnreadDropSerialNo : null,
-        divider: nextWaveId ? wave.firstUnreadDropSerialNo : null,
+        serialNo: unreadSerial,
+        divider: unreadSerial,
      });
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2bdd007 and 6d0b6be.

📒 Files selected for processing (5)
  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • contexts/wave/MyStreamContext.tsx
  • contexts/wave/hooks/useActiveWaveManager.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • components/brain/left-sidebar/web/WebBrainLeftSidebarWave/hooks/useWaveNavigation.ts
  • contexts/wave/MyStreamContext.tsx
  • contexts/wave/hooks/useActiveWaveManager.ts
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{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}: Remove unnecessary Effects. If the Effect's only job is to derive or sync internal state, calculate during render or use useMemo instead.
Use useEffectEvent for non-reactive logic inside Effects to read the latest props/state without turning them into dependencies or causing unnecessary re-runs.
Use explicit caching with "use cache" directive at the top of Server Components, routes, or functions. Configure cacheComponents: true in next.config.ts as needed.

**/*.{ts,tsx,js,jsx}: Remove unnecessary Effects; if the Effect only derives state, compute during render instead
Use useEffectEvent when listening to external events but needing the latest props/state without re-running the Effect
Move data fetching from client Effects to Server Components; mutations go through Server Actions ('use server')

Files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.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

**/*.{tsx,jsx}: Use internal links via <Link> component from Next.js instead of <a> tags
Replace <img> elements with <Image /> from next/image

Files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{test,spec}.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Run npm run test to execute all Jest tests and enforce ≥80% line coverage for files changed since main. Tests must pass and coverage threshold must be met before completing any task.

Enforce ≥ 80% line coverage for files changed since main by running npm run test

Files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Run npm run lint to ensure code satisfies ESLint (Next's Core Web Vitals + React Hooks). Code must pass linting before completing any task.

**/*.{js,ts,jsx,tsx}: Code must satisfy ESLint with Next's Core Web Vitals and React Hooks rules by running npm run lint
Do not add eslint-disable comments unless explicitly instructed; prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions

Files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

**/*.{jsx,tsx}: Replace <img> elements with <Image /> from next/image to comply with Next.js ESLint rule @next/next/no-img-element.
Use <Link href="/path"> from Next.js for internal navigation instead of raw <a> tags to comply with @next/next/no-html-link-for-pages.

Files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Use TypeScript with React functional components and hooks. Follow existing code style and naming conventions.

Files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/*.{tsx,ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with React functional components and hooks

Files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
**/{__tests__,*.test.{tsx,ts}}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
**/*.{test,spec}.{tsx,ts}

📄 CodeRabbit inference engine (AGENTS.md)

Mock external dependencies and APIs in tests

Files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
**/*.{tsx,ts,jsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Prefer direct named imports from React (useMemo, useRef, FC) over React. namespace usage

Files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
🧠 Learnings (5)
📚 Learning: 2025-12-30T14:32:37.293Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-30T14:32:37.293Z
Learning: Applies to __tests__/**/*.{tsx,jsx},!**/__tests__/**,!**/__mocks__/** : Use semantic HTML (`<label>`, `<output>`) over ARIA attributes when possible

Applied to files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
📚 Learning: 2025-12-30T14:32:37.293Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-30T14:32:37.293Z
Learning: Applies to __tests__/**/__tests__/**/*.{ts,tsx,js} : Test accessibility with keyboard navigation and screen reader compatibility

Applied to files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
📚 Learning: 2025-12-30T14:32:37.293Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-30T14:32:37.293Z
Learning: Applies to __tests__/**/__tests__/**/*.{ts,tsx,js} : Write one behaviour per test with clear, descriptive test names

Applied to files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
📚 Learning: 2025-12-30T14:32:37.293Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-30T14:32:37.293Z
Learning: Applies to __tests__/**/*.{ts,tsx,js},!**/__tests__/**,!**/__mocks__/**,!**/*.d.ts : Avoid double negatives in code; prefer explicit statements and use optional chaining (`?.`)

Applied to files:

  • __tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx
📚 Learning: 2025-12-30T14:32:19.339Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T14:32:19.339Z
Learning: Applies to **/*.{tsx,ts} : Use TypeScript with React functional components and hooks

Applied to files:

  • components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx
🧬 Code graph analysis (1)
components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx (2)
helpers/Helpers.ts (2)
  • isValidEthAddress (262-263)
  • formatAddress (32-47)
helpers/navigation.helpers.ts (2)
  • getWaveHomeRoute (61-71)
  • 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)
🔇 Additional comments (7)
__tests__/components/brain/left-sidebar/waves/BrainLeftSidebarWave.test.tsx (2)

88-93: LGTM!

The test correctly validates the new divider parameter in the setActiveWave call. When firstUnreadDropSerialNo is null (from baseWave), the divider is properly expected to be null.


101-105: LGTM!

The test correctly validates that when firstUnreadDropSerialNo is present (42), the href includes both divider=42 and serialNo=42 parameters, aligning with the component's updated URL generation logic.

components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx (5)

6-19: LGTM!

Imports are properly organized. FontAwesome is correctly used for icons per coding guidelines, and all necessary dependencies are imported.


34-35: LGTM!

Clean destructuring of activeWave to extract id and set with descriptive aliases improves readability.


65-84: LGTM!

The href memo correctly integrates the new divider parameter via extraParams. The conditional logic properly converts firstUnreadDropSerialNo to a string only when it exists. Dependencies are correctly listed.


40-63: LGTM!

The formattedWaveName memo correctly formats Ethereum addresses within wave names using the helper functions. The logic properly handles edge cases where the address marker exists but the candidate isn't a valid address.


135-208: LGTM!

The JSX structure is well-organized with appropriate conditional rendering for:

  • Drop wave indicator (trophy icon)
  • Unread count badge (when not active, has new drops, and not muted)
  • Muted indicator (bell-slash icon)

The use of <Link> from Next.js for navigation follows the coding guidelines.

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

@prxt6529 prxt6529 merged commit 8e0ea18 into main Dec 31, 2025
9 checks passed
This was referenced Feb 2, 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