Skip to content

fix(frontend): correct My Threads unread badge - #1641

Open
hmans wants to merge 6 commits into
mainfrom
hmans/fix-my-threads-unread-badge
Open

fix(frontend): correct My Threads unread badge#1641
hmans wants to merge 6 commits into
mainfrom
hmans/fix-my-threads-unread-badge

Conversation

@hmans

@hmans hmans commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Why

“My Threads” could show false or stale unread dots for unfollowed, muted, inaccessible, or concurrently updated threads, while the first realtime fix made every reply perform an exhaustive per-viewer followed-thread read.

What changed

  • Drive the badge from accessible, unmuted, followed-and-unread thread viewer state without changing channel badges or notification routing.
  • Keep live reply work bounded: a created reply/mention transition marks only its exact cached followed thread unread, while complete replacements remain limited to bootstrap/catch-up, follow/read, notification-preference, and access-restoration transitions.
  • Purge thread state on access loss, restore durable follows after rejoin/member-add/universal access, and revision-fence delayed viewer refreshes.
  • Preserve the exact thread target across concurrent cross-device notification dismissal, and add frontend, mounted component, core aggregate, realtime, reconnect, and access-transition regressions.
  • Update the realtime architecture inventory, generated protocol reference, and repository realtime-race guidance.

Closes #1643.

API compatibility

  • Additive public realtime change plus compatible behavioural changes; no ConnectRPC, auth, discovery, admin, or public HTTP shape changed.

Older client → newer server: Older clients ignore the two optional notification-transition fields and retain their existing notification-based badge behavior; known projection operations and protocol version remain unchanged.

Newer client → older server: The client falls back to resolving the target from the pending notification page; if another device dismisses it before mapping, the badge may defer until another thread-state replacement or reconnect. Servers without the access-restoration replacements likewise converge on another thread transition or reconnect.

Capability discovery or minimum client/server version: Unchanged; the fields are optional metadata on an existing protocol-v2 operation, so no capability or coordinated rollout is required.

Test plan

  • mise codegen-proto && mise build-api-types — passed; generated Go, TypeScript, and reference docs are committed.
  • mise test-cli — frontend production build and all CLI packages passed.
  • mise x -- pnpm check (from apps/frontend) — design guardrails passed; svelte-check reported 0 errors and 0 warnings.
  • Focused frontend Vitest command covering viewer mapping, mounted My Threads, projection, rooms, store, notifications, and room list — 7 files and 102 tests passed.
  • Targeted core and realtime tests for mute/unmute, bounded reply delivery, notification dismissal races, access restoration, and resume catch-up — passed; these paths also passed in the full CLI suite.
  • Svelte autofixer ran on every changed Svelte component/module: no issues in projection.svelte.ts; rooms.svelte.ts hit an autofixer internal parser error; store.svelte.ts reported only pre-existing $effect advisories. Frontend check is clean.
  • git diff --check origin/main...HEAD, generated source-link existence, and edited architecture-paragraph length checks — passed.

@hmans
hmans force-pushed the hmans/fix-my-threads-unread-badge branch from da1b2a5 to b901fbe Compare July 20, 2026 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: make My Threads unread projection bounded and authoritative

1 participant