Commit Graph

1728 Commits

Author SHA1 Message Date
jared 9fdc6160eb fix: emoji picker works + silence 429 presence rate-limit errors
CI / Build & Quality Checks (push) Successful in 10m24s
Emoji bug root cause: EmojiBoard wraps itself in a FocusTrap with
clickOutsideDeactivates:true. When the picker was rendered inside
Input's 'after' prop, the FocusTrap treated clicks on the emoji items
as outside-clicks and deactivated (calling requestClose) before the
onEmojiSelect callback fired. Fixed by moving the emoji PopOut to be
a direct sibling of Input in the form row instead of nesting it inside
Input.after — matching the established pattern used in MessageEditor.

429 rate-limit: mx.setPresence() calls in handleClear and the
auto-clear timer effect had no rejection handling, causing unhandled
promise rejections logged to Sentry when Synapse rate-limits presence
updates. Added .catch(() => undefined) to both call sites. Sentry
issue JAVASCRIPT-REACT-E resolved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 15:20:42 -04:00
jared 0ed3c0a384 fix: emoji selection appends correctly to status input
CI / Build & Quality Checks (push) Successful in 10m32s
When focus moves to the emoji picker the input loses focus, making
selectionStart/selectionEnd unreliable. Replace the cursor-tracking
insertion with a simple functional state updater that always appends
the emoji to the end — reliable and appropriate for a short status field.

Also removes the now-unused inputRef and useRef import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:41:48 -04:00
jared b086be3def feat: auto-clear status after configurable duration
CI / Build & Quality Checks (push) Successful in 10m39s
Adds an 'Auto-clear after' dropdown to the Status Message settings tile
with options: Never / 30 min / 1 hr / 4 hr / 8 hr / Until midnight /
1 day / 7 days.

How it works:
- On save, stores the expiry timestamp in localStorage keyed by userId
  (lotus-status-expiry-<userId>) and sets expiryTs state
- A single useEffect on expiryTs drives the timer — re-saving cancels
  the previous timer cleanly via useEffect cleanup
- On mount, reads stored expiry from localStorage so auto-clear
  survives page reloads (fires immediately if already expired)
- Manual Clear Status also removes the stored expiry and cancels any
  active timer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:10:46 -04:00
jared 2707b59e20 fix: capture emoji button rect before state updater to avoid null currentTarget
React nullifies synthetic event's currentTarget before async state
updater callbacks run. Capture getBoundingClientRect() synchronously
in the onClick handler, then pass the already-computed rect into
setEmojiAnchor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:06:31 -04:00
jared c36401db7e feat: custom status message — display + editor with emoji picker
CI / Build & Quality Checks (push) Successful in 10m23s
- MembersDrawer: show presence.status as small muted text below
  username in every member row (live via useUserPresence)
- UserHero/UserHeroName: accept optional status prop; render below
  the @username handle in user profile popouts
- UserRoomProfile: pass presence?.status down to UserHeroName
- Profile settings: new ProfileStatus tile below Display Name
  * Input with inline emoji picker (lazy-loaded EmojiBoard)
  * Cursor-aware emoji insertion (preserves caret position)
  * Save via mx.setPresence({ status_msg }) / Clear button
  * Pre-fills from current presence; syncs on remote update

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 12:39:51 -04:00
jared 1c6df604b1 feat: mute screenshare audio independently + fix CI lint/prettier
CI / Build & Quality Checks (push) Successful in 10m41s
- Add screenshareAudioMuted state to CallControlState and CallControl
- setSound() now preserves screenshare audio mute when un-deafening
- Add toggleScreenshareAudio() targeting audio[data-lk-source="screen_share_audio"]
- Add ScreenshareAudioButton (volume icon, warns when muted) to controls bar
- Fix unused prevScreenshare variable (ESLint error from prior commit)
- Run Prettier on Controls.tsx and CallControl.ts (CI formatting failures)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 23:52:57 -04:00
jared b8f1cc3c08 chore: track package-lock.json, revert gitignore change
CI / Build & Quality Checks (push) Failing after 5m42s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 23:18:15 -04:00
jared eeba02aeca feat: screenshare fullscreen button + pip spotlight, fix screenshare view
- Remove revert-to-grid logic that was overriding EC's natural screenshare
  spotlight, causing fullscreen to show user avatars instead of the screen
- Add fullscreen button to call controls (visible when screensharing) that
  requests fullscreen on the call embed container
