feat: count unread thread messages - #977
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Introduce unread_count and unread-item ledger schema plus an idempotent startup migration that backfills legacy unread threads before dropping message_threads.is_read. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 332cfd7b-8a60-4e28-9ea8-61854aa712c3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 332cfd7b-8a60-4e28-9ea8-61854aa712c3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 332cfd7b-8a60-4e28-9ea8-61854aa712c3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 332cfd7b-8a60-4e28-9ea8-61854aa712c3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 332cfd7b-8a60-4e28-9ea8-61854aa712c3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 332cfd7b-8a60-4e28-9ea8-61854aa712c3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 332cfd7b-8a60-4e28-9ea8-61854aa712c3
Retain unread tombstones, generate read watermarks under lock, and retry all counter transactions on CockroachDB serialization failures. Refuse duplicate conversations before destructive migration, then create the unique identity needed for concurrent first-message fallback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 332cfd7b-8a60-4e28-9ea8-61854aa712c3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 332cfd7b-8a60-4e28-9ea8-61854aa712c3
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 332cfd7b-8a60-4e28-9ea8-61854aa712c3
Greptile SummaryThe PR replaces message-thread read booleans with server-owned unread counts and adds retry-safe ledgers for received, deleted, and replayed activity.
Confidence Score: 4/5The PR should not merge until user-wide inbound events stop clearing the unread count of an unrelated currently open conversation. The backend sends received and missed-call notifications on a shared user channel without conversation identity, while the page handles every notification by persisting unread_count=0 for the current route's thread. Files Needing Attention: web/app/pages/threads/[id]/index.vue, api/pkg/listeners/websocket_listener.go Important Files Changed
Sequence DiagramsequenceDiagram
participant B as Backend event
participant P as User Pusher channel
participant A as Open thread A page
participant API as Thread API
B->>P: message.phone.received for thread B (event ID only)
P->>A: user-wide event
A->>API: "PUT /message-threads/A {unread_count: 0}"
API-->>A: thread A marked read
Note over A,API: Thread B's badge is not refreshed
Reviews (1): Last reviewed commit: "fix(api): preserve deleted message marke..." | Re-trigger Greptile |
| webhookChannel.bind('message.phone.received', () => { | ||
| if (!loadingMessages.value) { | ||
| void markCurrentThreadRead(true) | ||
| void resetCurrentThreadUnreadCount(true) | ||
| loadMessages(false, false) |
There was a problem hiding this comment.
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| CodeStyle | 66 minor |
🟢 Metrics 261 complexity · 138 duplication
Metric Results Complexity 261 Duplication 138
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Summary
is_readstate with a server-ownedunread_count99+badges in the web UI1and publish regenerated Swagger/TypeScript contractsConcurrency and migration safety
Validation
cd api && go test -count=1 ./...cd web && pnpm lint && pnpm run generatecd tests && go test -count=1 -run '^$' ./...Docker is unavailable in the local environment, so the live integration stack test is left to CI.