mirror of
https://github.com/vector-im/element-call.git
synced 2026-10-13 23:35:51 +00:00
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:
+15
-17
@@ -22,7 +22,6 @@ import { type ISyncStateData, type SyncState } from "matrix-js-sdk/lib/sync";
|
||||
import { ClientEvent, type MatrixClient } from "matrix-js-sdk";
|
||||
|
||||
import { ErrorPage } from "./FullScreenView";
|
||||
import { widget } from "./widget";
|
||||
import { useHostBridge } from "./HostBridge";
|
||||
import {
|
||||
PosthogAnalytics,
|
||||
@@ -163,7 +162,12 @@ export const ClientProvider: FC<Props> = ({ children, client }) => {
|
||||
|
||||
const initializing = useRef(false);
|
||||
useEffect(() => {
|
||||
if (client !== undefined) return;
|
||||
if (client !== undefined) {
|
||||
// Nothing to load, but analytics still need to follow the user's choices.
|
||||
if (PosthogAnalytics.instance.isEnabled())
|
||||
PosthogAnalytics.instance.startListeningToSettingsChanges();
|
||||
return;
|
||||
}
|
||||
// In case the component is mounted, unmounted, and remounted quickly (as
|
||||
// React does in strict mode), we need to make sure not to doubly initialize
|
||||
// the client.
|
||||
@@ -246,9 +250,9 @@ export const ClientProvider: FC<Props> = ({ children, client }) => {
|
||||
// To protect against multiple sessions writing to the same storage
|
||||
// simultaneously, we send a broadcast message that shuts down all other
|
||||
// running instances of the app. Element Call only has storage of its own to
|
||||
// protect when it created the session itself; given a client, or running as a
|
||||
// widget, it is mostly stateless.
|
||||
const ownsSession = client === undefined && widget === null;
|
||||
// protect when it created the session itself; given a client — by a host, or
|
||||
// over the widget API — it is mostly stateless.
|
||||
const ownsSession = client === undefined;
|
||||
useEffect(() => {
|
||||
if (ownsSession) loadChannel?.postMessage({});
|
||||
}, [ownsSession]);
|
||||
@@ -349,19 +353,13 @@ export type InitResult = {
|
||||
passwordlessUser: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Restores or creates a session of Element Call's own. Only reached when no
|
||||
* client was supplied for it to use.
|
||||
*/
|
||||
async function loadClient(): Promise<InitResult | null> {
|
||||
if (widget) {
|
||||
// We're inside a widget, so let's engage *matryoshka mode*
|
||||
logger.log("Using a matryoshka client");
|
||||
const client = await widget.client;
|
||||
return {
|
||||
client,
|
||||
passwordlessUser: false,
|
||||
};
|
||||
} else {
|
||||
const { initSPA } = await import("./utils/spa");
|
||||
return initSPA(loadSession, clearSession);
|
||||
}
|
||||
const { initSPA } = await import("./utils/spa");
|
||||
return initSPA(loadSession, clearSession);
|
||||
}
|
||||
|
||||
export interface Session {
|
||||
|
||||
Reference in New Issue
Block a user