diff --git a/LOTUS_BUGS.md b/LOTUS_BUGS.md index f276c8023..8bcdeb12a 100644 --- a/LOTUS_BUGS.md +++ b/LOTUS_BUGS.md @@ -1,4 +1,5 @@ # Lotus Chat — Bug Report & Technical Audit + **Date:** June 2026 This document tracks identified bugs, edge cases, and architectural discrepancies. @@ -7,66 +8,69 @@ This document tracks identified bugs, edge cases, and architectural discrepancie ## ✅ Resolved Issues (Recently Fixed) -* **GIF Sending Bypasses E2EE**: Fixed in `RoomInput.tsx`. -* **Scheduled Messages Bypass E2EE**: Fixed in `scheduledMessages.ts`. -* **Drag-and-Drop Overlay Persistence**: Fixed in `useFileDrop.ts`. -* **Stale Member List in Verification Banner**: Fixed in `useDeviceVerificationStatus.ts`. -* **Incomplete Python Comment Highlighting**: Fixed in `syntaxHighlight.ts`. -* **Search Button Hidden in E2EE Rooms**: Fixed in `RoomViewHeader.tsx`. -* **TDS Design Law Violations (Hardcoded Hex)**: Fixed in `GifPicker.tsx` and `VoiceMessageRecorder.tsx`. -* **Recent Emoji Sort Order**: Fixed in `recent-emoji.ts` (recency order, not frequency). -* **Encrypted Search Misses Historic Events**: Fixed in `useLocalMessageSearch.ts`. -* **Presence Updater Base URL Hack**: Fixed in `usePresenceUpdater.ts`. -* **Presence Badge Accessibility**: Fixed in `Presence.tsx` (`aria-label` on badge). -* **Presence Updater Wipes Custom Status**: Fixed in `usePresenceUpdater.ts` (removed `status_msg: ''`). -* **Manifest Main Icon Paths 404**: Fixed in `public/manifest.json` (`./public/android/` → `./res/android/`). Shortcut icon was already correct. +- **GIF Sending Bypasses E2EE**: Fixed in `RoomInput.tsx`. +- **Scheduled Messages Bypass E2EE**: Fixed in `scheduledMessages.ts`. +- **Drag-and-Drop Overlay Persistence**: Fixed in `useFileDrop.ts`. +- **Stale Member List in Verification Banner**: Fixed in `useDeviceVerificationStatus.ts`. +- **Incomplete Python Comment Highlighting**: Fixed in `syntaxHighlight.ts`. +- **Search Button Hidden in E2EE Rooms**: Fixed in `RoomViewHeader.tsx`. +- **TDS Design Law Violations (Hardcoded Hex)**: Fixed in `GifPicker.tsx` and `VoiceMessageRecorder.tsx`. +- **Recent Emoji Sort Order**: Fixed in `recent-emoji.ts` (recency order, not frequency). +- **Encrypted Search Misses Historic Events**: Fixed in `useLocalMessageSearch.ts`. +- **Presence Updater Base URL Hack**: Fixed in `usePresenceUpdater.ts`. +- **Presence Badge Accessibility**: Fixed in `Presence.tsx` (`aria-label` on badge). +- **Presence Updater Wipes Custom Status**: Fixed in `usePresenceUpdater.ts` (removed `status_msg: ''`). +- **Manifest Main Icon Paths 404**: Fixed in `public/manifest.json` (`./public/android/` → `./res/android/`). Shortcut icon was already correct. --- ## 🛡️ Critical Security & Logic ### 1. Edit History Broken for E2EE + **File:** `src/app/features/room/message/EditHistoryModal.tsx` **Status:** **OPEN** -* **Issue:** The modal fetches edit history via raw `fetch`. The returned events are not decrypted. -* **Impact:** In encrypted rooms, the edit history shows ciphertext or "(no text)" for all previous versions. -* **Recommended Fix:** After fetching raw events, check if they are encrypted. Use `mx.decryptEventIfNeeded(event)` for each event in the chunk before rendering. +- **Issue:** The modal fetches edit history via raw `fetch`. The returned events are not decrypted. +- **Impact:** In encrypted rooms, the edit history shows ciphertext or "(no text)" for all previous versions. +- **Recommended Fix:** After fetching raw events, check if they are encrypted. Use `mx.decryptEventIfNeeded(event)` for each event in the chunk before rendering. ### 2. Service Worker Ephemeral Sessions + **File:** `src/sw.ts` **Status:** **OPEN** -* **Issue:** Access tokens are stored in an in-memory `sessions` Map within the SW. -* **Impact:** Closing all app tabs wipes the sessions. Background tasks (like future push notification handling or media pre-fetching) will fail. -* **Recommended Fix:** Persist the session info (accessToken/baseUrl) in IndexedDB within the Service Worker so it survives app restarts. +- **Issue:** Access tokens are stored in an in-memory `sessions` Map within the SW. +- **Impact:** Closing all app tabs wipes the sessions. Background tasks (like future push notification handling or media pre-fetching) will fail. +- **Recommended Fix:** Persist the session info (accessToken/baseUrl) in IndexedDB within the Service Worker so it survives app restarts. --- ## 📱 PWA & Mobile Issues ### 1. No PWA Precaching (Offline Mode Broken) + **File:** `src/sw.ts`, `vite.config.js` **Status:** **OPEN** -* **Issue:** The Service Worker is missing the `self.__WB_MANIFEST` injection point and `precacheAndRoute` call. -* **Impact:** The app does not work offline and fails PWA installation requirements in most browsers. -* **Recommended Fix:** Add `precacheAndRoute(self.__WB_MANIFEST)` to `sw.ts` and ensure `vite.config.js` has a valid `injectionPoint`. +- **Issue:** The Service Worker is missing the `self.__WB_MANIFEST` injection point and `precacheAndRoute` call. +- **Impact:** The app does not work offline and fails PWA installation requirements in most browsers. +- **Recommended Fix:** Add `precacheAndRoute(self.__WB_MANIFEST)` to `sw.ts` and ensure `vite.config.js` has a valid `injectionPoint`. ### 2. PiP Resize Impossible on Mobile + **File:** `src/app/components/CallEmbedProvider.tsx` **Status:** **OPEN** -* **Issue:** Resizing the PiP window uses `onMouseDown` handlers which do not trigger on touch devices. -* **Impact:** Mobile users cannot resize the PiP window. -* **Recommended Fix:** Implement `onTouchStart` handlers for the resize corners, mapping touch coordinates to the same resize logic. +- **Issue:** Resizing the PiP window uses `onMouseDown` handlers which do not trigger on touch devices. +- **Impact:** Mobile users cannot resize the PiP window. +- **Recommended Fix:** Implement `onTouchStart` handlers for the resize corners, mapping touch coordinates to the same resize logic. ### 3. Double Background Animation (GPU Waste) + **File:** `src/app/pages/client/SidebarNav.tsx`, `src/app/features/room/RoomView.tsx` **Status:** **OPEN** -* **Issue:** When Glassmorphism is enabled, the chat background is mirrored to `document.body` while the `RoomView` also renders it. -* **Impact:** Two identical animations (e.g., Digital Rain) run simultaneously, doubling GPU usage on mobile. -* **Recommended Fix:** When Glassmorphism is active, make the `RoomView` background transparent and rely on the `document.body` background. - - +- **Issue:** When Glassmorphism is enabled, the chat background is mirrored to `document.body` while the `RoomView` also renders it. +- **Impact:** Two identical animations (e.g., Digital Rain) run simultaneously, doubling GPU usage on mobile. +- **Recommended Fix:** When Glassmorphism is active, make the `RoomView` background transparent and rely on the `document.body` background. diff --git a/LOTUS_FEATURES.md b/LOTUS_FEATURES.md index 3a3f564a3..645fae705 100644 --- a/LOTUS_FEATURES.md +++ b/LOTUS_FEATURES.md @@ -47,6 +47,7 @@ Last updated: June 2026. A CRT terminal aesthetic applied globally when the TDS theme is active. **Visual effects:** + - Scanline overlay via repeating `linear-gradient` pseudo-element - Vignette via radial-gradient overlay - Phosphor glow on text and accents via `text-shadow` / `box-shadow` @@ -61,14 +62,17 @@ A CRT terminal aesthetic applied globally when the TDS theme is active. | `--lt-text` | `#c4d9ee` | Body text | **Typography & chrome:** + - Monospace font stack applied to all UI elements - Terminal-style scrollbars (thin, accent-colored track) **Decorative patterns:** + - Custom hex-grid CSS background pattern - Circuit-board CSS background pattern (switchable) **Boot sequence:** + - Matrix-style boot messages on the welcome page; press Escape to skip - Implemented in `src/lotus-boot.ts` @@ -88,6 +92,7 @@ A full light-palette counterpart to the dark TDS theme. | `--lt-text` | `#111827` | Body text | **Differences from dark mode:** + - CRT effects (scanlines, vignette, phosphor glow) are disabled - Scoped to `html[data-theme="light"] body.lotusTerminalBodyClass` to avoid bleed into non-TDS themes - `ThemeManager.tsx` is responsible for setting the `data-theme` attribute on the `` element when theme changes @@ -155,6 +160,7 @@ A "Pause Background Animations" toggle is exposed in **Settings → Appearance** An optional frosted-glass sidebar style toggled in **Settings → Appearance**. **Implementation:** + - `SidebarGlass` vanilla-extract class applies `background: rgba(3, 5, 8, 0.55)` and `backdropFilter: blur(12px)` to the sidebar element - `SidebarNav.tsx` uses a `useEffect` to mirror the active chat background onto `document.body` when the glassmorphism setting is enabled, so the blur filter has meaningful content to work through - Degrades gracefully on browsers without `backdrop-filter` support (falls back to the semi-transparent background) @@ -166,6 +172,7 @@ An optional frosted-glass sidebar style toggled in **Settings → Appearance**. A warm orange overlay rendered over the entire UI to reduce blue light emission. **Implementation:** + - `NightLightOverlay` component mounted directly in `App.tsx` - CSS: `position: fixed; inset: 0; pointer-events: none; z-index: 9998` - Orange tint color with configurable opacity @@ -288,6 +295,7 @@ A pill of overlapping 24px user avatars displayed at the bottom-right of each me ### "Seen by" Modal — `EventReaders` Clicking the avatar pill opens a modal (`src/app/components/event-readers/EventReaders.tsx`) listing: + - User avatar - Display name - Formatted timestamp of when the receipt was recorded @@ -299,11 +307,11 @@ Clicking the avatar pill opens a modal (`src/app/components/event-readers/EventR Visual feedback on message delivery state, shown on the sender's own messages: -| State | Indicator | -|---|---| -| Sending (local echo) | ⟳ rotating clock icon | -| Sent (server ACK received) | ✓ checkmark | -| Failed | ✕ in red; orange glow in TDS | +| State | Indicator | +| -------------------------- | ---------------------------- | +| Sending (local echo) | ⟳ rotating clock icon | +| Sent (server ACK received) | ✓ checkmark | +| Failed | ✕ in red; orange glow in TDS | The indicator is hidden once the server confirms the event (when the internal status transitions to `null`), keeping the timeline clean for settled messages. @@ -316,7 +324,7 @@ The indicator is hidden once the server confirms the event (when the internal st - Topic `formatted_body` is rendered via `sanitizeCustomHtml` + `html-react-parser`, supporting bold, italic, links, and other inline HTML - The room header shows a plain-text preview of the topic - Clicking the topic preview opens a full modal with the formatted body -- The room settings topic editor includes a formatting toolbar with **B**, *I*, ~~S~~, and `code` buttons +- The room settings topic editor includes a formatting toolbar with **B**, _I_, ~~S~~, and `code` buttons ### Edit History Viewer @@ -395,21 +403,21 @@ Redacted events display "This message has been deleted" along with the redaction `UrlPreviewCard.tsx` implements 13 domain-specific card layouts: -| Domain | Layout | -|---|---| -| YouTube | Thumbnail, title, channel, duration | -| Vimeo | Thumbnail, title, author | -| GitHub | Repo name, description, stars/forks/language | -| Twitter / X | Avatar, display name, handle, tweet body | -| Reddit | Subreddit, post title, score, comment count | -| Spotify | Album art, track/album/playlist name, artist | -| Twitch | Stream thumbnail, streamer, game, viewer count | -| Steam | Header image, game name, price, rating | -| Wikipedia | Article title, extract excerpt | -| Discord | Server name, invite metadata | -| npm | Package name, version, description, weekly downloads | -| Stack Overflow | Question title, vote/answer count, tags | -| IMDb | Poster, title, year, rating | +| Domain | Layout | +| -------------- | ---------------------------------------------------- | +| YouTube | Thumbnail, title, channel, duration | +| Vimeo | Thumbnail, title, author | +| GitHub | Repo name, description, stars/forks/language | +| Twitter / X | Avatar, display name, handle, tweet body | +| Reddit | Subreddit, post title, score, comment count | +| Spotify | Album art, track/album/playlist name, artist | +| Twitch | Stream thumbnail, streamer, game, viewer count | +| Steam | Header image, game name, price, rating | +| Wikipedia | Article title, extract excerpt | +| Discord | Server name, invite metadata | +| npm | Package name, version, description, weekly downloads | +| Stack Overflow | Question title, vote/answer count, tags | +| IMDb | Poster, title, year, rating | Generic (non-domain-specific) cards display a Google S2 favicon. Empty or unparseable preview responses are suppressed entirely rather than showing a blank card. @@ -436,13 +444,13 @@ Generic (non-domain-specific) cards display a Google S2 favicon. Empty or unpars A presence status selector in the user panel offering five modes: -| Mode | Matrix broadcast | -|---|---| -| Online | `online` | -| Idle | `unavailable` | +| Mode | Matrix broadcast | +| -------------- | ----------------------------------- | +| Online | `online` | +| Idle | `unavailable` | | Do Not Disturb | `unavailable` + `status_msg: 'dnd'` | -| Invisible | `offline` | -| Auto | Standard Matrix presence lifecycle | +| Invisible | `offline` | +| Auto | Standard Matrix presence lifecycle | - Selection persists via the `presenceStatus` setting - `usePresenceUpdater` short-circuits its automatic presence updates when a manual mode (anything other than Auto) is selected @@ -457,6 +465,7 @@ A presence status selector in the user panel offering five modes: ### Presence Badges `PresenceBadge` component displays a colored dot indicating presence state. Used in: + - Members drawer - User settings panel @@ -465,6 +474,7 @@ A presence status selector in the user panel offering five modes: `PresenceRingAvatar` wraps any avatar component using `React.cloneElement` to inject an `outline: 2px solid` ring whose color maps to the user's presence state. `outlineOffset: 2px` ensures the ring sits cleanly outside the avatar regardless of the avatar's `border-radius`. Applied in: + - Message timeline - Members drawer - `@mention` autocomplete dropdown @@ -473,6 +483,7 @@ Applied in: ### Document Title Unread Count The browser tab title updates to reflect unread state: + - `(N) Lotus Chat` — N unread messages - `· Lotus Chat` — unread activity without a specific count - `Lotus Chat` — no unread items @@ -480,6 +491,7 @@ The browser tab title updates to reflect unread state: ### Extended Profile Fields Supports MSC4133 custom profile fields via `PUT /_matrix/client/unstable/uk.tcpip.msc4133/{userId}/{field}`: + - `m.pronouns` — displayed in profile panels - `m.tz` — IANA timezone string (e.g., `America/New_York`) @@ -488,6 +500,7 @@ Hook: `src/app/hooks/useExtendedProfile.ts` ### User Local Time When a user has `m.tz` set in their profile: + - Their profile panel shows a clock icon, their current local time, and the timezone abbreviation - The displayed time updates every 60 seconds - Respects the global `hour24Clock` setting for 12h/24h formatting @@ -509,6 +522,7 @@ A hover toolbar appears over messages, showing the 3 most recently used emojis ( ### In-App Notification Toasts `LotusToastContainer.tsx` displays rich in-app notification toasts with: + - 24px sender avatar - Sender display name - Message body preview @@ -531,6 +545,7 @@ Messages exceeding a configurable line threshold are truncated with a "Show more ### Message Send Animation A subtle animation plays on the sender's own messages as they appear in the timeline: + - `transform: scale(0.97) → scale(1)` combined with `opacity: 0.4 → 1` - Duration: 0.15s, ease-out - Only applied to the current user's outgoing messages @@ -539,6 +554,7 @@ A subtle animation plays on the sender's own messages as they appear in the time ### Right-Click Room Context Menu Right-clicking a room in the sidebar opens a context menu with: + - **Mute** with a duration submenu: 15 minutes, 1 hour, 8 hours, 24 hours, Indefinite - **Copy Room Link** — copies the `matrix.to` URI to clipboard - **Mark as Read** — marks all events in the room as read @@ -558,6 +574,7 @@ A text input at the top of the room list filters rooms by display name in real t ### DM Last Message Preview Direct message entries in the sidebar show: + - A 48-character truncated preview of the last message body - A relative timestamp (e.g., "2m ago") - Reactivity via `useRoomLatestRenderedEvent` @@ -566,6 +583,7 @@ Direct message entries in the sidebar show: ### Room Sort Order The room list sort order can be configured in **Settings → Appearance**: + - Recent Activity (default) - A → Z (alphabetical) - Unread First @@ -582,6 +600,7 @@ Persists via the `homeRoomSort` setting. ### Invite Link + QR Code `RoomShareInvite.tsx` provides a shareable invite UI: + - 160×160px QR code generated via `api.qrserver.com` - "Copy Link" button to copy the `matrix.to` URI - Also accessible via a toggle button (⊞) in the Invite modal @@ -643,6 +662,7 @@ Users can individually show or hide each composer toolbar button in **Settings - **HTML** — styled, self-contained page Features: + - Optional date range filter - Progress indicator during export - Uses `mx.paginateEventTimeline()` to retrieve history in chunks @@ -747,6 +767,7 @@ Three one-tap presets at the top of **Settings → Notifications** that apply a ### Server Notices `m.server_notice` rooms receive special treatment: + - A `Chip variant="Warning"` badge reading "Server Notice" is shown in the room header - The composer is read-only (no message input) - Invite, Report Room, and Room Settings menu items are hidden @@ -760,7 +781,7 @@ Three one-tap presets at the top of **Settings → Notifications** that apply a `mxcUrlToHttp()` calls now use the correct argument order for MSC3916 authenticated media: ```ts -mxcUrlToHttp(mx, mxcUrl, useAuthentication, width, height, 'crop') +mxcUrlToHttp(mx, mxcUrl, useAuthentication, width, height, 'crop'); ``` The `useAuthentication` parameter was previously mispositioned, causing unauthenticated requests to be sent for media in rooms that required authentication. @@ -787,32 +808,32 @@ The `encUrlPreview` setting defaults to `true` rather than `false`. A security a ## Key Custom Files -| File | Purpose | -|---|---| -| `src/lotus-terminal.css.ts` | TDS CSS variable definitions, scanline/vignette effects, dark + light palette tokens | -| `src/lotus-boot.ts` | Matrix-style boot sequence animation on the welcome page | -| `src/app/hooks/useRoomReadPositions.ts` | Reactive hook returning `Map` for per-message read receipts | -| `src/app/features/room/ReadPositionsContext.ts` | React context providing read positions map to timeline components | -| `src/app/components/read-receipt-avatars/` | `ReadReceiptAvatars` component — overlapping avatar pill with overflow count | -| `src/app/components/event-readers/EventReaders.tsx` | "Seen by" modal listing readers with display name and timestamp | -| `src/app/components/GifPicker.tsx` | Giphy-powered GIF picker, TDS-styled, gated on `gifApiKey` in config | -| `src/app/features/call/CallControls.tsx` | Push to Deafen (M key), PTT visual indicator, TDS typing dots | -| `src/app/plugins/call/CallControl.ts` | `onControlMutation()` state tracking, screenshare audio mute logic, call button scoping | -| `src/app/components/CallEmbedProvider.tsx` | PiP window, draggable overlay, navigate-on-click, imperative geometry sync | -| `src/app/plugins/call/CallEmbed.ts` | `getBoundingClientRect()`-based embed positioning, ResizeObserver sync, dark mode injection | -| `src/app/plugins/millify.ts` | Named re-export of `millify` to fix Rolldown `__toESM` CJS interop bug | -| `src/app/features/room/MediaGallery.tsx` | Images/Videos/Files gallery drawer with pagination and E2EE awareness | -| `src/app/features/room/PollCreator.tsx` | Poll creation UI for stable `m.poll.start`, single/multiple choice, 2–10 options | -| `src/app/features/common-settings/general/RoomShareInvite.tsx` | QR code + copy link invite sharing modal | -| `src/app/utils/syntaxHighlight.ts` | TDS-aware syntax highlighter using `--lt-accent-*` inline styles | -| `src/app/features/room-settings/ExportRoomHistory.tsx` | Plain Text / JSON / HTML room history export with date range and E2EE support | -| `src/app/features/room-settings/RoomActivityLog.tsx` | Human-readable mod log for member and state change events | -| `src/app/features/room-settings/RoomServerACL.tsx` | `m.room.server_acl` editor with allow/deny lists and wildcard validation | -| `src/app/features/room-settings/RoomInsights.tsx` | Room stats: top members, top reactions, media breakdown, activity heatmap | -| `src/app/features/bookmarks/BookmarksPanel.tsx` | Bookmarks sidebar panel backed by `io.lotus.bookmarks` account data | -| `src/app/hooks/useBookmarks.ts` | Hook for reading and mutating the bookmarks account data entry | -| `src/app/features/room/ScheduleMessageModal.tsx` | MSC4140 delayed event scheduling UI with date/time picker | -| `src/app/utils/scheduledMessages.ts` | Helpers for creating, listing, and cancelling MSC4140 delayed events | -| `src/app/hooks/useExtendedProfile.ts` | MSC4133 extended profile fields (`m.pronouns`, `m.tz`) read/write | -| `src/app/hooks/useLocalTime.ts` | Derives current local time from `m.tz` profile field, updates every 60s | -| `src/app/components/url-preview/UrlPreviewCard.tsx` | 13 domain-specific URL preview layouts plus generic fallback with favicon | +| File | Purpose | +| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| `src/lotus-terminal.css.ts` | TDS CSS variable definitions, scanline/vignette effects, dark + light palette tokens | +| `src/lotus-boot.ts` | Matrix-style boot sequence animation on the welcome page | +| `src/app/hooks/useRoomReadPositions.ts` | Reactive hook returning `Map` for per-message read receipts | +| `src/app/features/room/ReadPositionsContext.ts` | React context providing read positions map to timeline components | +| `src/app/components/read-receipt-avatars/` | `ReadReceiptAvatars` component — overlapping avatar pill with overflow count | +| `src/app/components/event-readers/EventReaders.tsx` | "Seen by" modal listing readers with display name and timestamp | +| `src/app/components/GifPicker.tsx` | Giphy-powered GIF picker, TDS-styled, gated on `gifApiKey` in config | +| `src/app/features/call/CallControls.tsx` | Push to Deafen (M key), PTT visual indicator, TDS typing dots | +| `src/app/plugins/call/CallControl.ts` | `onControlMutation()` state tracking, screenshare audio mute logic, call button scoping | +| `src/app/components/CallEmbedProvider.tsx` | PiP window, draggable overlay, navigate-on-click, imperative geometry sync | +| `src/app/plugins/call/CallEmbed.ts` | `getBoundingClientRect()`-based embed positioning, ResizeObserver sync, dark mode injection | +| `src/app/plugins/millify.ts` | Named re-export of `millify` to fix Rolldown `__toESM` CJS interop bug | +| `src/app/features/room/MediaGallery.tsx` | Images/Videos/Files gallery drawer with pagination and E2EE awareness | +| `src/app/features/room/PollCreator.tsx` | Poll creation UI for stable `m.poll.start`, single/multiple choice, 2–10 options | +| `src/app/features/common-settings/general/RoomShareInvite.tsx` | QR code + copy link invite sharing modal | +| `src/app/utils/syntaxHighlight.ts` | TDS-aware syntax highlighter using `--lt-accent-*` inline styles | +| `src/app/features/room-settings/ExportRoomHistory.tsx` | Plain Text / JSON / HTML room history export with date range and E2EE support | +| `src/app/features/room-settings/RoomActivityLog.tsx` | Human-readable mod log for member and state change events | +| `src/app/features/room-settings/RoomServerACL.tsx` | `m.room.server_acl` editor with allow/deny lists and wildcard validation | +| `src/app/features/room-settings/RoomInsights.tsx` | Room stats: top members, top reactions, media breakdown, activity heatmap | +| `src/app/features/bookmarks/BookmarksPanel.tsx` | Bookmarks sidebar panel backed by `io.lotus.bookmarks` account data | +| `src/app/hooks/useBookmarks.ts` | Hook for reading and mutating the bookmarks account data entry | +| `src/app/features/room/ScheduleMessageModal.tsx` | MSC4140 delayed event scheduling UI with date/time picker | +| `src/app/utils/scheduledMessages.ts` | Helpers for creating, listing, and cancelling MSC4140 delayed events | +| `src/app/hooks/useExtendedProfile.ts` | MSC4133 extended profile fields (`m.pronouns`, `m.tz`) read/write | +| `src/app/hooks/useLocalTime.ts` | Derives current local time from `m.tz` profile field, updates every 60s | +| `src/app/components/url-preview/UrlPreviewCard.tsx` | 13 domain-specific URL preview layouts plus generic fallback with favicon | diff --git a/LOTUS_TODO.md b/LOTUS_TODO.md index d0ad3c7b8..8d73ac804 100644 --- a/LOTUS_TODO.md +++ b/LOTUS_TODO.md @@ -40,32 +40,32 @@ Status: `[ ]` pending · `[~]` in progress · `[x]` completed ### Confirmed facts -| Finding | Impact | -| ----------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -| **MSC flags ON:** `msc4140` · `msc3771` · `msc3440.stable` · `msc4133.stable` · `simplified_msc3575` | All safe to use now | -| **MSC flags OFF:** `msc4306` (thread subscriptions) · `msc3882` · `msc3912` · `msc4155` | These features are BLOCKED | -| **MSC3266** room summary: returns 404 | Room Preview feature BLOCKED | -| **MSC3892** relation redaction: not in flags | Reaction Redaction feature BLOCKED | -| **MSC4260** report user: server at v1.12, endpoint may not exist | Report User feature BLOCKED | -| **MSC4151** report room: HTTP 405 on GET = endpoint exists (POST only) | Report Room live ✅ | -| `folds AvatarImage` does NOT accept children | Add frame/overlay inside `UserAvatar.tsx` itself — optional `frameName` prop | -| No in-app toast system exists (was) | Built `ToastProvider` + Jotai queue; at `App.tsx:65` | -| `useUnverifiedDeviceCount()` hook exists | `src/app/hooks/useDeviceVerificationStatus.ts:65-106` | -| Voice player: `AudioContent.tsx:44-223` | Playback rate on hidden `