- 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>
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>
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>
- 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>
- 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>
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.
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.
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>
- 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>
- 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>
- 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>
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>
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>
Synapse does not yet ship MSC3786/MSC3914 as server-default push rules.
matrix-js-sdk patches them client-side every login and warns. Filter these
at console.warn level -- functionality is unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ServerConfigsLoader: skip validateAuthMetadata when getAuthMetadata()
rejects (404 on /auth_issuer means server uses traditional SSO, not
native Matrix OIDC/MAS - this is expected and should not log errors)
- Router: use HydrateFallback={() => null} instead of hydrateFallbackElement={null}
so react-router v7 counts it as truthy and suppresses the spurious warning
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove @esbuild-plugins/node-globals-polyfill (redundant since Vite 8
rolldownOptions.define handles globalThis). Add rolldownOptions.checks
to suppress PREFER_BUILTIN_FEATURE until Vite exposes output in rolldownOptions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GHSA-qjx8-664m-686j: prototype hijack in js-cookie <= 3.0.5 used
transitively via react-use in @giphy/react-components.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- react 18.2.0 to 19.2.6
- react-dom 18.2.0 to 19.2.6
- @types/react 18.2.39 to 19.2.15
- @types/react-dom 18.2.17 to 19.2.3
React 19 breaking changes fixed:
- useRef<T>(null) now returns RefObject<T | null>; cast to
RefObject<T> at 16 component call sites (safe, runtime unchanged)
- useRef<T>() without arg no longer valid; add | undefined>(undefined)
in useDebounce, useFileDrop, useThrottle, useVirtualPaginator hooks,
RoomInput, RoomTimeline, and ClientNonUIFeatures
- useReducer<typeof reducer> 1-arg form removed; drop explicit type arg
in useForceUpdate (inferred from reducer function)
- global JSX namespace removed; import type { JSX } from react in
react-custom-html-parser.tsx
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- eslint 8.57.1 to 9.39.4
- @typescript-eslint/eslint-plugin 7.18.0 to 8.59.4
- @typescript-eslint/parser 7.18.0 to 8.59.4
- globals 11.12.0 to 17.6.0
- @eslint/eslintrc and @eslint/js added for FlatCompat
- Replace .eslintrc.cjs + .eslintignore with eslint.config.mjs
- Use flat configs for react, react-hooks, typescript-eslint directly
- FlatCompat only for airbnb-base (no flat config support yet)
- Fix no-unused-vars override from airbnb and react/display-name: off
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- vite 6.4.2 to 8.0.14
- @vitejs/plugin-react 5.2.0 to 6.0.2
- Migrate optimizeDeps.esbuildOptions to rolldownOptions (Vite 8 uses rolldown)
- Remove @esbuild-plugins/node-globals-polyfill (no longer needed)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- typescript 5.9.3 to 6.0.3
- moduleResolution Node to bundler (correct for Vite projects)
- target/lib ES2016 to ES2020 (enables flatMap, Promise.allSettled)
- Fix global to globalThis in initMatrix.ts (browser env)
- Fix EventEmitter default to named import in CallControl.ts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@giphy/react-components@10.1.2 imports noUUIDRandom from @giphy/js-util,
which was only added in 5.x. Previously the uuid override forced uuid@14
into js-util@4.4.2 breaking the noUUIDRandom export. Pin js-util@5.2.0
directly and drop the uuid override (moderate severity, not high).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolves all TS2345/TS2347/TS7006 type errors introduced by stricter TypeScript 5.x.
Fix Icons.Settings to Icons.Setting, cast account data returns, fix implicit any.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a new deploy lands while a tab is open, lazy-loaded chunks (like
GifPicker) disappear because their content-hash filename changes. Vite
dispatches a vite:preloadError event in this case. We reload once and
clear the flag on successful load so future deploys can trigger again.
Icons.Settings is undefined in folds v2.6.2; only Icons.Setting exists.
This caused TypeError: i is not a function when rendering m.room.join_rules
or m.room.guest_access state events in the room timeline, crashing DMs with
those events visible in the initial view.
react-router v7's generatePath() now calls encodeURIComponent() on all
path params. pathUtils.ts was also calling encodeURIComponent() before
passing to generatePath, resulting in double-encoding (e.g. '#' became
'%2523' instead of '%23').
This caused spaces/rooms with alias paths to receive double-encoded
room IDs from useParams(), which were then re-encoded by matrix-sdk
when making HTTP requests (400 Bad Request from Synapse).
Remove the manual encodeURIComponent() calls -- generatePath handles it.
- Fix prettier formatting in useCall.ts and initMatrix.ts (unblocks CI)
- Fix viteStaticCopy stripBase so manifest.json and public/locales/ land
at correct output paths (was getting extra 'public/' prefix from v4 path
preservation behavior)
- Silence react-router v7 HydrateFallback warning on root route (SPA has
no SSR hydration, null is intentional)
1.6.0 did not export SearchContextManager/SearchContext/SearchBar,
causing React error #130 (element type undefined) when opening GifPicker.
5.9.4 uses @emotion (not styled-components), supports React 16-18, and
exports all required components. Downgrade @giphy/js-fetch-api to 4.2.2
to match the peer dep range.
When matrix-sdk is briefly upgraded then reverted, the local IndexedDB
schema version is higher than the SDK expects. Detect the VersionError
DOMException and show a clear 'Clear local data and reload' button
instead of a cryptic error message.
@giphy/react-components@10.x calls styled-components internals
(mergeAttributes) that do not exist in styled-components v6 — crashes
on open. Reverted to 1.6.0 until giphy publishes a v6-compatible release.
WelcomePage: remove Sentry test button (verified working), rename
Support -> Lotus Matrix Guide.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All newly flagged high-severity packages (lodash, js-cookie) are either
in dev-only tools (commitizen) or tree-shaken out of the deployed bundle
(react-use/js-cookie is unused). Zero deployed-bundle impact confirmed.
Being 9 major versions behind accumulates migration debt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
lodash >= 4.18.0 patches prototype-pollution (GHSA-f23m-r3pf-42rh) and
code-injection (GHSA-r5fr-rjxr-66jc) used by slate-dom/slate-react in
the deployed bundle.
Attempted @giphy/react-components@10.1.2 upgrade but it pulled in new
high-severity lodash and js-cookie vulns — net regression, reverted.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- dompurify updated to 3.4.5 to fix 7 XSS/prototype-pollution CVEs
- emojibase-data added to manualChunks: splits 856 kB out of the main
bundle, reducing it from 1.8 MB to 932 kB
- husky prepare script updated from deprecated "husky install" to "husky"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace broken vite-plugin-static-copy target for pdf.worker with a
custom closeBundle plugin that copies the file directly to dist root.
Also uninstall vite-plugin-top-level-await which was removed from
vite.config.js in the previous commit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>