- Add FullscreenButton component with enter/exit SVG icons to Controls.tsx
- PIP mode: sync setPipMode to CallControl; auto-enable spotlight when
  screenshare is active in pip so the screenshare fills the window
- Make useCallControlState accept undefined control for safe use in
  CallEmbedProvider
- Add package-lock.json to .gitignore (generated by local npm install)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 23:16:43 -04:00
jared e07c9cc491 fix: prevent editor blur on any click inside autocomplete menu
CI / Build & Quality Checks (push) Successful in 10m44s
FocusTrap monitors focusin events and can redirect focus into the menu
container (blurring the editor) before individual MenuItem onMouseDown
handlers fire. Adding preventDefault at the container level ensures no
click anywhere inside the menu can steal focus from the editor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 21:35:38 -04:00
jared 2623e2af93 fix: prevent editor blur on mouse click in autocomplete menus
CI / Build & Quality Checks (push) Successful in 10m29s
Add onMouseDown preventDefault to all autocomplete suggestion MenuItems
so clicking a suggestion keeps the editor focused. Without this, the
mousedown event blurs the editor before onClick fires, causing Slate's
ReactEditor.toDOMNode to fail with "Cannot resolve a DOM node from Slate
node: {"text":""}" when Transforms.collapse tries to sync the selection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 21:10:01 -04:00
jared dde75ee389 fix: defer moveCursor to next tick to prevent Slate DOM resolution crash
CI / Build & Quality Checks (push) Successful in 11m12s
When selecting an autocomplete suggestion (user/room mention, emoticon,
command), Slate's replaceWithElement inserts a void inline node into the
model but React hasn't flushed the DOM update yet. Calling
Transforms.move + insertText immediately after causes ReactEditor.toDOMNode
to fail with "Cannot resolve a DOM node from slate node: {\"text\":\" \"}".

Fix: wrap moveCursor body in setTimeout(fn, 0) so React can flush the void
element's DOM node before Slate attempts to resolve the cursor position.
Also call ReactEditor.focus to restore editor focus after the autocomplete
menu item click blurs the editor.

Fixes all callers: UserMentionAutocomplete, RoomMentionAutocomplete,
EmoticonAutocomplete, CommandAutocomplete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 17:16:37 -04:00
jared 4e6b045c57 ui: incoming call button hierarchy + EventReaders timestamp glow
CI / Build & Quality Checks (push) Successful in 10m24s
- IncomingCall: Reject uses variant=Critical (red), Ignore uses variant=Secondary
  — previously both were variant=Success (green), making them visually identical
  to the Answer button
- EventReaders: TDS timestamp glow reduced from double-layer to single-layer
  (was 0 0 6px + 0 0 14px, now just 0 0 5px at 0.45 opacity)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:34:55 -04:00
jared 928c796316 ui: voice recorder pulse + TDS styling, wire mic denied error to input bar
- VoiceMessageRecorder recording dot now pulses (reuses pttLivePulse keyframe)
- Added data-voice-recorder / data-voice-rec-dot / data-voice-waveform attributes
  for TDS targeting: green pulsing dot, cyan waveform bars, subtle border in TDS dark
- Wire VoiceMessageRecorder onError to the same input-bar error display used by
  location errors (mic denied, media error surfaces to user instead of silent fail)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:30:12 -04:00
jared f8cc11e125 ux: reply null state, location error feedback, retry send, reaction keyboard nav
CI / Build & Quality Checks (push) Successful in 10m17s
- Reply: distinguish loading (placeholder) from not-found (null) — show
  "Original message not available" instead of a stuck loading bar
- RoomInput: geolocation errors now surface inline (denied / timed out /
  unsupported); location button shows Spinner during fetch and is disabled
- Message menu: Retry Send + Cancel Message items appear when a message
  is in NOT_SENT or CANCELLED state, calling mx.resendEvent / cancelPendingEvent
- ReactionViewer: sidebar gains role=listbox / role=option and ArrowUp/Down
  keyboard navigation between reactions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 00:02:19 -04:00
jared f3b5e550f9 ui: visual polish — animations, icons, and interaction improvements
CI / Build & Quality Checks (push) Successful in 10m15s
- Spin animation on ⟳ delivery status during SENDING/ENCRYPTING states
- Pulsing ● dot on PTT LIVE badge (pttLivePulse keyframe)
- Read receipt pill: hover scale/opacity transition, symmetric padding
- PiP resize handles: larger dots (5px), wider hit area (24px), higher contrast
- ForwardMessageDialog: position:relative on scroll container, spinner overlay 0.35 opacity
- Boot sequence: 45ms interval (was 65ms), brighter ESC hint (0.55 opacity)
- Location button: Icons.Pin → Icons.SpaceGlobe (globe icon)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:52:58 -04:00
jared 79d959934c chore: prettier format ForwardMessageDialog.tsx and lotus-terminal.css.ts
CI / Build & Quality Checks (push) Successful in 10m11s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:22:49 -04:00
jared 6134c36119 chore: prettier format PollContent.tsx and index.css
CI / Build & Quality Checks (push) Failing after 5m38s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:02:34 -04:00
jared df99038ad6 ui: forward dialog avatars, poll TDS, delivery icon, caption focus, boot hint
CI / Build & Quality Checks (push) Failing after 5m46s
ForwardMessageDialog:
- Room list now shows small avatars (48px crop) + DM label beneath room name
- Forward is now async: spinner overlay while in-flight, '✓ Forwarded' only
  shown after sendEvent resolves; error clears sending state so user can retry
- Search bar hidden in success state for cleaner confirmation view

DeliveryStatus:
- QUEUED state used  emoji breaking the ASCII/terminal aesthetic; changed
  to ⟳ matching the SENDING/ENCRYPTING icon

PollContent:
- Added data-poll-content + data-poll-answer + data-selected attributes so
  TDS CSS can override inline styles without JS branching
- Added data-poll-content-label on the ◉ Poll header
- TDS dark: answers get cyan dim bg/border, selected gets orange highlight
  with subtle box-shadow; hover brightens border; label uses cyan glow
- TDS light: equivalent blue/orange variants

Caption input:
- Marked with data-caption-input; focus-visible ring added in index.css
  (blue for default, dark-theme dark blue) and lotus-terminal.css.ts
  (orange glow for TDS dark, orange for TDS light)

Boot sequence:
- Added '[ ESC ] skip' hint at bottom-right of overlay so users know
  they can dismiss it without waiting

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:01:13 -04:00
jared dd5cede31d fix: screenshare dismiss, GIF header, PiP resize, call subtitle, CSS vars
CI / Build & Quality Checks (push) Failing after 5m37s
- CallControls: screenshare confirm now closes on Escape or click-outside
  (transparent fixed backdrop + window keydown listener); cleaned indentation
- GifPicker: TDS header rendered a JSX comment ({/* GIF_SEARCH */}) so the
  // GIF_SEARCH label was invisible; changed to {'// GIF_SEARCH'}
- CallEmbedProvider: PiP resize clamping now works at initial bottom/right
  position by normalising to top/left before parsing el.style.left
- CallEmbedProvider: incoming call subtitle now reads 'Incoming Video Call'
  or 'Incoming Voice Call' based on m.call.intent
- PollContent: progress bar background now uses --bg-surface-active /
  --bg-surface-low instead of hardcoded white (invisible in light mode)
- index.css + lotus-terminal.css.ts: define --bg-surface, --bg-surface-low,
  --bg-surface-active, --bg-surface-border, --text-primary as global CSS vars
  with vanilla fallbacks and TDS dark/light overrides; these were used by
  poll, location map, upload card and GIF picker but never defined

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:51:56 -04:00
jared 2eb5e94aed fix: prevent allow_redirect=true on media URLs; fallback on 400 too
CI / Build & Quality Checks (push) Successful in 10m23s
Synapse's thumbnail endpoint returns 400 Bad Request when the
allow_redirect=true query parameter is present (added by matrix-js-sdk
41.x for authenticated media). Default allowRedirects to false in our
mxcUrlToHttp wrapper so the parameter is never appended.

Also extend the downloadMedia legacy-URL fallback to cover 400 in
addition to 401, catching any encrypted-media fetches that still carry
the old URL shape after a cache refresh.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:25:13 -04:00
jared 3ebdff3410 fix: fallback to legacy media URL on 401, fix EC avatar letter centering
CI / Build & Quality Checks (push) Successful in 10m20s
downloadMedia: on 401 (SW session race or allow_redirect hop stripping
auth), retry via /_matrix/media/v3/ which is public on this homeserver
(allow_public_access_to_media_repo: true). Fixes images not loading
after sending, and avatar 401s in call prescreen tiles.

