From 579449acc35476ff600f4c724bd85e0760f542ee Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Wed, 1 Jul 2026 22:53:32 -0400 Subject: [PATCH] docs: Slack-style per-thread notifications (P4-1) across catalog/README/TODO/BUGS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LOTUS_FEATURES: Notifications subsection under Threads (participating default, per-thread All/Mentions/Mute, badge behavior). README: thread-notifications bullet. LOTUS_TODO: P4-1 → [~] + 6-step live-QA checklist + caveats. LOTUS_BUGS: verification row. Co-Authored-By: Claude Opus 4.8 --- LOTUS_BUGS.md | 1 + LOTUS_FEATURES.md | 5 +++++ LOTUS_TODO.md | 16 +++++++++++----- README.md | 1 + 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/LOTUS_BUGS.md b/LOTUS_BUGS.md index 773bc1d95..659675e93 100644 --- a/LOTUS_BUGS.md +++ b/LOTUS_BUGS.md @@ -36,6 +36,7 @@ Implemented and gate-green; confirm each per `LOTUS_TESTING.md`, then delete the | P4-4 | KaTeX math (`$…$`, `$$…$$`, data-mx-maths; lazy chunk) | `utils/mathParse.ts`, `components/math/` | send `$x^2$`, `$$\int f$$`, `$5 and $10` (stays text), math inside code block (stays text) | | P4-8 | Encrypted-search cache (opt-in toggle, clear button, logout wipe) | `utils/searchCache.ts`, message-search | enable in search panel → search → reload → coverage persists; logout wipes | | N97a | Session blob migration + cross-tab logout sync | `state/sessions.ts`, `useSessionSync` | login on old build → new build migrates; logout in tab A → tab B drops to auth | +| P4-1 | Slack-style thread notifications (participating default, All/Mentions/Mute, badge math) | `utils/threadNotifications.ts`, `ClientNonUIFeatures`, `roomToUnread` | 6-step checklist in LOTUS_TODO §P4-1 | **Verified working in live testing (2026-06):** A2, B1–B4, C1, C3, D (mic/camera/deafen/screenshare/fullscreen/more-menu/PiP). Denoise quality in D is still poor — tracked under the denoise project, not a regression. diff --git a/LOTUS_FEATURES.md b/LOTUS_FEATURES.md index c84286f65..e711fe389 100644 --- a/LOTUS_FEATURES.md +++ b/LOTUS_FEATURES.md @@ -800,9 +800,14 @@ Root messages in the main timeline show a **"N replies · time"** chip (server-a The panel embeds the full composer (uploads, emoji, stickers, GIFs, voice, location, polls) with drafts, reply state, and upload queues **isolated per thread** (`roomId::threadRootId` keys). Replies-to-replies produce spec-correct `m.thread` + `m.in_reply_to` (`is_falling_back: false`). Scheduling and slash commands are disabled inside threads (v1). +### Notifications (Slack-style, P4-1) + +By default you're notified for a thread reply only when you **participate** in that thread (you've posted in it) or the reply **@mentions** you — other threads accumulate quietly behind their chip badges. Every thread can be overridden from the bell menu in the panel header: **Default (participating) / All replies / Mentions only / Mute**. Modes sync across your devices (`io.lotus.thread_notifications` account data, auto-pruned). Muting a thread silences notifications and sounds, removes the chip's unread badge (a small bell-mute glyph shows instead), and subtracts that thread from the room's sidebar unread badge (client-side — other Matrix clients on the account still count it). + ### Under the Hood - `threadSupport: true` (startClient) partitions thread events into SDK `Thread` timelines; markAsRead sends **unthreaded** receipts so room badges keep clearing +- Thread replies are notified via exactly one path (room-level `ThreadEvent.NewReply` w/ per-thread dedupe + panel-aware focus suppression); the main timeline notifier is thread-guarded, and room badges refresh live on `RoomEvent.UnreadNotifications` - Pending sends render via a `LocalEchoUpdated` strip (chronological local echo never enters thread timelineSets) - Deep links to thread events redirect into the panel - Files: `features/room/thread/*`, `state/room/thread.ts`, `hooks/useThreadSummary.ts` (+35 tests across the stack) diff --git a/LOTUS_TODO.md b/LOTUS_TODO.md index 1abfe7993..a3ded4be9 100644 --- a/LOTUS_TODO.md +++ b/LOTUS_TODO.md @@ -214,12 +214,18 @@ Features: **What:** Implement a persistent local cache for search results, optimized for encrypted rooms. **Approach:** Use `IndexedDB` to store search metadata (event IDs, timestamps) to prevent redundant server-side decryption/fetching. -### [ ] P4-1 · Thread Notification Mode Per-Thread (MSC3771) +### [~] P4-1 · Thread Notification Mode Per-Thread — IMPLEMENTED (2026-07), ⚠️ AWAITING LIVE QA -**Spec:** MSC3771 (stable). Depends on Thread Panel (#P3-8) — **NOW UNBLOCKED (P3-8 implemented 2026-07)**. -**What:** Per-thread notification toggle: "All messages" vs "Mentions only". Accessible from the thread panel header. Tracks unread counts separately per thread. -**[AUDIT REQUIRED]** — Implement after Thread Panel. Requires understanding how the SDK tracks per-thread unread counts. -**Complexity:** Medium (after thread panel exists). +**Shipped (Slack-style):** default = **Participating** (notified only for threads you've posted in or where you're @mentioned); per-thread override **All / Mentions-only / Mute** via the bell menu in the thread panel header; modes sync across devices (`io.lotus.thread_notifications` account data, pruned on write). Mute also suppresses the chip badge and subtracts the thread from the room's sidebar badge (client-side). Also fixed the underlying path: thread replies are notified via exactly one handler (room-level `ThreadEvent.NewReply`), with the main-timeline notifier + unread binder thread-guarded, and live badge refresh on `RoomEvent.UnreadNotifications`. + +**Manual QA checklist (post-deploy):** +1. Friend replies in a thread YOU posted in → notification + sound; in a thread you never touched → silent (chip badge only) +2. @mention in any thread → notified regardless of participation +3. Set a thread to Mute → no notifications, chip badge gone (bell-mute glyph), room sidebar badge drops by that thread's count +4. Set to All → every reply notifies; Mentions-only → only @mentions +5. Second device shows the same per-thread modes (account-data sync) +6. Room-level Mute still silences everything incl. thread overrides +**Known caveats:** Mentions-only can under-notify in E2EE rooms (decision runs pre-decryption — same class as the existing notifier); muted-thread badge subtraction is Lotus-only (other clients still count them). --- diff --git a/README.md b/README.md index c59232baa..6245ceb03 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ The Lotus Chat logo (`public/res/Lotus.png`) is a derivative work based on the o ### Messaging - Threads: reply in a thread and read/write the whole conversation in a side panel — root messages show a "N replies" chip with an unread badge (threaded replies live in the panel now, not inline in the room) +- Slack-style thread notifications: by default you're only pinged for threads you're in or where you're @mentioned; set any thread to All / Mentions-only / Mute from the panel's bell menu (muted threads stop bumping badges; syncs across devices) - See who has read each message, and track delivery status (sending / sent / failed) - Bookmark any message and revisit saved messages from the sidebar - Schedule messages to send at a specific time