Skip to content

ECHO-415 Chat and conversation changes#266

Merged
ussaama merged 11 commits intomainfrom
chat-and-conversation-changes
Aug 19, 2025
Merged

ECHO-415 Chat and conversation changes#266
ussaama merged 11 commits intomainfrom
chat-and-conversation-changes

Conversation

@ussaama
Copy link
Copy Markdown
Contributor

@ussaama ussaama commented Aug 19, 2025

Summary by CodeRabbit

  • New Features

    • Infinite scrolling for chats and conversations with visible total counts.
    • Rename chats directly from the list.
  • Enhancements

    • Improved loading UX with compact skeletons, suspense fallback, and inline loaders.
    • Clear end-of-list and empty-state messages; headers show live totals and auto-selection respects counts.
  • Localization

    • Standardized translation keys and updated copy across EN/DE/ES/FR/NL (skeleton titles, rename/delete, end-of-list).

@linear
Copy link
Copy Markdown

linear bot commented Aug 19, 2025

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Aug 19, 2025

Walkthrough

Implements infinite, count-aware scrolling for chat list; extracts ChatAccordionMain and wraps it in Suspense with ChatSkeleton; adds infinite and count hooks for chats (and similar for conversations); integrates per-chat rename mutation; updates multiple locale keys across language bundles.

Changes

