Add widget actions for joining and leaving calls and switching layouts
These actions are processed lazily to ensure that even if the app takes a while to start up, they won't be missed.
This commit is contained in:
parent
f0045c9406
commit
b7be3011da
4 changed files with 141 additions and 36 deletions
|
|
@ -19,6 +19,8 @@ import { useHistory } from "react-router-dom";
|
|||
import { GroupCall, GroupCallState } from "matrix-js-sdk/src/webrtc/groupCall";
|
||||
import { MatrixClient } from "matrix-js-sdk/src/client";
|
||||
|
||||
import type { IWidgetApiRequest } from "matrix-widget-api";
|
||||
import { widget, ElementWidgetActions, JoinCallData } from "../widget";
|
||||
import { useGroupCall } from "./useGroupCall";
|
||||
import { ErrorView, FullScreenView } from "../FullScreenView";
|
||||
import { LobbyView } from "./LobbyView";
|
||||
|
|
@ -28,6 +30,8 @@ import { CallEndedView } from "./CallEndedView";
|
|||
import { useRoomAvatar } from "./useRoomAvatar";
|
||||
import { useSentryGroupCallHandler } from "./useSentryGroupCallHandler";
|
||||
import { useLocationNavigation } from "../useLocationNavigation";
|
||||
import { useMediaHandler } from "../settings/useMediaHandler";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
groupCall?: GroupCall;
|
||||
|
|
@ -38,6 +42,7 @@ interface Props {
|
|||
client: MatrixClient;
|
||||
isPasswordlessUser: boolean;
|
||||
isEmbedded: boolean;
|
||||
preload: boolean;
|
||||
hideHeader: boolean;
|
||||
roomIdOrAlias: string;
|
||||
groupCall: GroupCall;
|
||||
|
|
@ -47,6 +52,7 @@ export function GroupCallView({
|
|||
client,
|
||||
isPasswordlessUser,
|
||||
isEmbedded,
|
||||
preload,
|
||||
hideHeader,
|
||||
roomIdOrAlias,
|
||||
groupCall,
|
||||
|
|
@ -73,14 +79,50 @@ export function GroupCallView({
|
|||
unencryptedEventsFromUsers,
|
||||
} = useGroupCall(groupCall);
|
||||
|
||||
const { setAudioInput, setVideoInput } = useMediaHandler();
|
||||
|
||||
const avatarUrl = useRoomAvatar(groupCall.room);
|
||||
|
||||
useEffect(() => {
|
||||
window.groupCall = groupCall;
|
||||
return () => {
|
||||
delete window.groupCall;
|
||||
};
|
||||
}, [groupCall]);
|
||||
|
||||
// In embedded mode, bypass the lobby and just enter the call straight away
|
||||
if (isEmbedded) groupCall.enter();
|
||||
}, [groupCall, isEmbedded]);
|
||||
useEffect(() => {
|
||||
if (widget && preload) {
|
||||
// In preload mode, wait for a join action before entering
|
||||
const onJoin = async (ev: CustomEvent<IWidgetApiRequest>) => {
|
||||
const { audioInput, videoInput } = ev.detail
|
||||
.data as unknown as JoinCallData;
|
||||
if (audioInput !== null) setAudioInput(audioInput);
|
||||
if (videoInput !== null) setVideoInput(videoInput);
|
||||
await Promise.all([
|
||||
groupCall.setMicrophoneMuted(audioInput === null),
|
||||
groupCall.setLocalVideoMuted(videoInput === null),
|
||||
]);
|
||||
|
||||
await groupCall.enter();
|
||||
await Promise.all([
|
||||
widget.api.setAlwaysOnScreen(true),
|
||||
widget.api.transport.reply(ev.detail, {}),
|
||||
]);
|
||||
};
|
||||
|
||||
widget.lazyActions.on(ElementWidgetActions.JoinCall, onJoin);
|
||||
return () => {
|
||||
widget.lazyActions.off(ElementWidgetActions.JoinCall, onJoin);
|
||||
};
|
||||
}
|
||||
}, [groupCall, preload, setAudioInput, setVideoInput]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isEmbedded && !preload) {
|
||||
// In embedded mode, bypass the lobby and just enter the call straight away
|
||||
groupCall.enter();
|
||||
}
|
||||
}, [groupCall, isEmbedded, preload]);
|
||||
|
||||
useSentryGroupCallHandler(groupCall);
|
||||
|
||||
|
|
@ -90,13 +132,31 @@ export function GroupCallView({
|
|||
const history = useHistory();
|
||||
|
||||
const onLeave = useCallback(() => {
|
||||
setLeft(true);
|
||||
leave();
|
||||
if (widget) {
|
||||
widget.api.transport.send(ElementWidgetActions.HangupCall, {});
|
||||
widget.api.setAlwaysOnScreen(false);
|
||||
}
|
||||
|
||||
if (!isPasswordlessUser) {
|
||||
if (isPasswordlessUser) {
|
||||
setLeft(true);
|
||||
} else if (!isEmbedded) {
|
||||
history.push("/");
|
||||
}
|
||||
}, [leave, isPasswordlessUser, history]);
|
||||
}, [leave, isPasswordlessUser, isEmbedded, history]);
|
||||
|
||||
useEffect(() => {
|
||||
if (widget && state === GroupCallState.Entered) {
|
||||
const onHangup = async (ev: CustomEvent<IWidgetApiRequest>) => {
|
||||
leave();
|
||||
await widget.api.transport.reply(ev.detail, {});
|
||||
};
|
||||
widget.lazyActions.once(ElementWidgetActions.HangupCall, onHangup);
|
||||
return () => {
|
||||
widget.lazyActions.off(ElementWidgetActions.HangupCall, onHangup);
|
||||
};
|
||||
}
|
||||
}, [groupCall, state, leave]);
|
||||
|
||||
if (error) {
|
||||
return <ErrorView error={error} />;
|
||||
|
|
@ -148,33 +208,33 @@ export function GroupCallView({
|
|||
);
|
||||
} else if (left) {
|
||||
return <CallEndedView client={client} />;
|
||||
} else if (preload) {
|
||||
return null;
|
||||
} else if (isEmbedded) {
|
||||
return (
|
||||
<FullScreenView>
|
||||
<h1>Loading room...</h1>
|
||||
</FullScreenView>
|
||||
);
|
||||
} else {
|
||||
if (isEmbedded) {
|
||||
return (
|
||||
<FullScreenView>
|
||||
<h1>Loading room...</h1>
|
||||
</FullScreenView>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<LobbyView
|
||||
client={client}
|
||||
groupCall={groupCall}
|
||||
roomName={groupCall.room.name}
|
||||
avatarUrl={avatarUrl}
|
||||
state={state}
|
||||
onInitLocalCallFeed={initLocalCallFeed}
|
||||
localCallFeed={localCallFeed}
|
||||
onEnter={enter}
|
||||
microphoneMuted={microphoneMuted}
|
||||
localVideoMuted={localVideoMuted}
|
||||
toggleLocalVideoMuted={toggleLocalVideoMuted}
|
||||
toggleMicrophoneMuted={toggleMicrophoneMuted}
|
||||
roomIdOrAlias={roomIdOrAlias}
|
||||
isEmbedded={isEmbedded}
|
||||
hideHeader={hideHeader}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<LobbyView
|
||||
client={client}
|
||||
groupCall={groupCall}
|
||||
roomName={groupCall.room.name}
|
||||
avatarUrl={avatarUrl}
|
||||
state={state}
|
||||
onInitLocalCallFeed={initLocalCallFeed}
|
||||
localCallFeed={localCallFeed}
|
||||
onEnter={enter}
|
||||
microphoneMuted={microphoneMuted}
|
||||
localVideoMuted={localVideoMuted}
|
||||
toggleLocalVideoMuted={toggleLocalVideoMuted}
|
||||
toggleMicrophoneMuted={toggleMicrophoneMuted}
|
||||
roomIdOrAlias={roomIdOrAlias}
|
||||
isEmbedded={isEmbedded}
|
||||
hideHeader={hideHeader}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue