diff --git a/src/room/GroupCallLoader.jsx b/src/room/GroupCallLoader.jsx new file mode 100644 index 0000000..300af82 --- /dev/null +++ b/src/room/GroupCallLoader.jsx @@ -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 ( + +

Loading room...

+
+ ); + } + + if (error) { + return ; + } + + return children(groupCall); +} diff --git a/src/room/GroupCallView.jsx b/src/room/GroupCallView.jsx new file mode 100644 index 0000000..1d1641d --- /dev/null +++ b/src/room/GroupCallView.jsx @@ -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 ; + } else if (state === GroupCallState.Entered) { + return ( + + ); + } else if (state === GroupCallState.Entering) { + return ( + +

Entering room...

+
+ ); + } else if (left) { + return ; + } else { + return ( + + ); + } +} diff --git a/src/room/RoomAuthView.jsx b/src/room/RoomAuthView.jsx new file mode 100644 index 0000000..db5a2d4 --- /dev/null +++ b/src/room/RoomAuthView.jsx @@ -0,0 +1,5 @@ +import React from "react"; + +export function RoomAuthView() { + return
Register
; +} diff --git a/src/room/RoomPage.jsx b/src/room/RoomPage.jsx index 450ca54..946f795 100644 --- a/src/room/RoomPage.jsx +++ b/src/room/RoomPage.jsx @@ -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 ; - } - - if (registrationError || error) { - return ; - } - - return ; -} - -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 ( - -

Loading room...

-
- ); + return ; } if (error) { return ; } + if (!isAuthenticated) { + return ; + } + return ( - + + {(groupCall) => ( + + )} + ); } - -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 ; - } else if (state === GroupCallState.Entered) { - return ( - - ); - } else if (state === GroupCallState.Entering) { - return ( - -

Entering room...

-
- ); - } else if (left) { - return ; - } else { - return ( - - ); - } -} diff --git a/src/room/useSentryGroupCallHandler.js b/src/room/useSentryGroupCallHandler.js new file mode 100644 index 0000000..2bedf16 --- /dev/null +++ b/src/room/useSentryGroupCallHandler.js @@ -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]); +}