mirror of
https://github.com/vector-im/element-call.git
synced 2024-11-24 00:38:31 +08:00
Review
This commit is contained in:
parent
ab457be4bb
commit
f3404fbbf3
@ -77,9 +77,7 @@ export const App: FC<AppProps> = ({ history }) => {
|
||||
setLoaded(true);
|
||||
await widget?.api.sendContentLoaded();
|
||||
})
|
||||
.catch((e) => {
|
||||
logger.error(e);
|
||||
});
|
||||
.catch(logger.error);
|
||||
});
|
||||
|
||||
const errorPage = <CrashView />;
|
||||
|
@ -399,7 +399,7 @@ export class PosthogAnalytics {
|
||||
|
||||
if (this.identificationPromise) {
|
||||
// only make calls to posthog after the identification is done
|
||||
this.identificationPromise.then(doCapture).catch((e) => {
|
||||
this.identificationPromise.then(doCapture, (e) => {
|
||||
logger.error("Failed to identify user for tracking", e);
|
||||
});
|
||||
} else {
|
||||
|
@ -43,20 +43,19 @@ export class PosthogSpanProcessor implements SpanProcessor {
|
||||
|
||||
public onStart(span: Span): void {
|
||||
// Hack: Yield to allow attributes to be set before processing
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
switch (span.name) {
|
||||
case "matrix.groupCallMembership":
|
||||
this.onGroupCallMembershipStart(span);
|
||||
return;
|
||||
case "matrix.groupCallMembership.summaryReport":
|
||||
this.onSummaryReportStart(span);
|
||||
return;
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
// noop
|
||||
});
|
||||
try {
|
||||
switch (span.name) {
|
||||
case "matrix.groupCallMembership":
|
||||
this.onGroupCallMembershipStart(span);
|
||||
return;
|
||||
case "matrix.groupCallMembership.summaryReport":
|
||||
this.onSummaryReportStart(span);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// log to avoid tripping @typescript-eslint/no-unused-vars
|
||||
logger.debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
public onEnd(span: ReadableSpan): void {
|
||||
|
@ -58,9 +58,8 @@ export function useInteractiveLogin(
|
||||
password,
|
||||
}),
|
||||
stateUpdated: (): void => {},
|
||||
requestEmailToken: async (): Promise<{ sid: string }> => {
|
||||
return Promise.resolve({ sid: "" });
|
||||
},
|
||||
requestEmailToken: async (): Promise<{ sid: string }> =>
|
||||
Promise.resolve({ sid: "" }),
|
||||
});
|
||||
|
||||
// XXX: This claims to return an IAuthData which contains none of these
|
||||
|
@ -106,9 +106,8 @@ export const useInteractiveRegistration = (
|
||||
});
|
||||
}
|
||||
},
|
||||
requestEmailToken: async (): Promise<{ sid: string }> => {
|
||||
return Promise.resolve({ sid: "dummy" });
|
||||
},
|
||||
requestEmailToken: async (): Promise<{ sid: string }> =>
|
||||
Promise.resolve({ sid: "dummy" }),
|
||||
});
|
||||
|
||||
// XXX: This claims to return an IAuthData which contains none of these
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
} from "./ConfigOptions";
|
||||
|
||||
export class Config {
|
||||
private static internalInstance: Config;
|
||||
private static internalInstance: Config | undefined;
|
||||
|
||||
public static get(): ConfigOptions {
|
||||
if (!this.internalInstance?.config)
|
||||
@ -31,22 +31,22 @@ export class Config {
|
||||
}
|
||||
|
||||
public static async init(): Promise<void> {
|
||||
if (Config.internalInstance?.initPromise) {
|
||||
return Config.internalInstance.initPromise;
|
||||
}
|
||||
Config.internalInstance = new Config();
|
||||
if (!Config.internalInstance?.initPromise) {
|
||||
const internalInstance = new Config();
|
||||
Config.internalInstance = internalInstance;
|
||||
|
||||
Config.internalInstance.initPromise = downloadConfig("../config.json").then(
|
||||
(config) => {
|
||||
Config.internalInstance.config = { ...DEFAULT_CONFIG, ...config };
|
||||
},
|
||||
);
|
||||
Config.internalInstance.initPromise = downloadConfig(
|
||||
"../config.json",
|
||||
).then((config) => {
|
||||
internalInstance.config = { ...DEFAULT_CONFIG, ...config };
|
||||
});
|
||||
}
|
||||
return Config.internalInstance.initPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a alternative initializer that does not load anything
|
||||
* from a hosted config file but instead just initializes the conifg using the
|
||||
* from a hosted config file but instead just initializes the config using the
|
||||
* default config.
|
||||
*
|
||||
* It is supposed to only be used in tests. (It is executed in `vite.setup.js`)
|
||||
|
@ -60,19 +60,20 @@ export class MatrixKeyProvider extends BaseKeyProvider {
|
||||
encryptionKeyIndex: number,
|
||||
participantId: string,
|
||||
): void => {
|
||||
createKeyMaterialFromBuffer(encryptionKey)
|
||||
.then((keyMaterial) => {
|
||||
createKeyMaterialFromBuffer(encryptionKey).then(
|
||||
(keyMaterial) => {
|
||||
this.onSetEncryptionKey(keyMaterial, participantId, encryptionKeyIndex);
|
||||
|
||||
logger.debug(
|
||||
`Sent new key to livekit room=${this.rtcSession?.room.roomId} participantId=${participantId} encryptionKeyIndex=${encryptionKeyIndex}`,
|
||||
);
|
||||
})
|
||||
.catch((e) => {
|
||||
},
|
||||
(e) => {
|
||||
logger.error(
|
||||
`Failed to create key material from buffer for livekit room=${this.rtcSession?.room.roomId} participantId=${participantId} encryptionKeyIndex=${encryptionKeyIndex}`,
|
||||
e,
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
};
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ import {
|
||||
} from "react";
|
||||
import useMeasure from "react-use-measure";
|
||||
import classNames from "classnames";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import styles from "./Grid.module.css";
|
||||
import { useMergedRefs } from "../useMergedRefs";
|
||||
@ -362,7 +363,7 @@ export function Grid<
|
||||
// Because we're using react-spring in imperative mode, we're responsible for
|
||||
// firing animations manually whenever the tiles array updates
|
||||
useEffect(() => {
|
||||
void springRef.start();
|
||||
springRef.start().forEach((p) => void p.catch(logger.error));
|
||||
}, [placedTiles, springRef]);
|
||||
|
||||
const animateDraggedTile = (
|
||||
@ -372,7 +373,7 @@ export function Grid<
|
||||
const { tileId, tileX, tileY } = dragState.current!;
|
||||
const tile = placedTiles.find((t) => t.id === tileId)!;
|
||||
|
||||
void springRef.current
|
||||
springRef.current
|
||||
.find((c) => (c.item as Tile<TileModel>).id === tileId)
|
||||
?.start(
|
||||
endOfGesture
|
||||
@ -399,7 +400,8 @@ export function Grid<
|
||||
((key): boolean =>
|
||||
key === "zIndex" || key === "x" || key === "y"),
|
||||
},
|
||||
);
|
||||
)
|
||||
.catch(logger.error);
|
||||
|
||||
if (endOfGesture)
|
||||
callback({
|
||||
|
@ -133,14 +133,15 @@ export class Initializer {
|
||||
// config
|
||||
if (this.loadStates.config === LoadState.None) {
|
||||
this.loadStates.config = LoadState.Loading;
|
||||
Config.init()
|
||||
.then(() => {
|
||||
Config.init().then(
|
||||
() => {
|
||||
this.loadStates.config = LoadState.Loaded;
|
||||
this.initStep(resolve);
|
||||
})
|
||||
.catch((e) => {
|
||||
},
|
||||
(e) => {
|
||||
logger.error("Failed to load config", e);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
//sentry (only initialize after the config is ready)
|
||||
|
@ -49,14 +49,18 @@ export function useOpenIDSFU(
|
||||
const activeFocus = useActiveLivekitFocus(rtcSession);
|
||||
|
||||
useEffect(() => {
|
||||
(async (): Promise<void> => {
|
||||
const sfuConfig = activeFocus
|
||||
? await getSFUConfigWithOpenID(client, activeFocus)
|
||||
: undefined;
|
||||
setSFUConfig(sfuConfig);
|
||||
})().catch((e) => {
|
||||
logger.error("Failed to get SFU config", e);
|
||||
});
|
||||
if (activeFocus) {
|
||||
getSFUConfigWithOpenID(client, activeFocus).then(
|
||||
(sfuConfig) => {
|
||||
setSFUConfig(sfuConfig);
|
||||
},
|
||||
(e) => {
|
||||
logger.error("Failed to get SFU config", e);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
setSFUConfig(undefined);
|
||||
}
|
||||
}, [client, activeFocus]);
|
||||
|
||||
return sfuConfig;
|
||||
|
@ -180,15 +180,13 @@ export const GroupCallView: FC<Props> = ({
|
||||
if (widget && preload && skipLobby) {
|
||||
// In preload mode without lobby we wait for a join action before entering
|
||||
const onJoin = (ev: CustomEvent<IWidgetApiRequest>): void => {
|
||||
defaultDeviceSetup(ev.detail.data as unknown as JoinCallData)
|
||||
.catch((e) => {
|
||||
logger.error("Error setting up default devices", e);
|
||||
})
|
||||
.then(async () => enterRTCSession(rtcSession, perParticipantE2EE))
|
||||
.then(() => widget!.api.transport.reply(ev.detail, {}))
|
||||
.catch((e) => {
|
||||
logger.error("Error entering RTC session", e);
|
||||
});
|
||||
(async (): Promise<void> => {
|
||||
await defaultDeviceSetup(ev.detail.data as unknown as JoinCallData);
|
||||
await enterRTCSession(rtcSession, perParticipantE2EE);
|
||||
widget!.api.transport.reply(ev.detail, {});
|
||||
})().catch((e) => {
|
||||
logger.error("Error joining RTC session", e);
|
||||
});
|
||||
};
|
||||
widget.lazyActions.on(ElementWidgetActions.JoinCall, onJoin);
|
||||
return (): void => {
|
||||
@ -196,14 +194,12 @@ export const GroupCallView: FC<Props> = ({
|
||||
};
|
||||
} else if (widget && !preload && skipLobby) {
|
||||
// No lobby and no preload: we enter the rtc session right away
|
||||
defaultDeviceSetup({ audioInput: null, videoInput: null })
|
||||
.catch((e) => {
|
||||
logger.error("Error setting up default devices", e);
|
||||
})
|
||||
.then(async () => enterRTCSession(rtcSession, perParticipantE2EE))
|
||||
.catch((e) => {
|
||||
logger.error("Error entering RTC session", e);
|
||||
});
|
||||
(async (): Promise<void> => {
|
||||
await defaultDeviceSetup({ audioInput: null, videoInput: null });
|
||||
await enterRTCSession(rtcSession, perParticipantE2EE);
|
||||
})().catch((e) => {
|
||||
logger.error("Error joining RTC session", e);
|
||||
});
|
||||
}
|
||||
}, [rtcSession, preload, skipLobby, perParticipantE2EE]);
|
||||
|
||||
|
@ -478,12 +478,14 @@ export const InCallView: FC<InCallViewProps> = ({
|
||||
);
|
||||
|
||||
const toggleScreensharing = useCallback(() => {
|
||||
void localParticipant.setScreenShareEnabled(!isScreenShareEnabled, {
|
||||
audio: true,
|
||||
selfBrowserSurface: "include",
|
||||
surfaceSwitching: "include",
|
||||
systemAudio: "include",
|
||||
});
|
||||
localParticipant
|
||||
.setScreenShareEnabled(!isScreenShareEnabled, {
|
||||
audio: true,
|
||||
selfBrowserSurface: "include",
|
||||
surfaceSwitching: "include",
|
||||
systemAudio: "include",
|
||||
})
|
||||
.catch(logger.error);
|
||||
}, [localParticipant, isScreenShareEnabled]);
|
||||
|
||||
let footer: JSX.Element | null;
|
||||
|
@ -69,11 +69,11 @@ export const RoomPage: FC = () => {
|
||||
if (!loading && !authenticated && displayName && !widget) {
|
||||
setIsRegistering(true);
|
||||
registerPasswordlessUser(displayName)
|
||||
.finally(() => {
|
||||
setIsRegistering(false);
|
||||
})
|
||||
.catch((e) => {
|
||||
logger.error("Failed to register passwordless user", e);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsRegistering(false);
|
||||
});
|
||||
}
|
||||
}, [
|
||||
|
@ -159,10 +159,9 @@ export const useLoadGroupCall = (
|
||||
viaServers: string[],
|
||||
onKnockSent: () => void,
|
||||
): Promise<Room> => {
|
||||
let joinedRoom: Room | null = null;
|
||||
await client.knockRoom(roomId, { viaServers });
|
||||
onKnockSent();
|
||||
const invitePromise = new Promise<void>((resolve, reject) => {
|
||||
return await new Promise<Room>((resolve, reject) => {
|
||||
client.on(
|
||||
RoomEvent.MyMembership,
|
||||
(room, membership, prevMembership): void => {
|
||||
@ -172,14 +171,10 @@ export const useLoadGroupCall = (
|
||||
membership === KnownMembership.Invite &&
|
||||
prevMembership === KnownMembership.Knock
|
||||
) {
|
||||
client
|
||||
.joinRoom(room.roomId, { viaServers })
|
||||
.then((room) => {
|
||||
joinedRoom = room;
|
||||
logger.log("Auto-joined %s", room.roomId);
|
||||
resolve();
|
||||
})
|
||||
.catch((e) => reject(e));
|
||||
client.joinRoom(room.roomId, { viaServers }).then((room) => {
|
||||
logger.log("Auto-joined %s", room.roomId);
|
||||
resolve(room);
|
||||
}, reject);
|
||||
}
|
||||
if (membership === KnownMembership.Ban) reject(bannedError());
|
||||
if (membership === KnownMembership.Leave)
|
||||
@ -187,11 +182,6 @@ export const useLoadGroupCall = (
|
||||
},
|
||||
);
|
||||
});
|
||||
await invitePromise;
|
||||
if (!joinedRoom) {
|
||||
throw new Error("Failed to join room after knocking.");
|
||||
}
|
||||
return joinedRoom;
|
||||
};
|
||||
|
||||
const fetchOrCreateRoom = async (): Promise<Room> => {
|
||||
|
@ -127,9 +127,14 @@ const widgetPostHangupProcedure = async (
|
||||
// we need to wait until the callEnded event is tracked on posthog.
|
||||
// Otherwise the iFrame gets killed before the callEnded event got tracked.
|
||||
await new Promise((resolve) => window.setTimeout(resolve, 10)); // 10ms
|
||||
await widget.api.setAlwaysOnScreen(false);
|
||||
PosthogAnalytics.instance.logout();
|
||||
|
||||
try {
|
||||
await widget.api.setAlwaysOnScreen(false);
|
||||
} catch (e) {
|
||||
logger.error("Failed to set call widget `alwaysOnScreen` to false", e);
|
||||
}
|
||||
|
||||
// We send the hangup event after the memberships have been updated
|
||||
// calling leaveRTCSession.
|
||||
// We need to wait because this makes the client hosting this widget killing the IFrame.
|
||||
|
@ -236,13 +236,9 @@ class IndexedDBLogStore {
|
||||
return this.flushAgainPromise;
|
||||
}
|
||||
// queue up a flush to occur immediately after the pending one completes.
|
||||
this.flushAgainPromise = this.flushPromise
|
||||
.then(async () => {
|
||||
return this.flush();
|
||||
})
|
||||
.then(() => {
|
||||
this.flushAgainPromise = undefined;
|
||||
});
|
||||
this.flushAgainPromise = this.flushPromise.then(this.flush).then(() => {
|
||||
this.flushAgainPromise = undefined;
|
||||
});
|
||||
return this.flushAgainPromise;
|
||||
}
|
||||
// there is no flush promise or there was but it has finished, so do
|
||||
|
@ -30,9 +30,8 @@ export function useWakeLock(): void {
|
||||
// so we need to reacquire it on visibility changes
|
||||
const onVisibilityChange = (): void => {
|
||||
if (document.visibilityState === "visible") {
|
||||
navigator.wakeLock
|
||||
.request("screen")
|
||||
.then((newLock) => {
|
||||
navigator.wakeLock.request("screen").then(
|
||||
(newLock) => {
|
||||
lock = newLock;
|
||||
// Handle the edge case where this component unmounts before the
|
||||
// promise resolves
|
||||
@ -40,10 +39,11 @@ export function useWakeLock(): void {
|
||||
lock
|
||||
.release()
|
||||
.catch((e) => logger.warn("Can't release wake lock", e));
|
||||
})
|
||||
.catch((e) => {
|
||||
},
|
||||
(e) => {
|
||||
logger.warn("Can't acquire wake lock", e);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -269,40 +269,40 @@ export async function createRoom(
|
||||
});
|
||||
|
||||
// Wait for the room to arrive
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const onRoom = (room: Room): void => {
|
||||
createPromise
|
||||
.then((result) => {
|
||||
if (room.roomId === result.room_id) {
|
||||
resolve();
|
||||
cleanUp();
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
logger.error("Failed to wait for the room to arrive", e);
|
||||
});
|
||||
};
|
||||
const roomId = await new Promise<string>((resolve, reject) => {
|
||||
createPromise.catch((e) => {
|
||||
reject(e);
|
||||
cleanUp();
|
||||
});
|
||||
|
||||
const onRoom = (room: Room): void => {
|
||||
createPromise.then(
|
||||
(result) => {
|
||||
if (room.roomId === result.room_id) {
|
||||
resolve(room.roomId);
|
||||
cleanUp();
|
||||
}
|
||||
},
|
||||
(e) => {
|
||||
logger.error("Failed to wait for the room to arrive", e);
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const cleanUp = (): void => {
|
||||
client.off(ClientEvent.Room, onRoom);
|
||||
};
|
||||
client.on(ClientEvent.Room, onRoom);
|
||||
});
|
||||
|
||||
const result = await createPromise;
|
||||
|
||||
let password;
|
||||
let password: string | undefined;
|
||||
if (e2ee == E2eeType.SHARED_KEY) {
|
||||
password = secureRandomBase64Url(16);
|
||||
saveKeyForRoom(result.room_id, password);
|
||||
saveKeyForRoom(roomId, password);
|
||||
}
|
||||
|
||||
return {
|
||||
roomId: result.room_id,
|
||||
roomId,
|
||||
alias: e2ee ? undefined : fullAliasFromRoomName(name, client),
|
||||
password,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user