Cohort / File(s) Summary
Chat Accordion & Skeleton
echo/frontend/src/components/chat/ChatAccordion.tsx, echo/frontend/src/components/chat/ChatSkeleton.tsx
Replaced paged chat list with infinite scrolling using useInfiniteProjectChats + useProjectChatsCount; sentinel via useInView triggers fetchNextPage; introduced ChatAccordionMain and Suspense-wrapped ChatAccordion with ChatSkeleton fallback; loader, end-of-list UI, per-item rename mutation; i18n keys updated.
Chat Hooks
echo/frontend/src/components/chat/hooks/index.ts
Added useInfiniteProjectChats (useInfiniteQuery paging with nextOffset logic) and useProjectChatsCount (Directus aggregate via useSuspenseQuery); converted useProjectChats to suspense-based variant; new query keys.
Conversation Accordion & Hooks
echo/frontend/src/components/conversation/ConversationAccordion.tsx, echo/frontend/src/components/conversation/hooks/index.ts
Introduced infinite + count hooks for conversations (useInfiniteConversationsByProjectId, useConversationsCountByProjectId); flatten pages to allConversations, sentinel-driven paging, loader and end-of-list messaging; adjusted query usage and export naming.
Locales (EN/DE/ES/FR/NL)
echo/frontend/src/locales/*.{po,ts}
Added/renamed explicit Lingui IDs (chat/conversation skeleton titles, sidebar chat title/delete/rename, empty/end descriptions, end-of-list); deprecated implicit keys; updated message catalogs (data-only changes).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Sidebar as Project Sidebar
  participant ChatAcc as ChatAccordion (Suspense)
  participant Main as ChatAccordionMain
  participant Hooks as Chat Hooks
  participant API as Directus API

  User->>Sidebar: open project
  Sidebar->>ChatAcc: render
  ChatAcc->>Main: mount (fallback: ChatSkeleton)
  Main->>Hooks: useInfiniteProjectChats(projectId, initialLimit=15)
  Hooks->>API: GET /project_chat?offset=0&limit=15
  API-->>Hooks: page0
  Hooks-->>Main: page0 (allChats)
  Main->>Hooks: useProjectChatsCount(projectId)
  Hooks->>API: GET /project_chat/aggregate?count=*
  API-->>Hooks: {count: totalChats}
  Hooks-->>Main: totalChats

  rect rgba(200,240,255,0.25)
    note over Main: Infinite scroll sentinel observed (useInView)
    Main-->>Hooks: fetchNextPage() when sentinel in view
    Hooks->>API: GET /project_chat?offset=pageParam&limit=15
    API-->>Hooks: nextPage or empty
    Hooks-->>Main: append pages or end-of-list
  end
Loading
sequenceDiagram
  autonumber
  actor User
  participant UI as ChatAccordionMain
  participant Mut as useUpdateChatMutation
  participant API as Directus API

  User->>UI: trigger "Rename" on item
  UI->>User: prompt for new name
  User->>UI: provide name
  UI->>Mut: mutate({ chatId, projectId, payload:{ name } })
  Mut->>API: PATCH /project_chat/:chatId { name }
  API-->>Mut: 200 OK
  Mut-->>UI: invalidate/update queries
  UI-->>User: updated name displayed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Assessment against linked issues

Objective Addressed Explanation
ECHO-415: Implement paginated infinite scrolling for the chats accordion

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Add rename capability via useUpdateChatMutation (echo/frontend/src/components/chat/ChatAccordion.tsx) Rename feature is not specified by ECHO-415 (which targets pagination); this extends scope beyond the stated objective.
Apply infinite/count changes to conversations (echo/frontend/src/components/conversation/ConversationAccordion.tsx, echo/frontend/src/components/conversation/hooks/index.ts) ECHO-415 specifically targets the chats accordion; conversation refactor is outside that issue's stated scope.

Possibly related PRs

Suggested reviewers

  • spashii
  • ArindamRoy23
  • sameer-kymata

LGTM.

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chat-and-conversation-changes

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@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: 20

Caution

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

⚠️ Outside diff range comments (16)
echo/frontend/src/components/conversation/hooks/index.ts (1)

634-725: Live-flag logic: OK, but avoid over-fetching chunk payloads

The live-status calc is solid. However, upstream in this query you request { chunks: ["*"] } and deep _limit: loadChunks ? 1000 : 1. For list views that only need recency, this is expensive.

Keep the select logic, but fetch minimal chunk fields (e.g., only timestamp or created_at) and avoid large transcripts:

  • In the fields array: use { chunks: ["timestamp", "created_at"] }.
  • Keep _limit: 1 when loadChunks is false.

If you want, I can patch both the non-infinite and infinite queries accordingly.

echo/frontend/src/components/chat/ChatAccordion.tsx (1)

70-79: Don’t navigate away before confirming delete succeeds.

You navigate immediately after calling deleteChatMutation.mutate, even if it fails. Safer to redirect on success.

-            onClick={() => {
-              deleteChatMutation.mutate({
-                chatId: chat.id ?? "",
-                projectId: (chat.project_id as string) ?? "",
-              });
-              navigate(`/projects/${chat.project_id}/overview`);
-            }}
+            onClick={() => {
+              deleteChatMutation.mutate(
+                {
+                  chatId: chat.id ?? "",
+                  projectId: (chat.project_id as string) ?? "",
+                },
+                { onSuccess: () => navigate(`/projects/${chat.project_id}/overview`) },
+              );
+            }}
echo/frontend/src/components/conversation/ConversationAccordion.tsx (2)

599-613: Redundant conversations query wastes a network call; remove it.

totalConversationsQuery = useConversationsByProjectId(... limit: 1 ...) is unused, yet it still fires a request (with deep chunks). This adds latency and load for no value.

Remove the whole block:

-  // Get total conversations count without filters
-  const totalConversationsQuery = useConversationsByProjectId(
-    projectId,
-    false,
-    false,
-    {
-      limit: 1,
-      deep: {
-        // @ts-expect-error chunks is not typed
-        chunks: {
-          _limit: 25,
-        },
-      },
-    },
-  );

783-790: Localize the upload tooltip label.

This hard-coded tooltip isn’t localized.

-          <Tooltip label={`Upload conversations`}>
+          <Tooltip label={t`Upload`}>
echo/frontend/src/locales/de-DE.po (12)

248-251: Fix compound noun: “Analysis Language” → “Analysesprache”

German compounds this; current translation reads unnatural in UI.

Apply this diff:

-msgstr "Analyse Sprache"
+msgstr "Analysesprache"

1455-1458: Fix noun form: “Neuer Gesprächsname”

Current: “Neuer Gespräch Name” is incorrect splitting.

Apply this diff:

-msgstr "Neuer Gespräch Name"
+msgstr "Neuer Gesprächsname"

1349-1352: Hyphenate “Live-Vorschau”

Minor polish; common UI convention in German.

Apply this diff:

-msgstr "Live Vorschau"
+msgstr "Live-Vorschau"

2194-2197: Preserve intent: add “zum Hochladen”

The source says “Select Audio Files to Upload”; current de string omits purpose.

Apply this diff:

-msgstr "Audio-Dateien auswählen"
+msgstr "Audio-Dateien zum Hochladen auswählen"

2782-2785: Grammar fix: “Ihren Mikrofon” → “Ihr Mikrofon” and improve phrasing

Current line has wrong case/gender and reads awkward.

Apply this diff:

-msgstr "Versuchen Sie, etwas näher an Ihren Mikrofon zu sein, um bessere Audio-Qualität zu erhalten."
+msgstr "Versuchen Sie, etwas näher an Ihr Mikrofon heranzugehen, um die Klangqualität zu verbessern."

2937-2940: Natural phrasing: “Wir hören einige Stille” is off

Suggested clearer guidance.

Apply this diff:

-msgstr "Wir hören einige Stille. Versuchen Sie, lauter zu sprechen, damit Ihre Stimme deutlich klingt."
+msgstr "Wir nehmen Stille wahr. Sprechen Sie bitte etwas lauter, damit Ihre Stimme deutlich zu hören ist."

2983-2986: Use “Link” instead of “Verknüpfung”

“Verknüpfung” sounds technical/Windows-ish; “Link” is standard in web UIs.

Apply this diff:

-msgstr "Sie sind bereits abgemeldet oder Ihre Verknüpfung ist ungültig."
+msgstr "Sie sind bereits abgemeldet oder Ihr Link ist ungültig."

1365-1369: Consistency: unify “Loading...” as “Wird geladen...”

Elsewhere you use “wird geladen...”. Aligning improves polish.

Apply this diff:

-msgstr "Laden..."
+msgstr "Wird geladen..."

779-783: Confirm intent: “is recording” label likely mis-translated

Key implies active recording state. Current de string = “ready to record”. If this is a state badge/button during recording, better options:

  • “Aufnahme läuft”
  • Or “Sie nehmen gerade auf”

If correct, apply:

-msgstr "Sie sind gerade aufnahmebereit"
+msgstr "Aufnahme läuft"

Please confirm the UI context (button label vs. status text) and I’ll adjust accordingly.


71-75: Clarify duration string

More precise: it’s the generation that takes time, not “the library” per se.

Apply this diff:

-msgstr "Die Bibliothek wird {duration} dauern."
+msgstr "Die Generierung der Bibliothek wird {duration} dauern."

1890-1893: Compound noun: “Projekteinstellungen”

Standard German UI term.

Apply this diff:

-msgstr "Projekt Einstellungen"
+msgstr "Projekteinstellungen"

598-605: Apply German translation grammar fixes

  • In echo/frontend/src/locales/de-DE.po, update the translations:
-msgstr "Gesprächstatus"
+msgstr "Gesprächsstatus"
@@
-msgstr "Gesprächstatusdetails"
+msgstr "Details zum Gesprächsstatus"
  • Verified that the Conversation Status panel is already gated by conversationCounts.pending !== 0 in CreateReportForm.tsx (line 94); no UI changes needed. LGTM.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2e4377c and 10d6761.

📒 Files selected for processing (15)
  • echo/frontend/src/components/chat/ChatAccordion.tsx (7 hunks)
  • echo/frontend/src/components/chat/ChatSkeleton.tsx (1 hunks)
  • echo/frontend/src/components/chat/hooks/index.ts (3 hunks)
  • echo/frontend/src/components/conversation/ConversationAccordion.tsx (11 hunks)
  • echo/frontend/src/components/conversation/hooks/index.ts (6 hunks)
  • echo/frontend/src/locales/de-DE.po (41 hunks)
  • echo/frontend/src/locales/de-DE.ts (1 hunks)
  • echo/frontend/src/locales/en-US.po (41 hunks)
  • echo/frontend/src/locales/en-US.ts (1 hunks)
  • echo/frontend/src/locales/es-ES.po (41 hunks)
  • echo/frontend/src/locales/es-ES.ts (1 hunks)
  • echo/frontend/src/locales/fr-FR.po (41 hunks)
  • echo/frontend/src/locales/fr-FR.ts (1 hunks)
  • echo/frontend/src/locales/nl-NL.po (42 hunks)
  • echo/frontend/src/locales/nl-NL.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-17T15:57:51.321Z
Learnt from: ussaama
PR: Dembrane/echo#224
File: echo/frontend/src/components/report/CreateReportForm.tsx:97-155
Timestamp: 2025-07-17T15:57:51.321Z
Learning: In echo/frontend/src/components/report/CreateReportForm.tsx, the conversation status section should only be displayed when there are pending conversations (conversationCounts.pending !== 0). When all conversations are processed, no status information should be shown to keep the UI minimal and clean.

Applied to files:

  • echo/frontend/src/components/conversation/ConversationAccordion.tsx
  • echo/frontend/src/locales/en-US.po
  • echo/frontend/src/locales/de-DE.po
🧬 Code Graph Analysis (10)
echo/frontend/src/locales/en-US.ts (4)
echo/frontend/src/locales/de-DE.ts (1)
  • messages (1-1)
echo/frontend/src/locales/nl-NL.ts (1)
  • messages (1-1)
echo/frontend/src/locales/es-ES.ts (1)
  • messages (1-1)
echo/frontend/src/locales/fr-FR.ts (1)
  • messages (1-1)
echo/frontend/src/components/chat/ChatSkeleton.tsx (1)
echo/frontend/src/components/common/BaseSkeleton.tsx (1)
  • BaseSkeleton (11-25)
echo/frontend/src/locales/nl-NL.ts (2)
echo/frontend/src/locales/de-DE.ts (1)
  • messages (1-1)
echo/frontend/src/locales/en-US.ts (1)
  • messages (1-1)
echo/frontend/src/locales/es-ES.ts (2)
echo/frontend/src/locales/de-DE.ts (1)
  • messages (1-1)
echo/frontend/src/locales/en-US.ts (1)
  • messages (1-1)
echo/frontend/src/locales/fr-FR.ts (2)
echo/frontend/src/locales/de-DE.ts (1)
  • messages (1-1)
echo/frontend/src/locales/en-US.ts (1)
  • messages (1-1)
echo/frontend/src/components/chat/hooks/index.ts (2)
echo/frontend/src/lib/typesDirectusContent.ts (1)
  • CustomDirectusTypes (1125-1232)
echo/frontend/src/lib/directus.ts (1)
  • directus (6-14)
echo/frontend/src/components/chat/ChatAccordion.tsx (1)
echo/frontend/src/components/chat/hooks/index.ts (2)
  • useInfiniteProjectChats (158-195)
  • useProjectChatsCount (197-222)
echo/frontend/src/components/conversation/ConversationAccordion.tsx (4)
echo/frontend/src/components/conversation/hooks/index.ts (2)
  • useInfiniteConversationsByProjectId (811-930)
  • useConversationsCountByProjectId (932-957)
echo/frontend/src/config.ts (1)
  • ENABLE_CHAT_AUTO_SELECT (31-32)
echo/frontend/src/components/conversation/AutoSelectConversations.tsx (1)
  • AutoSelectConversations (27-218)
echo/frontend/src/components/common/BaseSkeleton.tsx (1)
  • BaseSkeleton (11-25)
echo/frontend/src/components/conversation/hooks/index.ts (2)
echo/frontend/src/lib/typesDirectusContent.ts (1)
  • CustomDirectusTypes (1125-1232)
echo/frontend/src/lib/directus.ts (1)
  • directus (6-14)
echo/frontend/src/locales/de-DE.ts (1)
echo/frontend/src/locales/en-US.ts (1)
  • messages (1-1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci-check-server
🔇 Additional comments (18)
echo/frontend/src/locales/nl-NL.ts (1)

1-1: LGTM on new key: conversation.accordion.skeleton.title

Translation “Gesprekken” is correct and consistent with other locales.

echo/frontend/src/locales/de-DE.ts (1)

1-1: LGTM on new key: conversation.accordion.skeleton.title

“Gespräche” is accurate and aligned with the rest of the locales.

echo/frontend/src/locales/en-US.ts (1)

1-1: LGTM: added conversation skeleton title + correct chat end-of-list with [totalChats]

  • conversation.accordion.skeleton.title: “Conversations” — good
  • project.sidebar.chat.end.description uses [totalChats] — correct for infinite scroll UX
echo/frontend/src/locales/fr-FR.ts (1)

1-1: LGTM on new key: conversation.accordion.skeleton.title

“Conversations” is correct for FR.

echo/frontend/src/locales/es-ES.ts (1)

1-1: LGTM on new key: conversation.accordion.skeleton.title

“Conversaciones” reads well and matches usage elsewhere.

echo/frontend/src/components/chat/hooks/index.ts (2)

140-155: Switching to Suspense: ensure boundary coverage

Good move to useSuspenseQuery for useProjectChats. Make sure all call sites render under a React Suspense boundary with an appropriate fallback; otherwise this will throw at runtime instead of returning loading states.

Would you like me to scan usages of useProjectChats and ChatAccordion to confirm Suspense boundaries are present?


197-222: Count query: double-check aggregate result shape across Directus versions

Using response[0].count is fine for most Directus setups, but some versions return nested shapes for aggregates. Confirm your SDK returns a flat [{ count: number }].

If you want to be defensive:

  • Validate the response shape before indexing.
  • Align with the same pattern used in conversations count to keep consistency.

Run-time check suggestion: log the first aggregate result in a non-prod env to confirm shape, or point me to your Directus SDK version to validate against docs.

echo/frontend/src/locales/en-US.po (3)

481-485: New skeleton title key looks solid

chat.accordion.skeleton.title → “Chats” aligns with the component rename. LGTM.


487-490: Explicit chat title key is consistent

project.sidebar.chat.title standardized to “Chats”. Nice cleanup. LGTM.


1557-1560: Empty state copy LGTM

Clear, concise, and matches the new sidebar behavior. LGTM.

echo/frontend/src/locales/es-ES.po (2)

465-468: Skeleton title translation LGTM

chat.accordion.skeleton.title → “Chats” is correct and consistent. LGTM.


470-473: Sidebar chat title translation LGTM

project.sidebar.chat.title → “Chats” is accurate. LGTM.

echo/frontend/src/components/chat/ChatSkeleton.tsx (1)

14-20: Skeleton title and footprint look solid. LGTM.

Explicit id chat.accordion.skeleton.title and reduced row height are consistent with the new UX.

echo/frontend/src/components/chat/ChatAccordion.tsx (1)

88-122: Infinite query + count wiring looks clean. LGTM.

Flattening pages, separating count, and prioritizing chats with messages (plus the active chat) is a solid approach.

echo/frontend/src/components/conversation/ConversationAccordion.tsx (1)

912-951: Infinite list/rendering pipeline looks tight. LGTM.

Pending skeleton, last-item sentinel, next-page loader, and end-of-list message are implemented cleanly and resiliently.

echo/frontend/src/locales/nl-NL.po (1)

537-546: New explicit IDs for chat skeleton and title look correct. LGTM.

Keys chat.accordion.skeleton.title and project.sidebar.chat.title align with usage.

echo/frontend/src/locales/fr-FR.po (1)

464-473: New explicit IDs for chat skeleton and title look consistent. LGTM.

Translations for chat.accordion.skeleton.title and project.sidebar.chat.title are aligned with UI.

echo/frontend/src/locales/de-DE.po (1)

460-469: LGTM: Chat i18n keys migration aligns with the infinite scroll refactor

Explicit IDs for Chat accordion/skeleton and sidebar actions are clean and consistent. The empty and end descriptions read well and map 1:1 to the updated components. Ship it.

Also applies to: 705-709, 1511-1514, 883-886

Copy link
Copy Markdown
Contributor

@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

Caution

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

⚠️ Outside diff range comments (1)
echo/frontend/src/components/conversation/ConversationAccordion.tsx (1)

653-673: Stabilize query key inputs: memoize the query object

Passing a fresh object each render into the hook (and into the query key) can trigger avoidable re-fetches/rehashes. Memoize the query object so it only changes when deps change.

Apply this diff:

-  const conversationsQuery = useInfiniteConversationsByProjectId(
+  const conversationsQuery = useInfiniteConversationsByProjectId(
     projectId,
     false,
     false,
-    {
-      search: debouncedConversationSearchValue,
-      sort: sortBy,
-      deep: {
-        // @ts-expect-error chunks is not typed
-        chunks: {
-          _limit: 25,
-        },
-      },
-    },
+    useMemo(
+      () => ({
+        search: debouncedConversationSearchValue,
+        sort: sortBy,
+        deep: {
+          // @ts-expect-error chunks is not typed
+          chunks: {
+            _limit: 25,
+          },
+        },
+      }),
+      [debouncedConversationSearchValue, sortBy],
+    ),
     // Temporarily disabled source filters
     // filterBySource,
     undefined,
     {
       initialLimit: 15,
     },
   );
♻️ Duplicate comments (2)
echo/frontend/src/components/conversation/ConversationAccordion.tsx (2)

360-362: hasContent computes number | boolean; force a boolean

Short-circuiting with && can yield 0 or true. Return a boolean explicitly to avoid subtle bugs downstream (e.g., in conditional rendering).

Apply this diff:

-  const hasContent = useMemo(
-    () => conversation.chunks?.length && conversation.chunks.length > 0,
-    [conversation.chunks],
-  );
+  const hasContent = useMemo(
+    () => (conversation.chunks?.length ?? 0) > 0,
+    [conversation.chunks],
+  );

571-573: Prefetch slightly earlier for seamless infinite scroll

Begin fetching before the sentinel is actually on-screen to reduce perceived latency.

Apply this diff:

-  const { ref: loadMoreRef, inView } = useInView();
+  const { ref: loadMoreRef, inView } = useInView({ rootMargin: "200px" });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 10d6761 and 928e915.

📒 Files selected for processing (1)
  • echo/frontend/src/components/conversation/ConversationAccordion.tsx (11 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-17T15:57:51.321Z
Learnt from: ussaama
PR: Dembrane/echo#224
File: echo/frontend/src/components/report/CreateReportForm.tsx:97-155
Timestamp: 2025-07-17T15:57:51.321Z
Learning: In echo/frontend/src/components/report/CreateReportForm.tsx, the conversation status section should only be displayed when there are pending conversations (conversationCounts.pending !== 0). When all conversations are processed, no status information should be shown to keep the UI minimal and clean.

Applied to files:

  • echo/frontend/src/components/conversation/ConversationAccordion.tsx
🧬 Code Graph Analysis (1)
echo/frontend/src/components/conversation/ConversationAccordion.tsx (4)
echo/frontend/src/components/conversation/hooks/index.ts (2)
  • useInfiniteConversationsByProjectId (811-930)
  • useConversationsCountByProjectId (932-957)
echo/frontend/src/config.ts (1)
  • ENABLE_CHAT_AUTO_SELECT (31-32)
echo/frontend/src/components/conversation/AutoSelectConversations.tsx (1)
  • AutoSelectConversations (27-218)
echo/frontend/src/components/common/BaseSkeleton.tsx (1)
  • BaseSkeleton (11-25)
🔇 Additional comments (7)
echo/frontend/src/components/conversation/ConversationAccordion.tsx (7)

10-12: Imports aligned with infinite + count hooks and BaseSkeleton/inView — LGTM

The new imports match the infinite-scroll and count strategy in this PR. Clean swap to BaseSkeleton and react-intersection-observer.

Also applies to: 79-81


696-698: Flattening pages into allConversations — LGTM

Simple and effective flatten; pairs well with the sentinel approach.


774-779: Header count/loader swap — LGTM

Loader while counting, otherwise show total. With the NaN fix above, this will be solid.


900-910: Empty-state copy/CTA — LGTM

Clear message with a direct link to the project overview. Solid UX.


912-915: Pending skeleton — LGTM

Right-sized skeletons inline with the list; good replacement for Suspense-based placeholder.


916-933: Sentinel attached to the last item — LGTM

Correctly references the final item; pairs with the inView effect for page fetches.


934-938: Next-page loader — LGTM

Good minimal spinner; communicates background fetch without disrupting content.

@cursor
Copy link
Copy Markdown

cursor bot commented Aug 19, 2025

Bugbot found 2 bugs

To see them, have a team admin activate your membership in the Cursor dashboard.

Copy link
Copy Markdown
Contributor

@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: 10

Caution

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

⚠️ Outside diff range comments (1)
echo/frontend/src/locales/de-DE.po (1)

14-14: Set German plural forms header (currently empty).

Plural-Forms is blank. For German, it must be set or pluralization for non-ICU strings will be wrong.

Apply this diff:

-"Plural-Forms: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
♻️ Duplicate comments (5)
echo/frontend/src/locales/es-ES.po (1)

886-890: Critical: wrong placeholder and noun in end-of-list banner for chats

The key is for chats but the Spanish reads “conversaciones” and uses an indexed placeholder. The component likely passes a named variable (totalChats). This will render the wrong noun and may fail interpolation.

Apply this fix:

 msgid "project.sidebar.chat.end.description"
-msgstr "Fin de la lista • Todas las {0} conversaciones cargadas"
+msgstr "Fin de la lista • Todos los {totalChats} chats cargados"

Verify the placeholder used by the code and other locales:

#!/bin/bash
# Inspect usage to confirm value name (expect { totalChats })
rg -n -C2 'project\.sidebar\.chat\.end\.description' echo/frontend/src

# Show msgstr across all locales for consistency
rg -n -C1 'project\.sidebar\.chat\.end\.description' echo/frontend/src/locales/*.po
echo/frontend/src/locales/nl-NL.po (1)

1000-1003: Fix noun (“chats” vs “gesprekken”) and align key with intended usage

Two issues:

  • The chat end-of-list line says “gesprekken” (conversations) — should be “chats”.
  • Prior review requested a distinct key for end-of-list: project.sidebar.chat.end (keeping project.sidebar.chat.empty.description for the empty state). The code still uses project.sidebar.chat.end.description.

Apply minimal fix now, and optionally introduce the new key to future-proof:

 msgid "project.sidebar.chat.end.description"
-msgstr "Einde van de lijst • Alle {0} gesprekken geladen"
+msgstr "Einde van de lijst • Alle {0} chats geladen"
+
+#. js-lingui-explicit-id
+#: src/components/chat/ChatAccordion.tsx:217
+msgid "project.sidebar.chat.end"
+msgstr "Einde van de lijst • Alle {0} chats geladen"

Run this to verify usages in ChatAccordion and ensure we can safely switch to the new key:

#!/bin/bash
# Check current usages of end/empty keys in ChatAccordion
rg -n -C2 -e 'project\.sidebar\.chat\.(end(\.description)?|empty\.description)' src/components/chat/ChatAccordion.tsx

# Sanity check for the Ask button translation used in the empty-state hint
rg -n -C2 -e 'msgid "Ask"\nmsgstr "Stel vraag"' echo/frontend/src/locales/nl-NL.po
echo/frontend/src/locales/fr-FR.po (1)

886-890: Split the end-of-list key for Chat and fix copy to use “discussions” (not “conversations”)

We’re still using project.sidebar.chat.end.description and the copy mentions “conversations”. This should be a dedicated key for chats and say “discussions”. Past review asked for this exact change.

Apply this diff:

-#: src/components/chat/ChatAccordion.tsx:217
-msgid "project.sidebar.chat.end.description"
-msgstr "Fin de la liste • Toutes les {0} conversations chargées"
+#: src/components/chat/ChatAccordion.tsx:217
+msgid "project.sidebar.chat.end"
+#. placeholder {0}: totalChats
+msgstr "Fin de la liste • Toutes les {0} discussions chargées"

Then update usage in ChatAccordion to the new key.

Run to verify/update usages:

#!/bin/bash
set -euo pipefail

# Where the key is used
rg -n -C2 -P 'project\.sidebar\.chat\.end(\.description)?' echo/frontend/src/components/chat/ChatAccordion.tsx

# Sanity: empty-state key remains separate
rg -n -C2 'project\.sidebar\.chat\.empty\.description' echo/frontend/src/components/chat/ChatAccordion.tsx
echo/frontend/src/locales/de-DE.po (2)

877-881: End-of-list copy needs plural-safety; migrate to ICU (previous feedback still applies).

For count=1, “Alle 1 Gespräche geladen” reads awkward. Use ICU plural with an explicit ID and pass a named count.

Apply this change and update the component to use the explicit ID with a named value:

-#: src/components/conversation/ConversationAccordion.tsx:944
-msgid "End of list • All {0} conversations loaded"
-msgstr "Ende der Liste • Alle {0} Gespräche geladen"
+#. js-lingui-explicit-id
+#: src/components/conversation/ConversationAccordion.tsx:944
+msgid "conversation.accordion.endOfList"
+msgstr "Ende der Liste • {count, plural, one {# Gespräch geladen} other {Alle # Gespräche geladen}}"

Outside this file (component sketch):

// src/components/conversation/ConversationAccordion.tsx
import { i18n } from "@lingui/core";
const total = totalConversations ?? allConversations.length;
const endLabel = i18n._("conversation.accordion.endOfList", { count: total });

Want me to prep the component patch?


1849-1852: Fix tense: “Processing” → “Wird verarbeitet”.

“Verarbeitet” means “processed.” For the in-progress state, use “Wird verarbeitet”.

Apply this diff:

 msgid "Processing"
-msgstr "Verarbeitet"
+msgstr "Wird verarbeitet"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 928e915 and ea05af9.

📒 Files selected for processing (4)
  • echo/frontend/src/locales/de-DE.po (41 hunks)
  • echo/frontend/src/locales/es-ES.po (41 hunks)
  • echo/frontend/src/locales/fr-FR.po (41 hunks)
  • echo/frontend/src/locales/nl-NL.po (42 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-17T15:57:51.321Z
Learnt from: ussaama
PR: Dembrane/echo#224
File: echo/frontend/src/components/report/CreateReportForm.tsx:97-155
Timestamp: 2025-07-17T15:57:51.321Z
Learning: In echo/frontend/src/components/report/CreateReportForm.tsx, the conversation status section should only be displayed when there are pending conversations (conversationCounts.pending !== 0). When all conversations are processed, no status information should be shown to keep the UI minimal and clean.

Applied to files:

  • echo/frontend/src/locales/de-DE.po
⏰ 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). (2)
  • GitHub Check: Cursor Bugbot
  • GitHub Check: ci-check-server
🔇 Additional comments (15)
echo/frontend/src/locales/es-ES.po (4)

881-885: LGTM: conversations end-of-list message

Plural and placeholder usage for conversations look correct and consistent.


464-473: LGTM: explicit IDs and titles for chat skeleton/accordion

Good move to explicit Lingui IDs and consistent “Chats” title across skeleton and accordion.


1515-1518: LGTM: empty-state copy for chats

Empty-state guidance reads well and matches product terminology (“Preguntar”).


455-459: LGTM: route and header labels

“Chat” strings align with the route and don’t introduce placeholder risks.

echo/frontend/src/locales/nl-NL.po (5)

994-998: Conversations end-of-list: LGTM

String and placeholder usage look correct for conversations. No action needed.


537-546: New explicit chat keys: LGTM

Using explicit IDs for skeleton title and sidebar title improves clarity and i18n control. Translations look good.


790-794: Delete chat label: LGTM

“Chat verwijderen” is accurate and consistent with other actions.


1020-1023: Rename prompt: LGTM

Clear and idiomatic phrasing for the rename prompt.


528-536: “Chat” route/title updates: LGTM

Consistent with product naming. Good.

echo/frontend/src/locales/fr-FR.po (2)

464-468: Chat i18n additions are on point — LGTM

New explicit IDs and copy for Chat skeleton, sidebar title, rename/delete actions, input and send controls look clean and consistent with “discussion(s)” terminology.

Also applies to: 470-473, 709-713, 907-910, 1515-1518, 2241-2244, 2788-2790, 455-459, 460-463


881-885: Conversation end-of-list message — LGTM

Count-aware end-of-list copy for conversations matches the new infinite scrolling UX.

echo/frontend/src/locales/de-DE.po (4)

460-464: LGTM: New explicit ID for Chat skeleton title.

Explicit ID aligns with Lingui best practices. Translation is correct.


1511-1514: LGTM: Empty-state copy for Chat.

Clear, instructive, and consistent with the “Ask” CTA label.


903-906: LGTM: Rename prompt for Chat.

Terminology and casing are on point.


66-70: Ignore the obsolete PO entry—translations now live in TS locale modules.

The de-DE.po file is vestigial. All locale strings (including conversation.accordion.skeleton.title) are defined and consumed from the frontend/src/locales/*.ts files (e.g. de-DE.ts). No action is needed in the .po file.

Likely an incorrect or invalid review comment.

@Dembrane Dembrane deleted a comment from coderabbitai bot Aug 19, 2025
@Dembrane Dembrane deleted a comment from coderabbitai bot Aug 19, 2025
Copy link
Copy Markdown
Contributor

@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

♻️ Duplicate comments (1)
echo/frontend/src/components/chat/ChatSkeleton.tsx (1)

8-8: Accordion.Item value fixed to "chat": resolves prior mismatch. LGTM.

This aligns the skeleton’s item with the real value and avoids controlled-state glitches.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ea05af9 and f334c39.

📒 Files selected for processing (1)
  • echo/frontend/src/components/chat/ChatSkeleton.tsx (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
echo/frontend/src/components/chat/ChatSkeleton.tsx (1)
echo/frontend/src/components/common/BaseSkeleton.tsx (1)
  • BaseSkeleton (11-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: ci-check-server
🔇 Additional comments (3)
echo/frontend/src/components/chat/ChatSkeleton.tsx (3)

14-14: Confirmed i18n ID “chat.accordion.skeleton.title” in all locale catalogs
LGTM—translations exist in:

  • en-US (en-US.po, en-US.ts)
  • nl-NL (nl-NL.po, nl-NL.ts)
  • de-DE (de-DE.po)
  • fr-FR (fr-FR.po)
  • es-ES (es-ES.po, es-ES.ts)

Ready to merge.


6-6: LGTM: No residual ConversationSkeleton artifacts detected

  • ✅ No stale ConversationSkeleton references found
  • ℹ️ No barrel re-exports of ChatSkeleton detected
  • ℹ️ No direct imports of ChatSkeleton present

Ready to merge 🚀


1-1: Import path verified for Lingui v5
With @lingui/core & @lingui/react at v5.3.3 in your front-end, import { Trans } from "@lingui/react/macro"; is the correct macro import. No action required. LGTM.

@ussaama ussaama enabled auto-merge August 19, 2025 12:50
@ussaama ussaama added this pull request to the merge queue Aug 19, 2025
Merged via the queue into main with commit f71a54e Aug 19, 2025
12 checks passed
@ussaama ussaama deleted the chat-and-conversation-changes branch August 19, 2025 13:14
spashii pushed a commit that referenced this pull request Nov 18, 2025
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- New Features
- Infinite scrolling for chats and conversations with visible total
counts.
  - Rename chats directly from the list.

- Enhancements
- Improved loading UX with compact skeletons, suspense fallback, and
inline loaders.
- Clear end-of-list and empty-state messages; headers show live totals
and auto-selection respects counts.

- Localization
- Standardized translation keys and updated copy across EN/DE/ES/FR/NL
(skeleton titles, rename/delete, end-of-list).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants