-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Fix: Web app conversation sorting by date #4121
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
Conversation
Date group sorting was incorrect because parsing formatted date strings (e.g., "Mon, Jan 6") lacks year info. Now uses conversation timestamps (started_at/created_at) for accurate chronological ordering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request correctly addresses the conversation sorting issue by using full timestamps instead of formatted date strings that lack year information. The changes in both ConversationList.tsx and ConversationSplitView.tsx are appropriate.
My review includes suggestions to make the sorting logic more robust by handling potential invalid date values, which would prevent unpredictable sorting behavior. This ensures the fix is not only correct for the expected case but also resilient to unexpected data.
| const dateA = new Date(convA?.started_at || convA?.created_at); | ||
| const dateB = new Date(convB?.started_at || convB?.created_at); | ||
| return dateB.getTime() - dateA.getTime(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This correctly fixes the sorting issue across years. However, it could be made more robust against potentially invalid date strings.
If started_at or created_at were ever to be invalid date strings, new Date(...).getTime() would return NaN. The behavior of Array.prototype.sort() with NaN is inconsistent across JavaScript engines and can lead to unpredictable sorting.
I recommend adding a check to handle NaN values gracefully, ensuring invalid dates are pushed to the end of the list. This makes the sorting more robust.
Also, the optional chaining (?.) on convA and convB is not necessary, as the logic that creates groupedConversations ensures that the conversation arrays for each date key are never empty.
const dateA = new Date(convA.started_at || convA.created_at);
const dateB = new Date(convB.started_at || convB.created_at);
const timeA = dateA.getTime();
const timeB = dateB.getTime();
if (isNaN(timeA) || isNaN(timeB)) {
if (isNaN(timeA) && isNaN(timeB)) return 0;
return isNaN(timeA) ? 1 : -1;
}
return timeB - timeA;
| const dateA = new Date(convA?.started_at || convA?.created_at); | ||
| const dateB = new Date(convB?.started_at || convB?.created_at); | ||
| return dateB.getTime() - dateA.getTime(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This correctly fixes the sorting issue across years. However, it could be made more robust against potentially invalid date strings.
If started_at or created_at were ever to be invalid date strings, new Date(...).getTime() would return NaN. The behavior of Array.prototype.sort() with NaN is inconsistent across JavaScript engines and can lead to unpredictable sorting.
I recommend adding a check to handle NaN values gracefully, ensuring invalid dates are pushed to the end of the list. This makes the sorting more robust.
Also, the optional chaining (?.) on convA and convB is not necessary, as the logic that creates displayedConversations ensures that the conversation arrays for each date key are never empty.
| const dateA = new Date(convA?.started_at || convA?.created_at); | |
| const dateB = new Date(convB?.started_at || convB?.created_at); | |
| return dateB.getTime() - dateA.getTime(); | |
| const dateA = new Date(convA.started_at || convA.created_at); | |
| const dateB = new Date(convB.started_at || convB.created_at); | |
| const timeA = dateA.getTime(); | |
| const timeB = dateB.getTime(); | |
| if (isNaN(timeA) || isNaN(timeB)) { | |
| if (isNaN(timeA) && isNaN(timeB)) return 0; | |
| return isNaN(timeA) ? 1 : -1; | |
| } | |
| return timeB - timeA; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes a bug in conversation date group sorting within the web app. Previously, the sorting logic parsed formatted date strings (e.g., "Mon, Jan 6") which lacked year information, causing incorrect chronological ordering. The fix now uses actual conversation timestamps (started_at/created_at) for accurate date-based sorting.
- Replaces date string parsing with timestamp-based comparison
- Ensures "Today" and "Yesterday" groups appear first, followed by older dates in descending order
- Applies the fix consistently across two components
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| web/app/src/components/conversations/ConversationSplitView.tsx | Updates the date sorting logic to use conversation timestamps instead of parsing formatted date strings |
| web/app/src/components/conversations/ConversationList.tsx | Applies the same timestamp-based sorting fix for consistent behavior |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Use actual conversation timestamps instead of parsing the date string | ||
| // (which lacks year info and causes incorrect sorting) | ||
| const convA = displayedConversations[a][0]; | ||
| const convB = displayedConversations[b][0]; | ||
| const dateA = new Date(convA?.started_at || convA?.created_at); | ||
| const dateB = new Date(convB?.started_at || convB?.created_at); | ||
| return dateB.getTime() - dateA.getTime(); |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code doesn't handle the case where the first conversation in a group might be undefined (empty array) or when both started_at and created_at are null/undefined. This could result in invalid Date objects where getTime() returns NaN, leading to unpredictable sorting behavior. Consider adding validation to ensure the dates are valid before comparing them.
| // Use actual conversation timestamps instead of parsing the date string | |
| // (which lacks year info and causes incorrect sorting) | |
| const convA = displayedConversations[a][0]; | |
| const convB = displayedConversations[b][0]; | |
| const dateA = new Date(convA?.started_at || convA?.created_at); | |
| const dateB = new Date(convB?.started_at || convB?.created_at); | |
| return dateB.getTime() - dateA.getTime(); | |
| const getConversationTime = (conv: Conversation | undefined): number => { | |
| if (!conv) return 0; | |
| const rawDate = conv.started_at ?? conv.created_at; | |
| if (!rawDate) return 0; | |
| const time = new Date(rawDate).getTime(); | |
| return Number.isNaN(time) ? 0 : time; | |
| }; | |
| // Use actual conversation timestamps instead of parsing the date string | |
| // (which lacks year info and causes incorrect sorting) | |
| const convA = displayedConversations[a]?.[0]; | |
| const convB = displayedConversations[b]?.[0]; | |
| const timeA = getConversationTime(convA); | |
| const timeB = getConversationTime(convB); | |
| return timeB - timeA; |
| const convA = groupedConversations[a][0]; | ||
| const convB = groupedConversations[b][0]; | ||
| const dateA = new Date(convA?.started_at || convA?.created_at); | ||
| const dateB = new Date(convB?.started_at || convB?.created_at); | ||
| return dateB.getTime() - dateA.getTime(); |
Copilot
AI
Jan 8, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code doesn't handle the case where the first conversation in a group might be undefined (empty array) or when both started_at and created_at are null/undefined. This could result in invalid Date objects where getTime() returns NaN, leading to unpredictable sorting behavior. Consider adding validation to ensure the dates are valid before comparing them.
Summary
started_at/created_at) for accurate sortingTest plan