Adds 11 CSS-only seasonal overlays (Halloween, Christmas, New Year, Autumn, April Fool's, Lunar New Year, Valentine's Day, St. Patrick's Day, Earth Day, Deep Space, Retro Arcade) with date-based auto-detection and a manual override dropdown in Settings → Appearance → Seasonal Theme. All themes respect prefers-reduced-motion. SeasonalEffect mounts at z-index 9997 in App.tsx. Also rewrites all 5 animated chat background keyframes for smoother, more organic motion: Digital Rain gains a phosphor glow flicker; Star Drift now loops each layer by exactly its own tile size (no more seam); Grid Pulse adds an independent brightness oscillation at a prime period; Aurora Flow drives all four gradient layers through distinct paths; Fireflies adds glow-pulse and opacity-blink animations at prime periods for unsynchronised bioluminescence. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.6 KiB
Lotus Chat — Bug Report & Technical Audit
Date: June 2026
This document tracks identified bugs, edge cases, and architectural discrepancies found during the audit of the Lotus Chat codebase. Recommended fixes are provided for each item.
🛡️ Critical Security & Privacy Regressions
1. E2EE Bypass in Media Gallery Downloads
File: src/app/features/room/MediaGallery.tsx (Line 855)
Status: CRITICAL
- Issue: The "Download" button in the Files tab uses
mxcUrlToHttpdirectly and clicks an<a>link. - Impact: In encrypted rooms, this downloads the encrypted ciphertext rather than the decrypted file. Users cannot open the downloaded files.
- Recommended Fix:
- Check if the event is encrypted.
- If encrypted, use the
decryptAttachmentlogic (similar touseDecryptedMediaUrl) to decrypt the file in memory. - Use
file-saveror a Blob URL to trigger the download of the decrypted plaintext.
2. Privacy Leak in URL Previews
File: src/app/components/url-preview/UrlPreviewCard.tsx (Line 1655)
Status: PRIVACY RISK
- Issue: Generic URL preview cards fetch favicons directly from
https://www.google.com/s2/favicons?domain=.... - Impact: This leaks the user's browsing/chat activity (domains of links they see) to Google. It bypasses the "proxied through Matrix" privacy standard.
- Recommended Fix: Use the proxy URL returned by the Matrix
/_matrix/media/v3/preview_urlendpoint instead of contacting Google directly.
🚩 Functional & Logic Bugs
1. Presence Updater Reverts Status Updates
File: src/app/hooks/usePresenceUpdater.ts (Line 20)
Status: High Priority
- Issue: The
storedStatusvariable is captured once when theuseEffectstarts. - Impact: If a user updates their status message in the Profile settings, the presence updater hook continues to use the old status message from its closure. Every time the user moves their mouse/activity, the hook sends
setOnlinewith the stale status, reverting the user's change. - Recommended Fix:
- Read the status from
localStorageinside thesetOnline/setUnavailablefunctions rather than at the top of the effect.
- Read the status from
2. Audio Playback Rate Reset
File: src/app/components/message/content/AudioContent.tsx (Line 97)
Status: UX Bug
- Issue: The
playbackRateis set in auseEffectthat only depends on[playbackSpeed]. - Impact: If a user selects a playback speed before the audio blob has finished loading, the
<audio>element may reset its rate to 1.0 once the<source>is added. - Recommended Fix: Add
srcState.datato theuseEffectdependencies or set theplaybackRatein anonCanPlayhandler on the audio element.
3. Room Insights are Static (No Live Updates)
File: src/app/features/room-settings/RoomInsights.tsx (Line 60)
Status: Medium Priority
- Issue: Stats are calculated in a
useMemothat only depends on[room]. - Impact: If new messages arrive while the Insights page is open, the statistics (message counts, top participants, etc.) do not update.
- Recommended Fix: Add a listener for
RoomEvent.Timelineinside the component to trigger a recalculation when new events are added to the room.
4. Incorrect Ringing in Voice Rooms
File: src/app/components/CallEmbedProvider.tsx
Status: Logic Bug
- Issue: Joining a static voice room (Public Space channel) triggers the "Incoming Call" ringing animation and sound. This should only occur for "StartedByUser" intents (DMs and Private Group Calls).
- Root Cause: The ringing logic does not distinguish between persistent voice rooms and user-initiated calls.
- Recommended Fix: Check
room.getJoinRule()or check for them.space.parentevent. If the room is a public voice channel, suppress the ringing animation.
🎨 UI/UX & Visual Consistency
1. Hardcoded Primary Color in Polls
File: src/app/components/message/content/PollContent.tsx (Line 245)
Status: TDS Violation
- Issue: Uses
rgba(var(--mx-primary-rgb, 0,132,255), ...)for selected options and borders. - Impact: Polls look like standard Cinny and ignore the Lotus Terminal Design System (TDS) colors.
- Recommended Fix: Use
var(--lt-accent-cyan)or the primary theme accent color.
2. Inaccessible Room Menu on Mobile
File: src/app/features/room-nav/RoomNavItem.tsx (Line 643)
Status: MOBILE BUG
- Issue: The room menu icon (
VerticalDots) is hidden on mobile becausehoveris never active. - Impact: Mobile users cannot access room settings, mark as read, or leave rooms from the sidebar.
- Recommended Fix: Ensure the menu button is visible on mobile for the active room or provide an alternative trigger.
3. Inconsistent Settings Dropdown Styling
File: src/app/features/settings/general/General.tsx
Status: UI Consistency
- Issue: The dropdowns for "Join & Leave Sounds" and "UI Font" use raw HTML
<select>elements, which look different from the custom-styledMenuused elsewhere. - Recommended Fix: Replace raw selects with the
Menu+PopOutpattern used in the "Message Layout" setting.
4. No Camera Focus During Screenshare
File: src/app/features/call/CallControls.tsx
Status: UX Bug
- Issue: When someone is screensharing and another participant turns on their camera, there is no way to switch the primary display to the camera or go fullscreen on it.
- Recommended Fix: Implement a "Pin/Focus" toggle on participant tiles that overrides the automatic screenshare spotlight.