CallEmbed: inject flex-centering CSS for EC 0.19.4 participant avatar
container so the initial letter is correctly centered in its circle.
CSS class names are scoped to _avatarContainer_1mrho_40 in EC 0.19.4.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:01:45 -04:00
jared 8cbb0f2c6b fix: bump matrixRTC maxListeners to suppress MaxListenersExceededWarning
Each RoomNavItem subscribes to session_started/session_ended on the
MatrixRTCSessionManager, one per visible room. The default limit of 10
fires a spurious warning when 11+ rooms are in the sidebar. Listeners
are properly cleaned up — this is not a real leak.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 21:40:12 -04:00
jared 84fcc161ea fix: throw on non-OK response in downloadMedia (Fixes JAVASCRIPT-REACT-B)
CI / Build & Quality Checks (push) Successful in 10m23s
When the server returns a 4xx/5xx, downloadMedia was silently returning
the error response body as a blob. decryptAttachment would then fail with
a misleading 'Mismatched SHA-256 digest' instead of surfacing the real
HTTP error. Now throws immediately so callers (useAsyncCallback) can
show the correct error state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 20:38:24 -04:00
jared 15a54eca4b chore: remove debug console.log calls from CallEmbed
CI / Build & Quality Checks (push) Successful in 10m21s
Remove [CallEmbed] state, container styles, and syncCallEmbedPlacement
debug logs that were flooding the console during call sessions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 20:16:45 -04:00
jared 2e1e61c963 feat: show presence status badges in member list panels
Add online/offline/idle presence dots next to verification shields in
both the room members drawer and the common-settings members list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 20:13:08 -04:00
jared a3b3ca90c9 fix: replace non-existent Icons.Device with Icons.Monitor in SessionsSection
CI / Build & Quality Checks (push) Successful in 10m18s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 19:56:53 -04:00
jared 467275fc02 feat: add other-user device sessions list with per-device verification
CI / Build & Quality Checks (push) Successful in 10m25s
Adds a collapsible "Sessions" section to the user profile card that
appears when cross-signing is active and the profile belongs to another
user. Each session shows a colour-coded shield (green = verified, yellow
= unverified) and a "Verify" button for unverified devices that
initiates the SAS emoji flow via crypto.requestDeviceVerification.

New hook useOtherUserDevices fetches the target user's device list via
crypto.getUserDeviceInfo and reacts to CryptoEvent.DevicesUpdated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 19:44:22 -04:00
jared fc27d88e93 fix: replace remaining fill="Solid" in VoiceMessageRecorder preview send button
CI / Build & Quality Checks (push) Successful in 10m23s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 13:28:17 -04:00
jared 79c8c986ee fix: show verification badges regardless of room encryption state
CI / Build & Quality Checks (push) Successful in 10m35s
Spaces and unencrypted rooms have hasEncryptionStateEvent() = false,
causing all badges to be hidden. Cross-signing verification is a user
identity property, not room-specific — show badges whenever
crossSigningActive, keep the E2EE banner gated on isEncrypted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 13:21:12 -04:00
jared 2f7f933350 feat: extend verification badge to user profile and settings members list
CI / Build & Quality Checks (push) Successful in 10m22s
Extract MemberVerificationBadge into a shared component and render it in:
- UserRoomProfile: shield badge beside the display name on the profile card
- common-settings Members: badge next to each member in the room/space
  settings members page (accessible from the lobby)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 12:53:33 -04:00
jared 1ae286ee74 fix: correct IconButton fill and Box gap types in VoiceMessageRecorder
- fill="Solid" → fill="Soft" (valid values: Soft | None)
- gap="50" → gap="100" (valid sizes: 100–700)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 12:36:10 -04:00
jared 74284902c2 feat: voice message recording + per-member encryption verification
CI / Build & Quality Checks (push) Successful in 10m20s
- Add VoiceMessageRecorder component: mic button in composer toolbar,
  live waveform + timer, preview before send, MSC3245-compliant content
  (org.matrix.msc3245.voice, org.matrix.msc1767.audio with waveform),
  E2EE support via encryptFile before upload
- Add useUserVerifiedStatus hook: uses crypto.getUserVerificationStatus,
  reacts live to CryptoEvent.UserTrustStatusChanged
- MembersDrawer: show green/yellow shield badge per member in encrypted
  rooms (cross-signing verified/unverified), E2EE status banner in header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 12:19:06 -04:00
jared 8ca9853dea Merge tag 'v4.12.2' into lotus
CI / Build & Quality Checks (push) Successful in 10m23s
2026-05-23 11:26:45 -04:00
jared 6d095dfbf3 Fix device verification UX: show request card, enable cross-user SAS
- RenderMessageContent: add case for m.key.verification.request msgtype
  so it renders an informational card instead of "Unsupported message"
