Captures the plan to fork element-hq/element-call and build it from source for true ownership of the in-call experience (decorations, focus/screenshare, reconnect mic, native theming, call-audio injection) — none of which are fixable against the prebuilt @element-hq/element-call-embedded bundle we ship today. - New HANDOFF_ELEMENT_CALL_FORK.md: self-contained plan for a fresh session (current architecture, full file inventory, phases, new-repo decision, the denoise-shim interaction, doc corrections). - Tagged every related note with [EC-FORK] + links: README (For Developers), LOTUS_BUGS (EC limitations), LOTUS_TODO (soundboard, denoise, soundboard cross-origin correction), LOTUS_FEATURES (call section). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8.1 KiB
Lotus Chat — Open Bugs & Technical Debt
Only OPEN and awaiting-verification items live here. Resolved findings
(fixed-and-verified, false-positives, won't-fix) have been removed to keep this
actionable — the full history is in git. Items fixed in code but not yet
verified in a real environment are in Needs Verification below and have
step-by-step checks in LOTUS_TESTING.md.
Design rules for any fix here: follow the Native-Cinny Law and TDS Design Law in
LOTUS_TODO.md.
⚠️ Needs Verification — fixed in code, awaiting live testing
Implemented and gate-green; confirm each per LOTUS_TESTING.md, then delete the row.
| ID | Item | File / area | Test |
|---|---|---|---|
| #2 | Chat-background animation flicker (contain:paint) |
lotus/chatBackground.ts |
F1 |
| #4 | Ringtone re-fixes: classic loudness + caller decline notice (A2 ✓ live) | CallEmbedProvider.tsx, ringtones.ts |
A1,A3,A4 |
| #6 | Background vs. seasonal theme mutual exclusion | state/settings.ts, General.tsx |
F2 |
| #7 | Composer toolbar touch targets (≥44px) | room/RoomInput.tsx |
E1 |
| #8 | Room Settings horizontal overflow (mobile) | components/page/style.css.ts |
E2 |
| #9 | Modal fullscreen on mobile (useModalStyle) |
22+ modal files | E3 |
| #10 | Composer not hidden by keyboard (100dvh) |
src/index.css |
E4 |
| #12 | PiP "All muted" badge re-fixed (was firing on any single mute) | hooks/useCallSpeakers.ts |
G1 |
| N96 | Call-recovery overlay single "Back" button | call/CallView.tsx |
A7 |
| N95 | AFK-monitor mic released on mute (OS indicator clears) | hooks/useAfkAutoMute.ts |
L1 |
| N108 | Maskable PWA icons (Android adaptive) | public/manifest.json + res/android/maskable-* |
L2 |
| EC | EC iframe load watchdog + self-heal + recovery UI | plugins/call/CallEmbed.ts, CallView.tsx |
A7 |
| Gal | MediaGallery lazy-decrypt (true virtualization deferred) | room/MediaGallery.tsx |
H1 |
| a11y | aria-labels: edit-history / reaction / thread / reply | message/* (FallbackContent, Reaction, Reply) |
I |
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.
🧩 Known Element Call iframe limitations (not fixable from our side)
🔱 [EC-FORK] These are the motivating issues for the Element Call fork initiative — see
HANDOFF_ELEMENT_CALL_FORK.md. Once we build EC from our own source, A5/A6/A7 below become normal code fixes. (Correction: the iframe is actually same-origin / self-hosted — we just don't own EC's compiled source today.)
The in-call participant grid is rendered inside EC's iframe (a pre-built npm bundle we don't own), which we can style/place around but cannot change the logic of. Consequences from testing:
- A5 — "Focus camera": EC already supports native tile-pinning (click a video tile). Our bottom-bar "Focus camera" is a programmatic wrapper that clicks that tile; it can't live inside EC's UI. During a screenshare EC spotlights the shared screen and a camera pin may not override it. Decision: keep the shortcut, revisit with the larger call-UI/EC work.
- A6 — avatar decorations in-call: decorations render on our pre-join
lobby roster (
CallMemberCard) but cannot be drawn on EC's in-call video tiles. Working as designed given the iframe boundary. - A7 — mic dead after EC's "Reconnect": the mid-call "Connection lost /
Reconnect" screen is EC's own (our load watchdog only covers an initial
hung load). After EC reconnects, the mic isn't re-published through our denoise
getUserMediashim until a clean End+rejoin. Tied to the denoise rework.
🔴 Open — Actionable
Calls / Audio
- N127 — ML denoise shim is never injected in
vite dev. ThelotusDenoiseplugin injects only oncloseBundle(build), so ML noise suppression is silently inactive during local dev. Add a dev-mode injection (configureServer/transformIndexHtml). Dev-only impact.
Security & Privacy
- N97 — Access token stored in plaintext
localStorage(state/sessions.ts), vulnerable to XSS; device ID likewise. Architectural — needs a token-protection / session-storage redesign. - Session writes are non-atomic and not cross-tab synced (
state/sessions.ts) — risks inconsistent state / races across tabs. - Persisted PII without encryption: user status message + expiry (
settings/account/Profile.tsx), unsent composer drafts (room/RoomInput.tsx). Leak risk on shared devices.
PWA / Offline / Notifications
- N105 — Service worker has no
notificationclickhandler — notification clicks are broken when the tab is closed. NeedsshowNotification()via the SW + anotificationclicklistener. - N107 — SW has no
pushhandler — Web Push delivery is entirely non-functional. Needs apushlistener + a Matrix push-gateway integration. - No app-asset caching strategy (
src/sw.ts) — no offline capability. manifest: falseinvite.config.js— may block correct PWA install if not handled externally.
Dependencies & Build
matrix-js-sdkpinned to a Release Candidate (41.6.0-rc.0);@atlaskitand build tools (vite,typescript,eslint) on unstable/experimental pins — review for stable versions; RC SDK is a tree-shaking/bundle-size risk.- Build-time overhead:
lotusDenoisedoes heavy sequentialfswork incloseBundle;viteStaticCopyconfig is complex with redundant renames — could be streamlined.
Code Hygiene / DevEx
- No automated test suite (
src/) — no unit/integration tests configured. - Extensive
as anycasts acrosssrc/— gradual typing cleanup. types/matrix/mirrors SDK types instead of importing them — drift risk.- Hardcoded CDN URL should move to an env var (the decoration CDN is now single-sourced in
avatarDecorations.ts, but the literal is still in-repo). patch-folds.mjseditsnode_modulesdirectly — considerpatch-package.- Infra docs:
contrib/nginxlacks security headers (HSTS/CSP) + uses rewrites overtry_files;contrib/caddyhas a placeholder path. CI/CD (prod-deploy.yml): sequential deploy, aggressive 1-min Netlify timeout,package-manager-cache: false. - README: keep the fork-sync version + logo path current. (
CONTRIBUTING.mdis intentionally left as upstream Cinny's — not a Lotus concern.) - Architecture notes (low priority): deep
features/+hooks/nesting, many small coupled hooks, possible dead CSS/components,SpacingVariant/DropTargetrecipe simplification. - Git workflow (forward-looking): keep commits scoped — past monolithic "fix all bugs" commits and inconsistent prefixes hurt
git bisect.
Big Projects
- #5 — Seasonal themes & chat-background redesign. Current backgrounds are basic CSS; goal is high-fidelity, research-backed, GPU-accelerated designs (layered
oklch,backdrop-filter,contain:paint) with WCAG-AA overlay contrast. Treat each as its own design sprint.