# 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 & UI Bugs ### 1. Drag-and-Drop Overlay Persistence **File:** `src/app/hooks/useFileDrop.ts` **Status:** Confirmed (Backlog item #!BUG) * **Issue:** The file drop overlay remains visible if a user drags a file over the browser window and then moves the mouse out of the window without dropping. * **Root Cause:** The `dragleave` event does not reliably decrement the internal `dragCounter` when the mouse leaves the browser viewport entirely. * **Recommended Fix:** Update the `handleDragLeave` function to detect when the mouse has left the window by checking if `evt.relatedTarget` is null. ### 2. Stale Member List in Verification Banner **File:** `src/app/hooks/useDeviceVerificationStatus.ts` **Status:** High Priority * **Issue:** The "Unverified Device Warning" banner may fail to appear for users who join a room after it has already been opened in the client. * **Root Cause:** The `memberIds` array is memoized only on `room.roomId`. New members joining the room do not trigger a recalculation of the list, meaning their devices are never checked. * **Recommended Fix:** Add the room's joined member count to the memoization dependencies. ### 3. Night Light Overlay Coverage (Portal Issue) **File:** `src/app/pages/App.tsx` **Status:** UI Consistency * **Issue:** The Night Light (blue light filter) overlay is rendered inside the `#root` div. However, Cinny's modals, tooltips, and popouts are rendered inside a sibling `#portalContainer`. * **Impact:** Modals and tooltips will appear at full brightness, bypassing the filter. * **Recommended Fix:** Move the `NightLightOverlay` component to the end of `document.body` or utilize a Portal to render it inside `#portalContainer` with a high z-index (e.g., 9999). ### 4. Decrypted Media Memory Leak (Gallery & Lightbox) **File:** `src/app/features/room/MediaGallery.tsx` **Status:** Performance / Memory * **Issue:** Every image in the gallery history is decrypted and converted to a Blob URL simultaneously. * **Impact:** Scrolling through long room histories can consume gigabytes of RAM, as Blob URLs are not revoked until the gallery is closed. * **Recommended Fix:** Implement virtualization for the gallery grid. Only decrypt and create URLs for items currently in or near the viewport. --- ## 🎨 UI/UX & Visual Consistency ### 1. Search Button Hidden in E2EE Rooms **File:** `src/app/features/room/RoomViewHeader.tsx` **Status:** Major UX Regression * **Issue:** The message search icon is hidden in encrypted rooms. * **Impact:** Users cannot access the "Encrypted Room Search" feature (local cache scan) from the room header, even though the feature is implemented and functional in the search page. * **Recommended Fix:** Remove the `!encryptedRoom` condition from the Search button renderer in the header. ### 2. TDS Design Law Violations (Hardcoded Hex) **Files:** `src/app/components/GifPicker.tsx`, `src/app/components/VoiceMessageRecorder.tsx` **Status:** Styling Integrity * **Issue:** Multiple custom components use hardcoded hex values (e.g., `#FF6B00`, `#060c14`) instead of the CSS variables defined in `lotus-terminal.css.ts`. * **Impact:** These components will not adapt if theme tokens are updated in the central TDS file, and they bypass the "Design Law" established in the backlog. * **Recommended Fix:** Replace all hardcoded hex values with `var(--lt-accent-orange)`, `var(--lt-bg-secondary)`, etc. ### 3. Missing CSS Variable `--bg-surface-variant` **Files:** `src/app/features/message-search/MessageSearch.tsx`, `src/app/components/VoiceMessageRecorder.tsx` **Status:** UI Bug * **Issue:** Components use `var(--bg-surface-variant)`, which is not defined in either `index.css` or `lotus-terminal.css.ts`. * **Impact:** Backgrounds for the voice recorder and search cache panels appear transparent or fall back to browser defaults. * **Recommended Fix:** Define `--bg-surface-variant` in both global themes and the TDS theme, or switch to using `--bg-surface-low`. ### 4. Recent vs. Top Emoji Logic Discrepancy **File:** `src/app/plugins/recent-emoji.ts` **Status:** Logic Inconsistency * **Issue:** The "Quick Reactions" hover bar is described as showing the "3 most recently used emojis." However, the implementation sorts by `usage count`, meaning it actually shows the "most frequently used" emojis. * **Impact:** If a user uses a new emoji, it will not appear in the quick reactions until its total usage count exceeds the current top 3. This contradicts user expectations for a "recently used" list. * **Recommended Fix:** Update `getRecentEmojis` to sort by the order in the array (which is unshifted in `addRecentEmoji`) or add a timestamp to each emoji entry in the account data to allow true chronological sorting. --- ## 🔍 Technical Refinements ### 1. Incomplete Python Comment Highlighting **File:** `src/app/utils/syntaxHighlight.ts` **Status:** Medium Priority * **Issue:** Python comments (`#`) are only highlighted if they appear at the very start of a line. Inline comments like `print("hello") # comment` are treated as plain text. * **Recommended Fix:** Update the detection logic to allow `#` after whitespace or tabs. ```typescript // Recommended (i === 0 || code[i - 1] === '\n' || code[i - 1] === ' ' || code[i - 1] === '\t') ``` ### 2. Duplicate Bookmarking Race Condition **File:** `src/app/hooks/useBookmarks.ts` **Status:** Data Integrity * **Issue:** Rapidly clicking the bookmark button can trigger multiple `setAccountData` calls that read from the same stale local cache, potentially overwriting each other. * **Recommended Fix:** Implement a queue or locking mechanism for account data updates to ensure atomicity. ### 3. Presence Updater Matrix Base URL Access **File:** `src/app/hooks/usePresenceUpdater.ts` **Status:** Best Practice * **Issue:** The code uses a hacky cast: `(mx as unknown as { baseUrl: string }).baseUrl`. * **Recommended Fix:** Use the standard SDK method `mx.getHomeserverUrl()`. ### 4. Encrypted Search Misses Historic Events **File:** `src/app/features/message-search/useLocalMessageSearch.ts` **Status:** Functional Limitation * **Issue:** The search only scans `room.getLiveTimeline().getEvents()`. * **Impact:** If a user has scrolled back and loaded historic messages into linked timelines, those messages will be ignored by the search. * **Recommended Fix:** Iterate through all timelines in the room's primary `TimelineSet` using `room.getUnfilteredTimelineSet().getTimelines()`. ### 5. useAccountDataCallback Memoization Risk **File:** `src/app/hooks/useAccountDataCallback.ts` **Status:** Maintenance Risk * **Issue:** The hook attaches/detaches a Matrix event listener every time the `onAccountData` callback changes. If a component using this hook does not memoize the callback (via `useCallback`), the listener will be churned on every render. * **Impact:** Potential performance degradation and subtle event-handling bugs if listeners are added/removed multiple times per second. * **Recommended Fix:** Add a JSDoc warning to the hook file instructing developers to always wrap the callback in `useCallback`. --- ## 📝 Documentation & Accessibility ### 1. Documentation Discrepancy (EC Spotlight) **Files:** `LOTUS_FEATURES.md` vs `matrix/README.md` * **Issue:** `LOTUS_FEATURES.md` claims there is an "Auto-revert spotlight on screenshare" feature. `matrix/README.md` correctly states this was **removed** as it broke fullscreen views. * **Action:** Update `LOTUS_FEATURES.md` to remove the mention. ### 2. Presence Badge Accessibility **File:** `src/app/components/presence/Presence.tsx` **Status:** Accessibility * **Issue:** `aria-labelledby` refers to a Tooltip ID that may not be in the DOM when the badge is first read by a screen reader. * **Recommended Fix:** Add a descriptive `aria-label` directly to the `Badge` component (e.g., `aria-label="Status: Online"`). ### 3. Missing Status Tooltip on Text **File:** `src/app/features/room/MembersDrawer.tsx` **Status:** UX Improvement * **Issue:** In the members drawer, the status message text is truncated but does not have a tooltip. The tooltip only exists on the small presence dot. * **Recommended Fix:** Wrap the status text in a `TooltipProvider` to allow users to read long status messages.