# Lotus Chat — Master Feature TODO **Location:** `/root/code/cinny/LOTUS_TODO.md` **Repo:** `lotus` branch at `https://code.lotusguild.org/LotusGuild/cinny` **Deploy:** push to `lotus` → CI → auto-deploy to `chat.lotusguild.org` (~11 min) This file is the single source of truth for all planned, in-progress, and backlog features. Update it as features are completed or reprioritized. --- ## ⚠️ TDS DESIGN LAW — READ BEFORE TOUCHING ANY UI > **ALL Lotus Terminal Design System (TDS) styling — colors, animations, glows, borders, fonts, spacing — MUST come exclusively from `/root/code/web_template/base.css` CSS variables.** > Do NOT hardcode hex values. Do NOT invent new variable names. Do NOT deviate from the design tokens defined in that file. > The canonical variable reference: `--lt-accent-orange`, `--lt-accent-cyan`, `--lt-accent-green`, `--lt-glow-orange`, `--lt-box-glow-*`, `--lt-border-color`, etc. > Reference implementation for code patterns: `/root/code/tinker_tickets/` (markdown.js, base.js, ticket.css) > This rule applies to EVERY task in this file without exception. --- Legend: - `[AUDIT REQUIRED]` — at least one assumption needs code/server verification before implementing - `[SERVER CHECK]` — depends on a Synapse feature or MSC; verify on `matrix.lotusguild.org` - `[LOW PRIORITY]` — implement after all higher-priority items - `[EXTREME COMPLEXITY]` — multi-sprint, plan separately before touching - `[BLOCKED]` — cannot build until a server upgrade, upstream MSC, or dependency resolves - `[IMPROVE]` — feature exists in upstream Cinny; this task enhances it for Lotus Chat Status: `[ ]` pending · `[~]` in progress · `[x]` completed --- ## AUDIT RESULTS — completed June 2026 ### Server Status - **Synapse version:** `1.153.0` (released 2026-05-19) — **FULLY UP TO DATE**, no upgrade needed - **Matrix spec reported:** up to `v1.12` formally, but newer MSC features available via `unstable_features` - **MSC feature flags confirmed ON:** `msc4140` (delayed messages) · `msc3771` (thread receipts) · `msc3440.stable` (threading) · `msc4133.stable` (extended profiles) · `simplified_msc3575` (sliding sync) - **MSC feature flags confirmed OFF:** `msc4306` (thread subscriptions — BLOCKED) · `msc3882` · `msc3912` · `msc4155` - **MSC3266** (room summary, v1.15): endpoint returned 404 — NOT available on this server - **MSC3765** (rich room topics, v1.15): NOT available as stable, but client-side rendering is still worth doing - **MSC3892** (relation redaction): not listed in flags — NOT supported, feature BLOCKED - **MSC4260** (report user, v1.14): server at v1.12 formally — NOT available as spec endpoint; **however** report user already exists upstream in Cinny (message reporting via `reportEvent`) - **MSC4151** (report room, v1.12): merged at exactly v1.12 — should be available ✅ ### Upstream Cinny Features Confirmed (exist in upstream — only improve, don't re-implement) | Feature | Location in upstream | Lotus improvement task | | ------------------------------------ | ---------------------------------------------------- | ----------------------------------- | | "Jump to Latest" button | `RoomTimeline.tsx:2180-2192` | #104 — add unread count + animation | | Mark rooms as read (per section) | `Home.tsx:73-102`, `DirectTab.tsx:29-61` | None needed | | Room upgrade / tombstone banner | `RoomTombstone.tsx`, `RoomUpgrade.tsx` | None needed | | Visual speaking indicator | `useCallSpeakers.ts:8-60`, `MemberSpeaking.tsx:1-78` | #107 — TDS animated ring | | Image + video spoilers (blur/reveal) | `ImageContent.tsx`, `VideoContent.tsx` | #105 — smooth CSS transition | | Report message per event | `Message.tsx:588-709` — `mx.reportEvent()` | #106 — add category selector | | Drag-and-drop file upload | `useFileDrop.ts` — works but overlay bug | #73 — fix overlay dismiss | | Typing indicator (animated dots) | `TypingIndicator.tsx`, `TypingIndicator.css.ts` | #108 — TDS orange dots | | Pinned messages count badge | Confirmed in upstream header icon | None needed | ### Upstream Cinny Features Confirmed MISSING (we should build these) Quick Switcher, Sidebar filter, Favorite rooms, Invite link generator, Edit history modal, Export history, Room preview before joining, Suggested rooms display, Server notices styling, DM last-message preview, Media gallery, Knock-to-join full UX ### Code Architecture Facts — Full Audit Results #### Corrected facts (previous version had errors) | Old assumption | Correct finding | | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ~~Join/leave sounds need m.call.member state events~~ | **Use `useCallMembersChange()` hook** at `src/app/hooks/useCall.ts:37-52` — subscribes to `MatrixRTCSessionEvent.MembershipsChanged`, receives old/new membership arrays | | ~~Glassmorphism needs parent wrapper (translateX blocks filter)~~ | **SAFE to apply directly to sidebar container** — `translateX` only on `SidebarItem` hover, not the sidebar container. Apply backdrop-filter to `Sidebar.css.ts:6-17` | | ~~Avatar frames must wrap externally~~ | **Modify `UserAvatar` internally** — add optional `frameName?: string` prop; renders overlay inside component. Avoids 3 different wrapper implementations | | ~~JetBrains Mono not bundled~~ | **Already loaded via Google Fonts CDN** in `index.html:33-35`. Other fonts: use `@fontsource` npm packages | | ~~Animated backgrounds: add to backgroundImage~~ | **backgroundImage can't have @keyframes** — use CSS `::before` pseudo-element on `` component with `position:absolute, inset:0, z-index:-1` | #### Confirmed facts (all audits complete as of June 2026) | Finding | Impact | | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `folds AvatarImage` does NOT accept children | Add frame/overlay inside `UserAvatar.tsx` itself — optional `frameName` prop | | No in-app toast system exists | Task #80: build `ToastProvider` + Jotai queue; insert at `App.tsx:65` after `OverlayContainerProvider`; `portalContainer` in `index.html:101` | | `useUnverifiedDeviceCount()` hook EXISTS | Task #65 is trivial: `src/app/hooks/useDeviceVerificationStatus.ts:65-106` | | Voice player: `AudioContent.tsx:44-223` | Task #8: `playbackRate` on hidden `