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>
This commit is contained in:
Lotus Bot
2026-05-23 00:28:37 -04:00
parent 95ac291a61
commit 9ce8ad58b1
5 changed files with 52 additions and 12 deletions
+27 -9
View File
@@ -52,6 +52,8 @@ export class CallEmbed {
private styleRetryObserver?: MutationObserver;
private themeKind: ElementCallThemeKind = 'dark';
// Arrow-function class fields so dispose() passes the exact same reference to mx.off()
private readonly boundOnEvent = (ev: MatrixEvent) => this.onEvent(ev);
@@ -175,6 +177,7 @@ export class CallEmbed {
widget: Widget,
container: HTMLElement,
initialControlState?: CallControlState,
themeKind: ElementCallThemeKind = 'dark',
) {
const iframe = CallEmbed.getIframe(
widget.getCompleteUrl({ currentUserId: mx.getSafeUserId() }),
@@ -189,6 +192,7 @@ export class CallEmbed {
this.room = room;
this.iframe = iframe;
this.container = container;
this.themeKind = themeKind;
const controlState = initialControlState ?? new CallControlState(true, false, true);
this.control = new CallControl(controlState, call, iframe);
@@ -218,9 +222,17 @@ export class CallEmbed {
}
public setTheme(theme: ElementCallThemeKind) {
return this.call.transport.send(WidgetApiToWidgetAction.ThemeChange, {
name: theme,
});
this.themeKind = theme;
const doc = this.document;
if (doc && this.joined) {
const styleEl = doc.getElementById('lotus-ec-styles');
if (styleEl) styleEl.textContent = this.buildStyleContent();
}
return this.call.transport
.send(WidgetApiToWidgetAction.ThemeChange, { name: theme })
.catch(() => {
// Widget transport not ready yet; theme URL param is the fallback
});
}
public hangup() {
@@ -304,22 +316,28 @@ export class CallEmbed {
this.control.forceState(this.initialState);
}
private buildStyleContent(): string {
return [
'html, body { background: none !important; }',
`:root { color-scheme: ${this.themeKind}; }`,
'[style*="height: 0"][style*="z-index: 1"][style*="align-self: center"] { display: none !important; }',
].join('\n');
}
private applyStyles(): void {
const doc = this.document;
if (!doc) return;
doc.body.style.setProperty('background', 'none', 'important');
// Inject CSS for things that can't be reliably caught by DOM timing
if (!doc.getElementById('lotus-ec-styles')) {
const style = doc.createElement('style');
style.id = 'lotus-ec-styles';
style.textContent = [
'body { background: none !important; }',
// Hide "using to Device key transport" status line
'[style*="height: 0"][style*="z-index: 1"][style*="align-self: center"] { display: none !important; }',
].join('\n');
style.textContent = this.buildStyleContent();
(doc.head ?? doc.body).appendChild(style);
} else {
const styleEl = doc.getElementById('lotus-ec-styles');
if (styleEl) styleEl.textContent = this.buildStyleContent();
}
// Hide EC built-in controls (we provide our own)