- MsgTypeRenderers/FallbackContent: add VerificationRequestContent and
  MessageVerificationRequestContent components (lock icon + instructional text)
- DeviceVerification: remove isSelfVerification guard from
  ReceiveSelfDeviceVerification so cross-user verification requests also
  trigger the SAS emoji dialog (was silently dropped before)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 11:15:49 -04:00
Krishan 80fd8863c9 chore: Release v4.12.2 (#2956)
Release v4.12.2
2026-05-23 22:10:21 +10:00
Krishan cf2810b35e chore: remove semantic-release and keep script (#2946)
* chore: remove semantic-release

* chore: keep workflow to be tag publish based

* chore: fix typo
2026-05-23 22:02:49 +10:00
Ajay Bura 4916efa925 fix: call drop (#2954)
* update matrix-js-sdk and improve call driver

* remove unused room param from call members hook

* downgrade matrix-js-sdk to latest stable release
2026-05-23 21:50:41 +10:00
jared 3d87c55689 fix: prettier formatting in CallEmbedProvider and useCallEmbed
CI / Build & Quality Checks (push) Successful in 10m51s
Auto-fixed by prettier --write. Patch scripts used in the previous session
wrote code without running the formatter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 00:51:39 -04:00
jared 13088744f3 docs: add development workflow section to README
CI / Build & Quality Checks (push) Failing after 6m1s
Document the CI/CD pipeline: edit locally in /root/code/cinny, commit and
push to origin/lotus, Gitea Actions builds (~11 min), webhook triggers
lotus_deploy.sh which gates on CI pass before deploying to /var/www/html/.
Note that LXC credential is read-only; pushes require manual auth from dev box.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 00:37:17 -04:00
Lotus Bot 9ce8ad58b1 feat: dark mode fix, call wallpaper, setTheme error handling, Sentry filter
CI / Build & Quality Checks (push) Failing after 6m11s
- CallEmbed: inject :root { color-scheme } into iframe so EC respects Cinny
  theme regardless of OS preference (fixes white background in dark mode)
- CallEmbed: store themeKind, update color-scheme CSS on live setTheme() calls
- CallEmbed: catch transport.send() rejection in setTheme() to prevent
  unhandled promise rejection when widget not ready yet (fixes REACT-8)
- CallEmbed: html + body both set to background:none so wallpaper shows through
- CallEmbedProvider: apply chatBackground wallpaper style to call embed
  container in full-view mode (not PiP) -- wallpapers carry over to calls
- useCallEmbed: pass themeKind through to CallEmbed constructor
- index.tsx: ignoreErrors: [Request timed out] to suppress matrixRTC
  heartbeat timeouts (REACT-9) from Sentry noise
- README: document 0.19.4, positioning fix, dark mode fix, wallpaper,
  millify Rolldown interop fix, Sentry noise filter

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 00:28:37 -04:00
Lotus Bot 95ac291a61 fix: people list crash + call embed positioning + debug logging
- millify.ts: use named import { millify as millifyPlugin } instead of
  default import to fix Rolldown CJS interop bug where zc.default gets
  set to the whole module object instead of the function (mode=1 forces
  default=n instead of default=n.default, breaking MembersDrawer)
- useCallEmbed.ts: use getBoundingClientRect() for accurate fixed
  positioning; add useEffect to trigger syncCallEmbedPlacement on mount
  so embed is positioned before the first resize event
- CallEmbedProvider.tsx: fix [pipMode, callVisible] effect to NOT clear
  top/left/width/height when callVisible changes (previously cleared
  position set by syncCallEmbedPlacement every time joined changed);
  only clear pip-specific styles when actually exiting pip; add debug
  console logging for positioning state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 22:48:39 -04:00
Lotus Bot 24c525e6bb fix: listenAction must reply to prevent widget transport timeout
CI / Build & Quality Checks (push) Successful in 10m31s
Previously the listenAction wrapper only called preventDefault() to stop
the switch default from firing an error, but it never sent a reply.
The widget transport would then wait for a response until it timed out.
Now the wrapper also calls transport.reply(ev.detail, {}) to return an
immediate success, fixing io.element.join, io.element.device_mute, and
set_always_on_screen.
2026-05-22 22:09:38 -04:00
Lotus Bot 2de0b661c8 fix: override cancelScheduledDelayedEvent/restart/send in CallWidgetDriver
CI / Build & Quality Checks (push) Successful in 10m34s
The base WidgetDriver throws Failed to override function for these
methods. ClientWidgetApi routes update_delayed_event widget actions to
cancelScheduledDelayedEvent, restartScheduledDelayedEvent, or
sendScheduledDelayedEvent. Without these overrides every delayed-event
refresh from element-call fails, causing MembershipManager to drop the
call after retries.

Also make listenAction auto-call preventDefault so io.element.join and
other custom widget actions return success. Add set_always_on_screen
handler so element-call PiP requests are acknowledged.
2026-05-22 21:51:17 -04:00
Lotus Bot 4a0218682e fix: correctly deploy element-call widget via vite-plugin-static-copy
CI / Build & Quality Checks (push) Successful in 10m54s
The glob pattern dist/* preserved the full node_modules/...  path
when copying to public/element-call/, resulting in only a nested
node_modules directory being deployed (causing 404 on index.html).

Switching to a directory src with rename lets the plugin copy the
dist folder wholesale as public/element-call/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 20:22:39 -04:00
Lotus Bot b129232f2b fix: ESLint errors, stale disable comments, bundle splitting
CI / Build & Quality Checks (push) Successful in 10m28s
- RoomTimeline.tsx: add eslint-disable comment for intentional eventsLength
  dep on timelineSegments useMemo (needed to detect in-place timeline mutations)
- Remove ~47 stale eslint-disable-next-line comments across 28 files for rules
  that are now off in the flat config (no-param-reassign, jsx-a11y/media-has-caption,
  react/no-array-index-key, etc); run prettier to reformat
- vite.config.js: move manualChunks from rollupOptions.output to
  rolldownOptions.output so Rolldown (Vite 8) actually applies it; main bundle
  drops from 3.5 MB to 814 kB gzip-248 kB, matrix-sdk gets its own 1.16 MB
  cacheable chunk

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 19:52:23 -04:00
Lotus Bot 61167dae39 fix: code splitting, route errors, Sentry CI source maps
CI / Build & Quality Checks (push) Successful in 10m20s
- Lazy-import CreateRoomForm/CreateSpaceForm in CreateRoom.tsx and Create.tsx
  so create-room and create-space get their own chunks; eliminates
  INEFFECTIVE_DYNAMIC_IMPORT warnings
- Add RouteError component wired to root route errorElement so crashes show
  a reload button instead of React Router dev screen
- ci.yml: use secrets.SENTRY_AUTH_TOKEN so source maps upload on CI builds

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 19:30:55 -04:00
Lotus Bot b00e11d506 style: prettier format skeleton components
CI / Build & Quality Checks (push) Successful in 10m12s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 18:59:23 -04:00
Lotus Bot dd8190f506 fix: sent messages not appearing + add Lobby/Auth skeleton loaders
CI / Build & Quality Checks (push) Failing after 5m45s
- Fix timelineSegments useMemo stale cache: the Perf-5 optimization used
  timeline.linkedTimelines as its only dep, but that reference never changes
  when events are added in-place; adding eventsLength as a dep makes it
  recompute on every new live event so the binary search always finds the
  new item
- Add LobbySkeleton: shimmer placeholder for space lobby (header + hero +
  room list rows) shown while the Lobby chunk lazy-loads
- Add AuthSkeleton: shimmer placeholder for auth pages (logo + server
  picker + form fields) shown while AuthLayout chunk lazy-loads
- Wire both into Router.tsx fallback props

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 18:52:12 -04:00
Lotus Bot 685d91d41b fix: restore mx declarations to all components in Message.tsx
CI / Build & Quality Checks (push) Successful in 10m9s
Automated cleanup removed const mx = useMatrixClient() from 3 more components
that use it (MessagePinItem, Message, Event) in addition to the 2 fixed in
the previous hotfix. Root cause: the cleanup script used substring matching
on indentation which removed declarations at any indent level, not just the
one targeted unused variable.

All 5 components that call mx.* now have their declarations restored.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 18:03:55 -04:00
Lotus Bot e1c724c2fd fix: restore mx declarations removed by cleanup script
CI / Build & Quality Checks (push) Successful in 10m12s
The automated unused-var cleanup incorrectly removed const mx = useMatrixClient()
from MessageDeleteItem and ReportMessage components in Message.tsx. Both components
use mx inside their useCallback closures (mx.redactEvent, mx.reportEvent). This
caused a ReferenceError crash on the messages view in production.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 17:31:40 -04:00