docs: comprehensive audit pass — all 5 agent findings integrated into TODO
CI / Build & Quality Checks (push) Failing after 5m42s

Key findings:
- Jump to Date (task #7): DELETED — JumpToTime.tsx fully implemented upstream,
  wired in RoomViewHeader.tsx:215
- useUnverifiedDeviceCount() hook EXISTS (useDeviceVerificationStatus.ts:65) —
  task #65 is trivial
- useCallMembersChange() hook (useCall.ts:37-52) handles join/leave sounds
  via MatrixRTCSessionEvent.MembershipsChanged — correct approach for #89
- MessageQuickReactions already in hover toolbar (Message.tsx:146-184) — #92
  simpler than expected
- knockSupported() utility exists (matrix.ts:376) — #58 only needs RoomIntro button
- StateEventEditor in DevTools can already edit m.room.server_acl — #69 is a UX wrapper
- getMatrixToRoom() in matrix-to.ts already generates invite URLs — #24 just needs QR
- Glassmorphism: sidebar container safe for backdrop-filter (translateX only on items)
- Animated backgrounds: must use ::before pseudo-element, not backgroundImage
- matrix-js-sdk has no arbitrary profile field setters — #62 needs raw HTTP
- Toast system: build from scratch, insert at App.tsx:65 after OverlayContainerProvider
- JetBrains Mono already loaded via Google Fonts CDN in index.html:33
- MSC4151 report room endpoint confirmed live (405 on GET = POST-only endpoint exists)
- /.well-known/matrix/support not configured — needs server file creation + client reads

Full file reference table added with 30+ key file paths for all planned features.
Corrected 5 previously wrong architecture assumptions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 13:34:34 -04:00
parent c9a3edc142
commit 22e7252de8
+69 -18
View File
@@ -62,26 +62,77 @@ Quick Switcher, Sidebar filter, Favorite rooms, Invite link generator, Edit hist
Export history, Room preview before joining, Suggested rooms display, Server notices styling, Export history, Room preview before joining, Suggested rooms display, Server notices styling,
DM last-message preview, Media gallery, Knock-to-join full UX DM last-message preview, Media gallery, Knock-to-join full UX
### Code Architecture Facts (relevant to implementation) ### 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 `<Page>` component with `position:absolute, inset:0, z-index:-1` |
#### Confirmed facts
| Finding | Impact | | Finding | Impact |
|---|---| |---|---|
| `folds AvatarImage` does NOT accept children | Avatar overlays/frames must wrap the Avatar component externally, not nest inside it | | `folds AvatarImage` does NOT accept children | Add frame/overlay inside `UserAvatar.tsx` component itself (see correction above) |
| Sidebar `SidebarItem` has `translateX` on hover | CSS `backdrop-filter` won't work on sidebar items directly — apply to parent wrapper instead | | No in-app toast system exists | Toast redesign (#80): build `ToastProvider` + Jotai atom queue; insert after `OverlayContainerProvider` at `App.tsx:65`; use `portalContainer` div from `index.html:101` |
| Element Call bridge has NO join/leave participant events | Join/leave sounds (#89) must use `m.call.member` Matrix room state events instead | | `useUnverifiedDeviceCount()` hook EXISTS | Task #65 is trivial: `src/app/hooks/useDeviceVerificationStatus.ts:65-106` — call it in `RoomInput.tsx` |
| Element Call bridge has NO audio level events | Speaking indicator uses CSS polling of EC iframe DOM — no direct event bridge | | Voice player: `AudioContent.tsx:44-223` | Task #8: `playbackRate` on hidden `<audio>` at line 217 |
| No in-app toast system exists anywhere | Toast redesign (#80) must build a full `ToastProvider` + queue system from scratch | | Notification sounds: 2 hardcoded `.ogg` files in `ClientNonUIFeatures.tsx` | Task #22: replace hardcoded paths with `settingsAtom` value |
| Voice message player: `AudioContent.tsx:44-223` | Speed control (#8): add `playbackRate` on the hidden `<audio>` element at line 217 | | Chat backgrounds: `chatBackground.ts`, applied to `<Page>` in `RoomView.tsx:106` | Task #77: animated backgrounds need CSS class + `::before` pseudo-element approach |
| Notification sounds: 2 hardcoded `.ogg` files | Custom sounds (#22): replace file path with settingsAtom value | | `KeywordMessages.tsx` already implements custom keyword push rules | Task #61: only non-keyword rule types need new UI |
| Chat backgrounds: `chatBackground.ts`, applied to `<Page>` in `RoomView.tsx` | Animated wallpapers (#77): add new entries returning CSS animation keyframe strings | | `StateEventEditor.tsx` in Developer Tools can already edit any state event | Task #69: build user-friendly ACL UI in Permissions tab, not from scratch |
| Push rule UI: mode switcher only, no custom rule creation | Full push rule editor (#61) is a significant build from scratch | | URL preview: `urlPreview: true`, `encUrlPreview: false` in settings.ts | Task #49: one-line default change + warning string |
| URL preview: `urlPreview: true` default, `encUrlPreview: false` default | Task #49: only need to change `encUrlPreview` default to `true` + add warning text | | Private read receipts: `ReceiptType.ReadPrivate` in SDK, `markAsRead()` has param | Task #34: trivially simple |
| Private read receipts: `ReceiptType.ReadPrivate` already in SDK | Task #34: very simple — `markAsRead()` in `notifications.ts` already has `privateReceipt` param | | Right-click room menu: 6 items in `RoomNavItem.tsx:70-220` | Task #102: add Mute-duration submenu using `PopOut` same as Notifications item |
| Right-click room menu: 6 items (Mark read, Notifications, Invite, Copy Link, Settings, Leave) | Task #102: add Mute-with-duration submenu and consolidate | | GIF links render as generic OG preview cards | Task #42: inline GIF embed needs explicit URL pattern detection + `<img>` render |
| Glassmorphism: sidebar uses `translateX` transform | Must apply `backdrop-filter` to a parent div, not the sidebar element itself | | Toolbar buttons (in order): Attach, Formatting, Emoji/Sticker, GIF, Location, Voice, Send | Task #43: sequential array in `RoomInput.tsx` after/before props |
| JetBrains Mono: NOT bundled, relies on system fonts | Font selector (#98): must bundle fonts as `public/font/*.woff2` files | | `MessageQuickReactions` already in hover toolbar (4 recent emojis) | Task #92: increase limit, adjust layout position |
| GIF links (Giphy/Tenor): render as generic OG preview cards, NOT auto-embedded | Task #42: inline GIF embed needs to be built | | `knockSupported()` utility EXISTS at `matrix.ts:376-391` | Task #58: just need "Request to Join" button in `RoomIntro.tsx:25-119` |
| Composer toolbar buttons (in order): Formatting, Emoji/Sticker, GIF, Location, Voice, Send | Task #43: configurable toolbar is straightforward — buttons are a sequential array | | `CallControl.setMicrophone(bool)` at `CallControl.ts:206-212` | Task #84: call this directly for AFK auto-mute |
| Message hover toolbar: quick reactions row already exists inside Menu component | Task #92: quick reaction bar is already partially there via `MessageQuickReactions` | | matrix-js-sdk has NO arbitrary profile field methods | Task #62: use `mx.http.authedRequest()` for MSC4133 raw HTTP calls |
| `JumpToTime.tsx` FULLY IMPLEMENTED and wired in `RoomViewHeader.tsx:215` | Task #7: DELETED — already upstream |
| Poll voting already implemented in `PollContent.tsx:189-213` | Task #9: only CREATE UI needed |
| `useRecentEmoji(mx, 4)` provides the quick reaction data | Task #92: same source as full emoji board |
| `getMatrixToRoom()` in `matrix-to.ts` already generates invite URLs | Task #24: just add QR code display to room settings |
| `/.well-known/matrix/support` not configured on server | Task #67: client reads gracefully if present; Jared must CREATE the file server-side |
| MSC4151 report room endpoint returned HTTP 405 on GET → POST-only → EXISTS | Task #59: endpoint is live, just needs POST with JSON body |
| `/timestamp_to_event` returned 401 (needs auth) → EXISTS | Jump to Date already works — task deleted as upstream |
| `useCallSpeakers.ts` uses CSS MutationObserver polling on EC iframe DOM | Task #107: can augment with TDS ring animation on top of existing data |
#### Key file quick reference
| What you need | File | Lines |
|---|---|---|
| Global keydown hook | `src/app/hooks/useKeyDown.ts` | whole file |
| Room navigation | `src/app/hooks/useRoomNavigate.ts` | 19-72 |
| All room IDs atom | `src/app/state/room-list/roomList.ts` | `allRoomsAtom` |
| Room unread counts | `src/app/state/room/roomToUnread.ts` | `roomToUnreadAtom` |
| Overlay portal provider | `src/app/pages/App.tsx` | 65 |
| Portal container div | `index.html` | 101 |
| Room settings tabs | `src/app/features/room-settings/RoomSettings.tsx` | 27-56 |
| State event read/write pattern | `src/app/features/common-settings/general/RoomEncryption.tsx` | 42-52 |
| Power level checker | `src/app/hooks/usePowerLevels.ts` | whole file |
| Slash command registration | `src/app/hooks/useCommands.ts` | 140-537 |
| Chat background picker | `src/app/features/settings/general/General.tsx` | 945-981 |
| Chat backgrounds definition | `src/app/features/lotus/chatBackground.ts` | whole file |
| Matrix.to URL builder | `src/app/plugins/matrix-to.ts` | `getMatrixToRoom()` |
| Media event content types | `src/app/types/matrix/common.ts` | 46-91 |
| Media URL conversion | `src/app/utils/matrix.ts` | `mxcUrlToHttp()` |
| Message pagination (search) | `src/app/features/message-search/useMessageSearch.ts` | 74-121 |
| Infinite pagination pattern | `src/app/features/message-search/MessageSearch.tsx` | 234-365 |
| Poll event format | `src/app/components/message/content/PollContent.tsx` | 1-320 |
| Theme class application | `src/app/hooks/useTheme.ts` | 25-60 |
| Animations file | `src/app/styles/Animations.css.ts` | whole file |
| Message status (EventStatus) | `src/app/features/room/message/Message.tsx` | 84-142 |
| Call member change events | `src/app/hooks/useCall.ts` | 37-52 |
| Mic control in calls | `src/app/plugins/call/CallControl.ts` | 206-212 |
| Device verification hook | `src/app/hooks/useDeviceVerificationStatus.ts` | 65-106 |
| Knock room support check | `src/app/utils/matrix.ts` | 376-391 |
| Room join button location | `src/app/components/room-intro/RoomIntro.tsx` | 25-119 |
| Notification mute via push rules | `src/app/hooks/useRoomsNotificationPreferences.ts` | 110-150 |
| Message text body CSS | `src/app/components/message/layout/layout.css.ts` | 182-205 |
--- ---