Skip to content

[Detail Bug] Inbox Activity tab misorders conversations by creation time instead of last activity #32686

Description

@detail-app

Detail Bug Report

https://app.detail.dev/org_3377c26d-da48-4ccd-b83a-22c542f4fe83/bugs/bug_8c443515-7221-45fb-bed0-e0651e53e5a1

Introduced in #31911 by @karanh37 on Aug 29, 2026

Summary

  • Context: useInboxActivity is the single source that fetches and merges a user's activity events with their conversations for the Inbox's Activity tab. ActivityTab.tsx:108-120 renders items straight from the hook with no re-sorting.
  • Bug: The inbox's merge-sort key for conversations uses creation time (createdAt ?? updatedAt), whereas the upstream activity feed's sort key uses last-activity time (updatedAt ?? createdAt). A replied/reacted thread (updatedAt > createdAt) sinks below a newer-but-dead thread whose createdAt falls between the replied thread's createdAt and its updatedAt.
  • Actual vs. expected: Actual: merged items are sorted newest-first by conversation createdAt (not updatedAt). Expected: newest-first by last activity (updatedAt), matching upstream.
  • Impact: The Activity tab can show recently-active (replied/reacted) threads below newer-but-inactive threads; this is reachable under the default 30-day window and is dense in the all scope where many conversations are returned.

Code with Bug

src/components/discovery/personal-space/InboxPage/useInboxActivity.ts:

const items: InboxActivityItem[] = useMemo(() => {
  const merged: InboxActivityItem[] = [
    ...(data?.activities ?? []).map((activity) => ({ activity })),
    ...(data?.threads ?? []).map((feed) => ({ feed })),
  ];
  const itemTimestamp = (item: InboxActivityItem) =>
    item.activity?.timestamp ?? (item.feed ? getFeedTimestamp(item.feed) : 0); // <-- BUG 🔴 uses createdAt-first timestamp for sorting

  return merged.sort((a, b) => itemTimestamp(b) - itemTimestamp(a));
}, [data]);

src/components/discovery/personal-space/InboxPage/inbox.utils.ts:

export const getFeedTimestamp = (feed: Conversation): number =>
  feed.createdAt ?? feed.updatedAt ?? 0; // <-- BUG 🔴 createdAt-first (wrong for last-activity ordering)

Explanation

  • The server returns conversations filtered by createdAt window but ordered by updatedAt DESC (last activity). The client then calls merged.sort(...) which fully overrides that order.
  • In production responses both createdAt and updatedAt are set; updatedAt is bumped on replies/reactions, so updatedAt > createdAt for active threads. Sorting by createdAt therefore misorders active threads relative to newer-but-inactive ones.
  • Minimal repro condition: a replied thread where another item’s createdAt falls strictly between that thread’s createdAt and its later updatedAt.

Codebase Inconsistency

Upstream activity feed sorts conversations by last activity:

const getConversationTimestamp = (feed: Conversation): number =>
  feed.updatedAt ?? feed.createdAt ?? 0;

The inbox file header also states: Activity events and conversations interleave newest-first — upstream parity, OpenMetadata#30879.

Failing Test

src/components/discovery/personal-space/InboxPage/useInboxActivity.test.tsx (added regression test):

it('orders a replied conversation above a newer unreplied one by last-activity', async () => {
  mockGetUserActivity.mockResolvedValue({ data: [] });
  mockListConversations.mockResolvedValue({
    data: [
      { id: 'c-replied', createdAt: 200, updatedAt: 400 },
      { id: 'c-unreplied', createdAt: 300, updatedAt: 300 },
    ],
  });

  const { result } = renderHook(() => useInboxActivity('all'), {
    wrapper: createWrapper(),
  });

  await waitFor(() => expect(result.current.isLoading).toBe(false));

  expect(result.current.items.map((i) => i.feed?.id)).toEqual([
    'c-replied',
    'c-unreplied',
  ]);
});

Failing output on current code:

- Expected  - 1
+ Received  + 1

  Array [
-   "c-replied",
    "c-unreplied",
+   "c-replied",
  ]

Recommended Fix

  • Keep getFeedTimestamp as-is for display (“Posted on” time is createdAt-first).
  • Add a sort-specific helper (updatedAt-first) and use it in useInboxActivity’s merge sort; optionally add the same id tiebreaker as upstream.

History

This bug was introduced in commit 2807684. PR #31911 freshly authored the Inbox’s inbox.utils.ts / useInboxActivity.ts with getFeedTimestamp = createdAt ?? updatedAt ?? 0 and used it as the merged-list sort key, diverging from upstream’s updatedAt ?? createdAt sort precedence.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

  • Status
    Done ✅

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions