Motivation
Channel timelines order threads by when the root was posted. A two-week-old thread getting replies all morning stays buried under yesterday's dead ones, so finding the live conversation means scrolling and checking reply counts. Home / Inbox is the only pane that surfaces threads by activity, and it is personal/mention-scoped — it does not answer "what is live in this channel."
Proposed solution
An activity-ordering option for the channel timeline, shipped as a preview feature (preview-features.json) — off by default, same path Workflows, Projects, Pulse, and Forum Channels took.
The data already exists end to end. thread_metadata.last_reply_at is bumped on every reply (crates/buzz-db/src/thread.rs:210), selected in the channel window query (thread.rs:588), serialized to the client (crates/buzz-relay/src/api/bridge.rs:544), and already rendered as "last replied …" on thread summary rows (desktop/src/features/messages/ui/MessageThreadSummaryRow.tsx:253). Nothing sorts by it — get_channel_window (thread.rs:565) hardcodes ORDER BY e.created_at DESC, e.id ASC (thread.rs:628).
There are two implementations, with different scope and different correctness:
- Client-side re-sort. Sort the loaded window by
lastReplyAt ?? createdAt behind the flag. Desktop-only, no relay change, no migration. Reorders only what is loaded, so an old-but-active thread below the pagination boundary stays hidden until paged in. Reaches users in a desktop release.
- Server-side sort. Correct at any depth. The current pagination is a composite keyset on
(created_at, id), so it needs a new cursor over COALESCE(last_reply_at, created_at), a supporting index, and a sort param through bridge → Tauri → client. Reaches users only after a relay deploy.
(1) is a subset of (2) — the flag and the UI carry over, so starting there does not throw work away if (2) follows. Either is fine to build; which one depends on whether the partial ordering is acceptable to ship.
Alternatives considered
- Home / Inbox. Already orders by reply time (
crates/buzz-db/src/feed.rs:115), but it is a personal view, not a channel one.
- Always sort by activity, no toggle. Changes the timeline's meaning for every existing user, and reorders the view underneath the reader as replies land.
- Sort by reply count or unread. Reply count does not identify recent activity; unread is per-user state and does not belong in the window query.
Additional context
Searched open issues and PRs — no duplicates found.
Per CONTRIBUTING.md § "PRs We're Unlikely to Merge", raising this before building. If the direction works, the PR will include before/after screenshots.
Motivation
Channel timelines order threads by when the root was posted. A two-week-old thread getting replies all morning stays buried under yesterday's dead ones, so finding the live conversation means scrolling and checking reply counts. Home / Inbox is the only pane that surfaces threads by activity, and it is personal/mention-scoped — it does not answer "what is live in this channel."
Proposed solution
An activity-ordering option for the channel timeline, shipped as a preview feature (
preview-features.json) — off by default, same path Workflows, Projects, Pulse, and Forum Channels took.The data already exists end to end.
thread_metadata.last_reply_atis bumped on every reply (crates/buzz-db/src/thread.rs:210), selected in the channel window query (thread.rs:588), serialized to the client (crates/buzz-relay/src/api/bridge.rs:544), and already rendered as "last replied …" on thread summary rows (desktop/src/features/messages/ui/MessageThreadSummaryRow.tsx:253). Nothing sorts by it —get_channel_window(thread.rs:565) hardcodesORDER BY e.created_at DESC, e.id ASC(thread.rs:628).There are two implementations, with different scope and different correctness:
lastReplyAt ?? createdAtbehind the flag. Desktop-only, no relay change, no migration. Reorders only what is loaded, so an old-but-active thread below the pagination boundary stays hidden until paged in. Reaches users in a desktop release.(created_at, id), so it needs a new cursor overCOALESCE(last_reply_at, created_at), a supporting index, and asortparam through bridge → Tauri → client. Reaches users only after a relay deploy.(1) is a subset of (2) — the flag and the UI carry over, so starting there does not throw work away if (2) follows. Either is fine to build; which one depends on whether the partial ordering is acceptable to ship.
Alternatives considered
crates/buzz-db/src/feed.rs:115), but it is a personal view, not a channel one.Additional context
Searched open issues and PRs — no duplicates found.
Per CONTRIBUTING.md § "PRs We're Unlikely to Merge", raising this before building. If the direction works, the PR will include before/after screenshots.