docs: threads + July batch across catalog/README/TODO/BUGS
- LOTUS_FEATURES: new Threads section (+TOC) — panel, summary chips, thread composer isolation, under-the-hood notes; entries for KaTeX math, opt-in encrypted-search cache, hardened session storage, Crypto Diagnostics. - README: threads bullet (with the replies-move-to-panel release note), math, search-cache bullets. - LOTUS_TODO: P3-8 → [~] implemented + 6-step live-QA checklist; P4-1 marked unblocked. - LOTUS_BUGS: Needs Verification rows for P3-8 / P4-4 / P4-8 / session sync. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,10 @@ Implemented and gate-green; confirm each per `LOTUS_TESTING.md`, then delete the
|
||||
| N105 | Notification clicks work after tab close (SW `notificationclick` + `showNotification`) | `sw.ts`, `utils/dom.ts`, `ClientNonUIFeatures.tsx` | get a msg notif, close the tab, click it → app focuses/opens + routes to the room |
|
||||
| Gal | MediaGallery lazy-decrypt (true virtualization deferred) | `room/MediaGallery.tsx` | H1 |
|
||||
| a11y | aria-labels: edit-history / reaction / thread / reply | `message/*` (`FallbackContent`, `Reaction`, `Reply`) | I |
|
||||
| P3-8 | Thread Panel (side drawer, chips, threaded receipts, thread composer) | `features/room/thread/*`, `RoomTimeline/RoomInput` | 6-step checklist in LOTUS_TODO §P3-8 |
|
||||
| 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 |
|
||||
|
||||
**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.
|
||||
|
||||
|
||||
+61
-9
@@ -18,15 +18,16 @@ Last updated: June 2026.
|
||||
9. [Per-Message Read Receipts](#per-message-read-receipts)
|
||||
10. [Delivery Status Indicators](#delivery-status-indicators)
|
||||
11. [Messaging Enhancements](#messaging-enhancements)
|
||||
12. [Presence](#presence)
|
||||
13. [UX & Composer](#ux--composer)
|
||||
14. [Room Customization](#room-customization)
|
||||
15. [Moderation](#moderation)
|
||||
16. [Notifications](#notifications)
|
||||
17. [Server Integration](#server-integration)
|
||||
18. [Infrastructure](#infrastructure)
|
||||
19. [Desktop App Features](#desktop-app-features)
|
||||
20. [Key Custom Files](#key-custom-files)
|
||||
12. [Threads (P3-8)](#threads-p3-8)
|
||||
13. [Presence](#presence)
|
||||
14. [UX & Composer](#ux--composer)
|
||||
15. [Room Customization](#room-customization)
|
||||
16. [Moderation](#moderation)
|
||||
17. [Notifications](#notifications)
|
||||
18. [Server Integration](#server-integration)
|
||||
19. [Infrastructure](#infrastructure)
|
||||
20. [Desktop App Features](#desktop-app-features)
|
||||
21. [Key Custom Files](#key-custom-files)
|
||||
|
||||
---
|
||||
|
||||
@@ -690,6 +691,24 @@ Context menu → **Forward** allows forwarding a message to any room the user is
|
||||
- The search panel accepts `from_ts` and `to_ts` values (epoch milliseconds) passed to the search API
|
||||
- A chip shows the active date range with an **×** button to clear it
|
||||
|
||||
### Encrypted Search Cache (P4-8, opt-in)
|
||||
|
||||
Persistent local index for encrypted-room search, so coverage survives page reloads instead of requiring re-pagination + re-decryption every session.
|
||||
|
||||
- Raw IndexedDB (`lotus-search-cache`): message rows keyed `[roomId, eventId]` + per-room coverage markers; merged into local search results with in-memory-wins dedupe
|
||||
- **Opt-in, default OFF** (it stores decrypted text at rest): toggle + "Clear cached index" live in the search panel's Encrypted Rooms section, with the privacy note "Stores decrypted text on this device"
|
||||
- Always wiped on logout; any IndexedDB error degrades to a cache-miss (never breaks search)
|
||||
- Files: `src/app/utils/searchCache.ts`, `src/app/state/searchCacheEnabled.ts`, `features/message-search/useLocalMessageSearch.ts`
|
||||
|
||||
### Math / LaTeX Rendering (P4-4)
|
||||
|
||||
KaTeX-rendered math in messages, two paths:
|
||||
|
||||
- **Spec path (CS-API §11.5):** `<span/div data-mx-maths="…">` in `formatted_body` renders the attribute's LaTeX (block for div, inline for span); on render failure the element's child fallback content shows instead
|
||||
- **Plain-text path:** `$…$` (inline) and `$$…$$` (block) with conservative rules — escape-aware (`\$`), currency-guarded (`$5 and $10` stays text), never inside `code`/`pre`
|
||||
- KaTeX + its CSS load lazily on first math encountered — zero cost to the main bundle
|
||||
- Files: `src/app/utils/mathParse.ts` (+14 tests), `components/math/KaTeX.tsx`, `plugins/react-custom-html-parser.tsx`
|
||||
|
||||
### Image / Video Captions
|
||||
|
||||
Images and videos can be sent with a caption. The caption and media are sent as a single event.
|
||||
@@ -765,6 +784,31 @@ Generic (non-domain-specific) cards display a Google S2 favicon. Empty or unpars
|
||||
|
||||
---
|
||||
|
||||
## Threads (P3-8)
|
||||
|
||||
Full threaded-conversation support (`m.thread`, matrix-js-sdk `threadSupport`), Element-consistent.
|
||||
|
||||
### Thread Panel
|
||||
|
||||
A right-side drawer (mirrors the members drawer; fullscreen on mobile) with the thread's root message emphasized at top, an "N replies" divider, the full reply timeline (virtualized, back-paginates via `/relations`, decrypts E2EE threads), reactions/edits/redactions, and its own composer. Open it from **Reply in Thread** in the message menu, a reply's thread indicator, or a summary chip; close with **×** or Escape. Reading the panel sends threaded read receipts so per-thread unread counts clear.
|
||||
|
||||
### Summary Chips
|
||||
|
||||
Root messages in the main timeline show a **"N replies · time"** chip (server-aggregated `m.thread` bundle, or the live Thread once loaded) with an unread badge — threaded replies no longer render inline in the main timeline, so the chip is how conversations stay discoverable.
|
||||
|
||||
### Thread Composer
|
||||
|
||||
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).
|
||||
|
||||
### Under the Hood
|
||||
|
||||
- `threadSupport: true` (startClient) partitions thread events into SDK `Thread` timelines; markAsRead sends **unthreaded** receipts so room badges keep clearing
|
||||
- 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)
|
||||
|
||||
---
|
||||
|
||||
## Presence
|
||||
|
||||
### Discord-Style Presence Selector
|
||||
@@ -1160,6 +1204,14 @@ The `useAuthentication` parameter was previously mispositioned, causing unauthen
|
||||
|
||||
The `encUrlPreview` setting defaults to `true` rather than `false`. A security advisory chip in **Settings → Privacy** explains the tradeoff (the homeserver can see which URLs are being previewed) so users can make an informed choice.
|
||||
|
||||
### Hardened Session Storage (N97 partial, 2026-07)
|
||||
|
||||
The session persists as ONE atomic `cinny_session_v1` JSON write (previously ~10 separate localStorage keys written non-atomically). Reads prefer the blob with transparent migration from the legacy keys (dual-written one release for rollback). Cross-tab sync: logging out or in from one tab reloads the others so no tab runs with stale credentials. `state/sessions.ts` (22 tests), `hooks/useSessionSync.ts`.
|
||||
|
||||
### Crypto Diagnostics (E2EE investigation kit)
|
||||
|
||||
**Settings → Developer Tools → Crypto Diagnostics**: a capture-only ring buffer (max 200) hooks `console.warn/error` for E2EE failure signatures (OTK upload conflicts, missing call media keys, decryption errors, delayed-event timeouts) and downloads a JSON report — the evidence input for the KE-1→4 investigation. Companion runbook: [`LOTUS_E2EE_INVESTIGATION.md`](./LOTUS_E2EE_INVESTIGATION.md). `utils/cryptoDiagLog.ts`, `features/settings/developer/CryptoDiagnostics.tsx`.
|
||||
|
||||
---
|
||||
|
||||
## Desktop App Features
|
||||
|
||||
+11
-3
@@ -162,9 +162,17 @@ Status: `[ ]` pending · `[~]` in progress · `[x]` completed
|
||||
|
||||
---
|
||||
|
||||
### [ ] P3-8 · Thread Panel (full side drawer)
|
||||
### [~] P3-8 · Thread Panel (full side drawer) — IMPLEMENTED (2026-07), ⚠️ AWAITING LIVE QA
|
||||
|
||||
**⚠️ LARGEST FEATURE — 🟢 DESIGN COMPLETE (2026-07), READY FOR ITS OWN EXECUTION SESSION.** The full architecture (SDK-evidence-backed decisions, file inventory, 4-agent partition, risks, verification checklist) is in the Implementation Reference section below — no further planning needed, just a dedicated build session.
|
||||
Built per the design below (4-agent build + 2-agent review). Gates green (tsc/eslint/build/tests). **Release note: threaded replies no longer render inline in the main timeline — roots show a "N replies" chip that opens the panel.**
|
||||
|
||||
**Manual QA checklist (post-deploy):**
|
||||
1. Reply in Thread (message menu) → panel opens; send text/upload/emoji into it (appears pending → confirmed)
|
||||
2. Reply to a reply inside the panel → event carries `m.thread` + `m.in_reply_to` with `is_falling_back:false`
|
||||
3. Main timeline: root + chip only (replies absent); chip count/time updates live; unread badge appears for others' thread replies and clears after viewing the panel
|
||||
4. Room badge clears via normal markAsRead even with unread threads (unthreaded receipt)
|
||||
5. Reload: partitioning persists; encrypted-room threads decrypt (back-pagination too)
|
||||
6. Escape / × closes; mobile = fullscreen panel; switching rooms and back restores the open thread
|
||||
**What:** A right-side drawer for threaded conversations. Currently "Reply in Thread" exists but there is no panel to read or write thread replies.
|
||||
|
||||
Features:
|
||||
@@ -208,7 +216,7 @@ Features:
|
||||
|
||||
### [ ] P4-1 · Thread Notification Mode Per-Thread (MSC3771)
|
||||
|
||||
**Spec:** MSC3771 (stable). Depends on Thread Panel (#P3-8).
|
||||
**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).
|
||||
|
||||
@@ -18,6 +18,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)
|
||||
- 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
|
||||
@@ -33,6 +34,8 @@ The Lotus Chat logo (`public/res/Lotus.png`) is a derivative work based on the o
|
||||
- Search for and send GIFs from a built-in GIF picker
|
||||
- Control voice message playback speed: 0.75× / 1× / 1.5× / 2×
|
||||
- Search messages with a date range filter
|
||||
- Optional persistent search index for encrypted rooms (off by default — stores decrypted text on your device; clearable, wiped on logout)
|
||||
- Write math with LaTeX: `$inline$` and `$$block$$` render via KaTeX (spec `data-mx-maths` supported)
|
||||
- Room topics support rich formatting (bold, links, italics)
|
||||
- Deleted messages show a placeholder instead of disappearing
|
||||
- Code blocks highlight syntax for JS/TS, Python, and Rust
|
||||
|
||||
Reference in New Issue
Block a user