Refactor room loading components

This commit is contained in:
Robert Long 2022-01-05 15:35:12 -08:00
parent 550c45b69e
commit 0fe38000f5
5 changed files with 191 additions and 170 deletions

View file

@ -0,0 +1,25 @@
import React from "react";
import { useLoadGroupCall } from "../ConferenceCallManagerHooks";
import { ErrorView, FullScreenView } from "../FullScreenView";
export function GroupCallLoader({ client, roomId, viaServers, children }) {
const { loading, error, groupCall } = useLoadGroupCall(
client,
roomId,
viaServers
);
if (loading) {
return (
<FullScreenView>
<h1>Loading room...</h1>
</FullScreenView>
);
}
if (error) {
return <ErrorView error={error} />;
}
return children(groupCall);
}

111
src/room/GroupCallView.jsx Normal file
View file

@ -0,0 +1,111 @@
import React, { useCallback, useEffect, useState } from "react";
import { useHistory } from "react-router-dom";
import { GroupCallState } from "matrix-js-sdk/src/webrtc/groupCall";
import { useGroupCall } from "matrix-react-sdk/src/hooks/useGroupCall";
import { ErrorView, FullScreenView } from "../FullScreenView";
import { LobbyView } from "./LobbyView";
import { InCallView } from "./InCallView";
import { CallEndedView } from "./CallEndedView";
import { useSentryGroupCallHandler } from "./useSentryGroupCallHandler";
export function GroupCallView({
client,
isPasswordlessUser,
roomId,
groupCall,
simpleGrid,
}) {
const [showInspector, setShowInspector] = useState(false);
const {
state,
error,
activeSpeaker,
userMediaFeeds,
microphoneMuted,
localVideoMuted,
localCallFeed,
initLocalCallFeed,
enter,
leave,
toggleLocalVideoMuted,
toggleMicrophoneMuted,
toggleScreensharing,
isScreensharing,
localScreenshareFeed,
screenshareFeeds,
hasLocalParticipant,
} = useGroupCall(groupCall);
useEffect(() => {
window.groupCall = groupCall;
}, [groupCall]);
useSentryGroupCallHandler(groupCall);
const [left, setLeft] = useState(false);
const history = useHistory();
const onLeave = useCallback(() => {
leave();
if (!isPasswordlessUser) {
history.push("/");
} else {
setLeft(true);
}
}, [leave, history]);
if (error) {
return <ErrorView error={error} />;
} else if (state === GroupCallState.Entered) {
return (
<InCallView
groupCall={groupCall}
client={client}
roomName={groupCall.room.name}
microphoneMuted={microphoneMuted}
localVideoMuted={localVideoMuted}
toggleLocalVideoMuted={toggleLocalVideoMuted}
toggleMicrophoneMuted={toggleMicrophoneMuted}
userMediaFeeds={userMediaFeeds}
activeSpeaker={activeSpeaker}
onLeave={onLeave}
toggleScreensharing={toggleScreensharing}
isScreensharing={isScreensharing}
localScreenshareFeed={localScreenshareFeed}
screenshareFeeds={screenshareFeeds}
simpleGrid={simpleGrid}
setShowInspector={setShowInspector}
showInspector={showInspector}
roomId={roomId}
/>
);
} else if (state === GroupCallState.Entering) {
return (
<FullScreenView>
<h1>Entering room...</h1>
</FullScreenView>
);
} else if (left) {
return <CallEndedView client={client} />;
} else {
return (
<LobbyView
client={client}
hasLocalParticipant={hasLocalParticipant}
roomName={groupCall.room.name}
state={state}
onInitLocalCallFeed={initLocalCallFeed}
localCallFeed={localCallFeed}
onEnter={enter}
microphoneMuted={microphoneMuted}
localVideoMuted={localVideoMuted}
toggleLocalVideoMuted={toggleLocalVideoMuted}
toggleMicrophoneMuted={toggleMicrophoneMuted}
setShowInspector={setShowInspector}
showInspector={showInspector}
roomId={roomId}
/>
);
}
}

View file

@ -0,0 +1,5 @@
import React from "react";
export function RoomAuthView() {
return <div>Register</div>;
}

View file

@ -14,40 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useLocation, useParams, useHistory } from "react-router-dom";
import { GroupCallState } from "matrix-js-sdk/src/webrtc/groupCall";
import { useGroupCall } from "matrix-react-sdk/src/hooks/useGroupCall";
import { useClient, useLoadGroupCall } from "../ConferenceCallManagerHooks";
import { ErrorView, LoadingView, FullScreenView } from "../FullScreenView";
import * as Sentry from "@sentry/react";
import { LobbyView } from "./LobbyView";
import { InCallView } from "./InCallView";
import { CallEndedView } from "./CallEndedView";
import React, { useMemo } from "react";
import { useLocation, useParams } from "react-router-dom";
import { useClient } from "../ConferenceCallManagerHooks";
import { ErrorView, LoadingView } from "../FullScreenView";
import { RoomAuthView } from "./RoomAuthView";
import { GroupCallLoader } from "./GroupCallLoader";
import { GroupCallView } from "./GroupCallView";
export function RoomPage() {
const [registrationError, setRegistrationError] = useState();
const { loading, isAuthenticated, error, client, isPasswordlessUser } =
useClient();
useEffect(() => {
if (!loading && !isAuthenticated) {
setRegistrationError(new Error("Must be registered"));
}
}, [loading, isAuthenticated]);
if (loading) {
return <LoadingView />;
}
if (registrationError || error) {
return <ErrorView error={registrationError || error} />;
}
return <GroupCall client={client} isPasswordlessUser={isPasswordlessUser} />;
}
export function GroupCall({ client, isPasswordlessUser }) {
const { roomId: maybeRoomId } = useParams();
const { hash, search } = useLocation();
const [simpleGrid, viaServers] = useMemo(() => {
@ -55,155 +33,30 @@ export function GroupCall({ client, isPasswordlessUser }) {
return [params.has("simple"), params.getAll("via")];
}, [search]);
const roomId = maybeRoomId || hash;
const { loading, error, groupCall } = useLoadGroupCall(
client,
roomId,
viaServers
);
useEffect(() => {
window.groupCall = groupCall;
}, [groupCall]);
if (loading) {
return (
<FullScreenView>
<h1>Loading room...</h1>
</FullScreenView>
);
return <LoadingView />;
}
if (error) {
return <ErrorView error={error} />;
}
if (!isAuthenticated) {
return <RoomAuthView />;
}
return (
<GroupCallView
isPasswordlessUser={isPasswordlessUser}
client={client}
roomId={roomId}
groupCall={groupCall}
simpleGrid={simpleGrid}
/>
<GroupCallLoader roomId={roomId} viaServers={viaServers}>
{(groupCall) => (
<GroupCallView
client={client}
roomId={roomId}
groupCall={groupCall}
isPasswordlessUser={isPasswordlessUser}
simpleGrid={simpleGrid}
/>
)}
</GroupCallLoader>
);
}
export function GroupCallView({
client,
isPasswordlessUser,
roomId,
groupCall,
simpleGrid,
}) {
const [showInspector, setShowInspector] = useState(false);
const {
state,
error,
activeSpeaker,
userMediaFeeds,
microphoneMuted,
localVideoMuted,
localCallFeed,
initLocalCallFeed,
enter,
leave,
toggleLocalVideoMuted,
toggleMicrophoneMuted,
toggleScreensharing,
isScreensharing,
localScreenshareFeed,
screenshareFeeds,
hasLocalParticipant,
} = useGroupCall(groupCall);
useEffect(() => {
function onHangup(call) {
if (call.hangupReason === "ice_failed") {
Sentry.captureException(new Error("Call hangup due to ICE failure."));
}
}
function onError(error) {
Sentry.captureException(error);
}
if (groupCall) {
groupCall.on("hangup", onHangup);
groupCall.on("error", onError);
}
return () => {
if (groupCall) {
groupCall.removeListener("hangup", onHangup);
groupCall.removeListener("error", onError);
}
};
}, [groupCall]);
const [left, setLeft] = useState(false);
const history = useHistory();
const onLeave = useCallback(() => {
leave();
if (!isPasswordlessUser) {
history.push("/");
} else {
setLeft(true);
}
}, [leave, history]);
if (error) {
return <ErrorView error={error} />;
} else if (state === GroupCallState.Entered) {
return (
<InCallView
groupCall={groupCall}
client={client}
roomName={groupCall.room.name}
microphoneMuted={microphoneMuted}
localVideoMuted={localVideoMuted}
toggleLocalVideoMuted={toggleLocalVideoMuted}
toggleMicrophoneMuted={toggleMicrophoneMuted}
userMediaFeeds={userMediaFeeds}
activeSpeaker={activeSpeaker}
onLeave={onLeave}
toggleScreensharing={toggleScreensharing}
isScreensharing={isScreensharing}
localScreenshareFeed={localScreenshareFeed}
screenshareFeeds={screenshareFeeds}
simpleGrid={simpleGrid}
setShowInspector={setShowInspector}
showInspector={showInspector}
roomId={roomId}
/>
);
} else if (state === GroupCallState.Entering) {
return (
<FullScreenView>
<h1>Entering room...</h1>
</FullScreenView>
);
} else if (left) {
return <CallEndedView client={client} />;
} else {
return (
<LobbyView
client={client}
hasLocalParticipant={hasLocalParticipant}
roomName={groupCall.room.name}
state={state}
onInitLocalCallFeed={initLocalCallFeed}
localCallFeed={localCallFeed}
onEnter={enter}
microphoneMuted={microphoneMuted}
localVideoMuted={localVideoMuted}
toggleLocalVideoMuted={toggleLocalVideoMuted}
toggleMicrophoneMuted={toggleMicrophoneMuted}
setShowInspector={setShowInspector}
showInspector={showInspector}
roomId={roomId}
/>
);
}
}

View file

@ -0,0 +1,27 @@
import * as Sentry from "@sentry/react";
export function useSentryGroupCallHandler(groupCall) {
useEffect(() => {
function onHangup(call) {
if (call.hangupReason === "ice_failed") {
Sentry.captureException(new Error("Call hangup due to ICE failure."));
}
}
function onError(error) {
Sentry.captureException(error);
}
if (groupCall) {
groupCall.on("hangup", onHangup);
groupCall.on("error", onError);
}
return () => {
if (groupCall) {
groupCall.removeListener("hangup", onHangup);
groupCall.removeListener("error", onError);
}
};
}, [groupCall]);
}