Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions apps/web/src/components/Sidebar.tsx
Copy link
Contributor

Choose a reason for hiding this comment

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

🟢 Low

Issue on line in apps/web/src/components/Sidebar.tsx:107:

getThreadSidebarTimestamp returns the earliest message timestamp, but the sidebar sorting logic expects the latest timestamp so that more recent activity appears first. This causes threads to sort incorrectly — for example, a thread with messages at [10:01, 10:05] returns 10:01 and appears older than a thread with a single message at 10:03. Change the comparison to find the maximum timestamp instead.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file apps/web/src/components/Sidebar.tsx around line 107:

`getThreadSidebarTimestamp` returns the **earliest** message timestamp, but the sidebar sorting logic expects the **latest** timestamp so that more recent activity appears first. This causes threads to sort incorrectly — for example, a thread with messages at [10:01, 10:05] returns 10:01 and appears older than a thread with a single message at 10:03. Change the comparison to find the maximum timestamp instead.

Evidence trail:
apps/web/src/components/Sidebar.tsx lines 107-122: `getThreadSidebarTimestamp` function uses `messageTime < earliestTime` comparison to find minimum timestamp. apps/web/src/components/Sidebar.tsx lines 405-413: sorting uses `getThreadSidebarTimestamp(b) - getThreadSidebarTimestamp(a)` (descending order) and variable is named `latestThread`. apps/web/src/components/Sidebar.tsx lines 1317-1325: same sorting pattern. apps/web/src/components/Sidebar.tsx line 1576: timestamp displayed as relative time ('Xm ago') implying most recent activity.

Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,25 @@ function formatRelativeTime(iso: string): string {
return `${Math.floor(hours / 24)}d ago`;
}

function getThreadSidebarTimestamp(thread: Thread): string {
if (thread.messages.length === 0) {
return thread.createdAt;
}

let earliestTimestamp = thread.messages[0]?.createdAt ?? thread.createdAt;
let earliestTime = new Date(earliestTimestamp).getTime();

for (const message of thread.messages) {
const messageTime = new Date(message.createdAt).getTime();
if (messageTime < earliestTime) {
earliestTimestamp = message.createdAt;
earliestTime = messageTime;
}
}

return earliestTimestamp;
Comment on lines +108 to +123
}
Comment on lines +107 to +124

interface TerminalStatusIndicator {
label: "Terminal process running";
colorClass: string;
Expand Down Expand Up @@ -386,7 +405,9 @@ export default function Sidebar() {
const latestThread = threads
.filter((thread) => thread.projectId === projectId)
.toSorted((a, b) => {
const byDate = new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
const byDate =
new Date(getThreadSidebarTimestamp(b)).getTime() -
new Date(getThreadSidebarTimestamp(a)).getTime();
if (byDate !== 0) return byDate;
return b.id.localeCompare(a.id);
})[0];
Expand Down Expand Up @@ -1297,7 +1318,8 @@ export default function Sidebar() {
.filter((thread) => thread.projectId === project.id)
.toSorted((a, b) => {
const byDate =
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
new Date(getThreadSidebarTimestamp(b)).getTime() -
new Date(getThreadSidebarTimestamp(a)).getTime();
Comment on lines +1321 to +1322

Choose a reason for hiding this comment

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

P2 Badge Precompute sidebar timestamps before sorting threads

The new comparator recomputes getThreadSidebarTimestamp for both operands on every comparison, and getThreadSidebarTimestamp scans the full thread.messages array each time. In projectThreads sorting this turns one render into roughly O(threadCount * log(threadCount) * messagesPerThread), which is a significant regression for projects with long histories and can make sidebar interactions noticeably sluggish under load; deriving each thread timestamp once before sorting avoids this repeated full scan.

Useful? React with 👍 / 👎.

if (byDate !== 0) return byDate;
return b.id.localeCompare(a.id);
});
Expand Down Expand Up @@ -1551,7 +1573,7 @@ export default function Sidebar() {
: "text-muted-foreground/40"
}`}
>
{formatRelativeTime(thread.createdAt)}
{formatRelativeTime(getThreadSidebarTimestamp(thread))}
</span>
</div>
</SidebarMenuSubButton>
Expand Down
Loading