Sort channel threads by most recent reply, not creation date
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
**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:
1. **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.
2. **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.
Contributor guide
Research direction
Start with get_channel_window in crates/buzz-db/src/thread.rs, then trace the existing last_reply_at path through crates/buzz-relay/src/api/bridge.rs and desktop/src/features/messages/ui/MessageThreadSummaryRow.tsx. Read preview-features.json and compare the client-side and server-side options with the maintainer before implementing; done means the preview flag controls activity ordering and the relevant pagination or loaded-window behavior is covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, tauri, typescript
- Domain
- databases, full-stack
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100