Skip to content

fix: Show proper tab titles for DMs and channels from inbox#376

Merged
2witstudios merged 7 commits intomasterfrom
claude/fix-tab-titles-XbKZN
Feb 5, 2026
Merged

fix: Show proper tab titles for DMs and channels from inbox#376
2witstudios merged 7 commits intomasterfrom
claude/fix-tab-titles-XbKZN

Conversation

@2witstudios
Copy link
Owner

@2witstudios 2witstudios commented Feb 4, 2026

Tab titles for DMs and channels opened from the inbox were showing the
raw route path instead of meaningful names. Now DMs show "DM - {name}"
and channels show "#{channel-name}".

  • Add API endpoint to fetch single conversation metadata
  • Update useTabMeta hook to handle inbox-dm and inbox-channel types
  • Reuse page fetching logic for channels (since they're pages)
  • Add DM conversation metadata fetching with participant name

https://claude.ai/code/session_018mPA9wWDxNNPtewkMYKMrh

Summary by CodeRabbit

  • New Features

    • Public pages are now accessible as a dedicated tab type
    • Account is now available as a standalone navigation page
    • Settings supports nested subpages for better organization
    • DM tab metadata now shows DM participant name and DM-specific icon
  • Improvements

    • Inbox fetches a single conversation for faster, more accurate DM loading
    • Added new tab icons (MessageCircle and Hash)
  • Removed

    • Friends page has been removed

Tab titles for DMs and channels opened from the inbox were showing the
raw route path instead of meaningful names. Now DMs show "DM - {name}"
and channels show "#{channel-name}".

- Add API endpoint to fetch single conversation metadata
- Update useTabMeta hook to handle inbox-dm and inbox-channel types
- Reuse page fetching logic for channels (since they're pages)
- Add DM conversation metadata fetching with participant name

https://claude.ai/code/session_018mPA9wWDxNNPtewkMYKMrh
- DM page now fetches single conversation instead of all conversations
- Add Hash and MessageCircle icons to TabItem ICON_MAP for channel/DM tabs

https://claude.ai/code/session_018mPA9wWDxNNPtewkMYKMrh
…ages

- Add /account route support (shows "Account" with User icon)
- Handle nested settings pages like /settings/integrations/google-calendar
  (shows "Integrations - Google Calendar")
- Simplify settings page titles (e.g., "Account" instead of "Settings - Account")
- Add /p/[pageId] public page link support with async title fetch

https://claude.ai/code/session_018mPA9wWDxNNPtewkMYKMrh
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

Adds a GET API to fetch a single conversation by ID, updates the DM page to use that endpoint, removes the FriendsPage component, expands tab icon support, and extends tab metadata/routing (adds public-page and account, nests settings subpages, removes friends route).

Changes

Cohort / File(s) Summary
Conversation API Endpoint
apps/web/src/app/api/messages/conversations/[conversationId]/route.ts
New GET handler: authenticates user, queries DB for the conversation including the other participant's user/profile, returns 404 if not found, 500 on server errors.
DM Page Integration
apps/web/src/app/dashboard/inbox/dm/[conversationId]/page.tsx
Switched SWR fetch from conversations list to single-conversation endpoint (/api/messages/conversations/${conversationId}) and adjusted destructuring to consume { conversation }.
Tab Metadata & Routing Logic
apps/web/src/hooks/useTabMeta.ts, apps/web/src/lib/tabs/tab-title.ts
Added support for DM-specific fetching and tab meta updates, introduced public-page and account path types, added settingsSubPage parsing, removed friends route handling, and updated title/icon mapping logic.
Tab UI & Icons
apps/web/src/components/layout/tabs/TabItem.tsx
Imported Hash and MessageCircle icons and extended ICON_MAP to include them.
Tests
apps/web/src/lib/tabs/__tests__/tab-title.test.ts
Updated tests to reflect removal of friends route and changed expected settings subpage title formatting.
Cleanup
apps/web/src/app/friends/page.tsx
Removed the default-exported FriendsPage component.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Server
  participant Auth
  participant DB

  Client->>Server: GET /api/messages/conversations/:conversationId
  Server->>Auth: validate session (read-only)
  Auth-->>Server: userId
  Server->>DB: SELECT conversation where id = :id AND participant = userId
  DB-->>Server: conversation + other participant profile | or empty
  alt conversation found
    Server-->>Client: 200 { conversation: { ... , otherUser: { ... } } }
  else not found
    Server-->>Client: 404 { error: "Conversation not found" }
  end
  opt server error
    Server-->>Client: 500 { error: "Server error" }
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 One fetch, one conversation, neat and small,
Tabs sprout icons, new routes answer the call,
Friends page hopped away, account takes its place,
Settings nest deeper in soft, quiet space,
A rabbit hums code—organized and tall. 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 accurately describes the main change: fixing tab titles for DMs and channels from the inbox, which is the central objective across multiple file changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/fix-tab-titles-XbKZN

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.

claude and others added 3 commits February 4, 2026 14:11
The /friends page is an empty stub not linked anywhere in the app.
The actual feature is /dashboard/connections which is already handled.

https://claude.ai/code/session_018mPA9wWDxNNPtewkMYKMrh
This was an empty placeholder page not linked anywhere in the app.
The actual connections feature is at /dashboard/connections.

https://claude.ai/code/session_018mPA9wWDxNNPtewkMYKMrh
Removed dmConversations, eq, and, or imports that were not being used
since the route uses raw SQL queries instead of Drizzle query builder.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
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

🤖 Fix all issues with AI agents
In `@apps/web/src/app/api/messages/conversations/`[conversationId]/route.ts:
- Around line 84-92: The response currently exposes otherUser.email (populated
from row.user_email) which may be unnecessary; remove the email field from the
otherUser object in route.ts (the object literal keyed as otherUser), drop
row.user_email from the SQL SELECT that populates the result, and remove the
corresponding email property from any TypeScript interface/type used for the
response (e.g., the conversation/otherUser response type). Ensure no callers
rely on otherUser.email; if they do, update them to use name/displayName
instead.
🧹 Nitpick comments (2)
apps/web/src/app/api/messages/conversations/[conversationId]/route.ts (1)

58-75: Type assertion pattern is acceptable but consider extracting the interface.

The ConversationRow interface defined inline and the as unknown as ConversationRow cast is a common pattern for raw SQL queries with Drizzle. For better maintainability, consider moving this interface to a shared types file if it's reused elsewhere.

apps/web/src/hooks/useTabMeta.ts (1)

191-227: Potential display inconsistency for channel tab titles.

When the channel metadata is updated in the useEffect (line 116-120), the raw pageData.title is stored. However, when displaying, the title is prefixed with # (lines 196 and 206). This means the stored tab.title is "channel-name" but displayed as "#channel-name".

This works correctly but creates a subtle inconsistency: the DM title is stored as "DM - {name}" (line 129), while the channel title is stored as "{name}" and then prefixed at display time.

Consider either:

  1. Storing the prefixed title #${pageData.title} for channels (like DMs store the full formatted title), or
  2. Documenting this as intentional behavior for supporting different display contexts.

Comment on lines +84 to +92
otherUser: {
id: row.user_id,
name: row.user_name,
email: row.user_email,
image: row.user_image,
username: row.user_username,
displayName: row.user_display_name,
avatarUrl: row.user_avatar_url,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider whether exposing email in the response is necessary.

The otherUser object includes the user's email address. If this endpoint is only used for displaying tab titles (which uses displayName or name), the email field may be unnecessary and could be a privacy concern. Consider whether this data is needed by the consuming client.

🔒 Proposed fix to remove email from response
       otherUser: {
         id: row.user_id,
         name: row.user_name,
-        email: row.user_email,
         image: row.user_image,
         username: row.user_username,
         displayName: row.user_display_name,
         avatarUrl: row.user_avatar_url,
       },

Also remove the corresponding SQL select and interface property if email is not needed.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
otherUser: {
id: row.user_id,
name: row.user_name,
email: row.user_email,
image: row.user_image,
username: row.user_username,
displayName: row.user_display_name,
avatarUrl: row.user_avatar_url,
},
otherUser: {
id: row.user_id,
name: row.user_name,
image: row.user_image,
username: row.user_username,
displayName: row.user_display_name,
avatarUrl: row.user_avatar_url,
},
🤖 Prompt for AI Agents
In `@apps/web/src/app/api/messages/conversations/`[conversationId]/route.ts around
lines 84 - 92, The response currently exposes otherUser.email (populated from
row.user_email) which may be unnecessary; remove the email field from the
otherUser object in route.ts (the object literal keyed as otherUser), drop
row.user_email from the SQL SELECT that populates the result, and remove the
corresponding email property from any TypeScript interface/type used for the
response (e.g., the conversation/otherUser response type). Ensure no callers
rely on otherUser.email; if they do, update them to use name/displayName
instead.

- Update friends path test to expect 'unknown' type (route was removed)
- Remove friends type test from getStaticTabMeta (type no longer exists)
- Fix settings subpage test expectations to match actual behavior
  (returns just formatted page name, not "Settings - X")

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@2witstudios 2witstudios merged commit b477c19 into master Feb 5, 2026
3 checks passed
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