Skip to content

Update conversation timestamp display to use latestMessageAt #923

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Hanaffi
Copy link
Contributor

@Hanaffi Hanaffi commented Aug 14, 2025

Resolves: #899

I see that we already have this field latestMessageAt and I think we can just use it since for this case we will always do the join to get the last message content.

image

Summary by CodeRabbit

  • Bug Fixes
    • Conversation list timestamps now reflect the most recent message, providing accurate “Last updated” times.
    • When a latest message time isn’t available, the display falls back to the conversation’s creation time.
    • Non-closed conversations are ordered by most-recent-message time (with sensible fallbacks), improving relevance when browsing previous conversations.

Copy link

vercel bot commented Aug 14, 2025

@Hanaffi is attempting to deploy a commit to the Antiwork Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Contributor

coderabbitai bot commented Aug 14, 2025

Walkthrough

UI now reads an optional latestMessageAt timestamp for conversations (falls back to createdAt). Backend conversation search ordering was adjusted to prefer a most-recent-message timestamp (using COALESCE with message timestamps and createdAt).

Changes

Cohort / File(s) Summary
Widget: Previous Conversations UI
components/widget/PreviousConversations.tsx
Added `Conversation.latestMessageAt: string
Backend: Conversation search ordering
lib/data/conversation/search.ts
Reordered non-closed conversation sort key to prefer a last-message timestamp via COALESCE(lastMessageAt, recent_message.created_at, createdAt) and retained the lateral join recent_message for message timestamp resolution.

Sequence Diagram(s)

sequenceDiagram
  participant UI as PreviousConversations (frontend)
  participant API as Conversation Search (backend)
  participant HT as HumanizedTime

  API-->>UI: Conversations (createdAt, lastMessageAt?, recent_message.created_at?)
  UI->>UI: choose timestamp = latestMessageAt ?? createdAt
  UI-->>HT: time=timestamp
  HT-->>UI: humanized time string
  UI->>User: render conversation list (backend ordering uses last-message timestamp)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Change conversation date in list to last message date (#899)

Assessment against linked issues: Out-of-scope changes

(no out-of-scope functional changes identified)

Possibly related PRs

Suggested reviewers

  • binary-koan

Poem

🐰 I thump, I hop, I check each chat,
New latestMessageAt — a tasty stat.
If none are fresh, I nibble the start,
Still show the time, each thread and heart.
Hop, sort, render — conversations done.

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.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
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 7d1028f and 74b218d.

📒 Files selected for processing (1)
  • lib/data/conversation/search.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/data/conversation/search.ts
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

🧹 Nitpick comments (2)
components/widget/PreviousConversations.tsx (2)

14-15: Make latestMessageAt optional to match real-world API variability

If the backend omits latestMessageAt for older conversations or when there are no messages, keeping it required (even as string | null) can be slightly misleading. Marking it optional better reflects runtime shape and still works with your ?? fallback.

Apply this diff:

-  latestMessageAt: string | null;
+  latestMessageAt?: string | null;

1-1: Rename file to lowerCamelCase to align with .tsx naming guideline

Repo guideline for **/*.tsx favors lowerCamelCase file names. Consider renaming this file to previousConversations.tsx and updating imports.

Example:

  • git mv components/widget/PreviousConversations.tsx components/widget/previousConversations.tsx
  • Update any import paths referencing this component.
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 196245c and 0d4e096.

📒 Files selected for processing (1)
  • components/widget/PreviousConversations.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.tsx

📄 CodeRabbit Inference Engine (.cursorrules)

Name component files in lowerCamelCase, e.g. conversationList.tsx

Files:

  • components/widget/PreviousConversations.tsx

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

🧹 Nitpick comments (1)
lib/data/conversation/search.ts (1)

151-159: Optional: prefer column over join in COALESCE to improve index use on large lists

If conversations.lastMessageAt is reliably maintained, consider preferring it before the lateral-join value. This keeps semantics intact while giving the planner a better chance to leverage the lastMessageAt index when possible.

Proposed tweak:

-      : sql`COALESCE(recent_message.created_at, ${conversations.lastMessageAt}, ${conversations.createdAt})`;
+      : sql`COALESCE(${conversations.lastMessageAt}, recent_message.created_at, ${conversations.createdAt})`;

Rationale:

  • lastMessageAt is indexed (per schema), and using it first can help ordering on large datasets.
  • The lateral join still provides a correct fallback for any historical rows missing lastMessageAt.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
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 0d4e096 and 7d1028f.

📒 Files selected for processing (1)
  • lib/data/conversation/search.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
lib/data/conversation/search.ts (1)
db/schema/conversations.ts (1)
  • conversations (13-80)
🔇 Additional comments (1)
lib/data/conversation/search.ts (1)

151-159: Clarify sorting key for closed conversations vs. displayed timestamp

The current implementation in lib/data/conversation/search.ts uses conversations.closedAt to sort “closed” tickets, while the widget renders conversation.latestMessageAt ?? conversation.createdAt. This means closed tickets are ordered by when they were closed, but the UI shows the most recent message date (or creation date).

Please confirm product expectations:

  • Should closed conversations continue to sort by closedAt even though the UI displays latestMessageAt?
  • Or should they be sorted by the latest message timestamp (i.e. COALESCE(recent_message.created_at, lastMessageAt, createdAt)) to match what users see?

Locations to review:

  • lib/data/conversation/search.ts (lines 151–155) – sort key for closed status
  • components/widget/PreviousConversations.tsx (line 131) – timestamp displayed via HumanizedTime time={conversation.latestMessageAt ?? conversation.createdAt}

Copy link
Collaborator

@binary-koan binary-koan left a comment

Choose a reason for hiding this comment

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

Added a small suggestion, looks good otherwise!

@@ -151,7 +151,7 @@ export const searchConversations = async (
const orderByField =
filters.status?.length === 1 && filters.status[0] === "closed"
? conversations.closedAt
: sql`COALESCE(${conversations.lastUserEmailCreatedAt}, ${conversations.createdAt})`;
: sql`COALESCE(${conversations.lastMessageAt}, recent_message.created_at, ${conversations.createdAt})`;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
: sql`COALESCE(${conversations.lastMessageAt}, recent_message.created_at, ${conversations.createdAt})`;
: sql`COALESCE(${conversations.lastMessageAt}, ${conversations.createdAt})`;

I think this is fine, less potential for confusion if the calculation matches the UI

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@binary-koan the thing is, the UI is using recent_message.created_at because we still anyway have to keep the join as we need the last message body.
If we want to avoid the join at all, then we might need to store last_message_content or last_message_id .

We can also omit conversations.lastMessageAt to be:

      : sql`COALESCE(recent_message.created_at, ${conversations.createdAt})`;

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a comment about that few days ago
#899 (comment)

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.

Change date of conversation in list to last message date
2 participants