Return the widget from initializeWidget instead of assigning a global

Element Call reached the widget API through a mutable module-level
binding, which every consumer imported directly. Nothing outside the app
shell needs it any more, so hand it back from initializeWidget and thread
it through: the initializer returns it, main passes it to App, and App
uses it to build the host bridge and to await the client the host is
lending us.

ClientContext's loadClient is now only about restoring or creating a
session of Element Call's own, since a widget's client arrives as a prop
like any other host's would.

Also fixes an early return added in the previous commit, which skipped
starting the analytics settings listener when a client was supplied. That
was harmless until now, but would have stopped analytics following the
user's choices in widget mode.

sdk/main.ts asked the host to close by hand; it now uses the bridge, which
also stops the transport as the app does.
This commit is contained in:
Valere
2026-09-02 16:56:09 +02:00
parent f6f47ede62
commit 182be8676d
7 changed files with 84 additions and 72 deletions
+10 -16
View File
@@ -54,11 +54,7 @@ import { MediaDevices } from "../src/state/MediaDevices";
import { E2eeType } from "../src/e2ee/e2eeType";
import { currentAndPrev, TEXT_LK_TOPIC, tryMakeSticky } from "./helper";
import { logger as rootLogger } from "matrix-js-sdk/lib/logger";
import {
ElementWidgetActions,
widget as _widget,
initializeWidget,
} from "../src/widget";
import { initializeWidget } from "../src/widget";
import { type Connection } from "../src/state/CallViewModel/remoteMembers/Connection";
import { createWidgetHostBridge } from "../src/HostBridge";
@@ -110,8 +106,7 @@ export async function createMatrixRTCSdk(
const scope = new ObservableScope();
// widget client
initializeWidget(application, true);
const widget = _widget;
const widget = initializeWidget(application, true);
if (!widget) throw Error("No widget. This webapp can only start as a widget");
const client = await widget.client;
const hostBridge = createWidgetHostBridge(widget);
@@ -294,18 +289,17 @@ export async function createMatrixRTCSdk(
});
await leaveResolver.promise;
logger.info("send Unstick");
await widget.api
await hostBridge
.setAlwaysOnScreen(false)
.catch((e) =>
logger.error(
"Failed to set call widget `alwaysOnScreen` to false",
e,
),
.catch((e: unknown) =>
logger.error("Failed to set `alwaysOnScreen` to false", e),
);
logger.info("send Close");
await widget.api.transport
.send(ElementWidgetActions.Close, {})
.catch((e) => logger.error("Failed to send close action", e));
await hostBridge
.close?.()
.catch((e: unknown) =>
logger.error("Failed to ask the host to close", e),
);
};
// schedule close first and then leave (scope.end)