diff --git a/src/home/RegisteredView.jsx b/src/home/RegisteredView.jsx index 1d07d1c..b5fef74 100644 --- a/src/home/RegisteredView.jsx +++ b/src/home/RegisteredView.jsx @@ -47,7 +47,7 @@ export function RegisteredView({ client }) { setError(undefined); setLoading(true); - const roomIdOrAlias = await createRoom(client, roomName, ptt); + const [roomIdOrAlias] = await createRoom(client, roomName, ptt); if (roomIdOrAlias) { history.push(`/room/${roomIdOrAlias}`); diff --git a/src/home/UnauthenticatedView.jsx b/src/home/UnauthenticatedView.jsx index f324d50..a6d7a6e 100644 --- a/src/home/UnauthenticatedView.jsx +++ b/src/home/UnauthenticatedView.jsx @@ -70,7 +70,7 @@ export function UnauthenticatedView() { let roomIdOrAlias; try { - roomIdOrAlias = await createRoom(client, roomName, ptt); + [roomIdOrAlias] = await createRoom(client, roomName, ptt); } catch (error) { if (error.errcode === "M_ROOM_IN_USE") { setOnFinished(() => () => { diff --git a/src/matrix-utils.ts b/src/matrix-utils.ts index 9b6a005..5986954 100644 --- a/src/matrix-utils.ts +++ b/src/matrix-utils.ts @@ -220,8 +220,8 @@ export function isLocalRoomId(roomId: string): boolean { export async function createRoom( client: MatrixClient, name: string -): Promise { - await client.createRoom({ +): Promise<[string, string]> { + const result = await client.createRoom({ visibility: Visibility.Private, preset: Preset.PublicChat, name, @@ -251,7 +251,7 @@ export async function createRoom( }, }); - return fullAliasFromRoomName(name, client); + return [fullAliasFromRoomName(name, client), result.room_id]; } export function getRoomUrl(roomId: string): string { diff --git a/src/room/useLoadGroupCall.ts b/src/room/useLoadGroupCall.ts index 0d7fb7c..301ba54 100644 --- a/src/room/useLoadGroupCall.ts +++ b/src/room/useLoadGroupCall.ts @@ -21,6 +21,7 @@ import { GroupCallIntent, } from "matrix-js-sdk/src/webrtc/groupCall"; import { GroupCallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/groupCallEventHandler"; +import { ClientEvent } from "matrix-js-sdk/src/client"; import type { MatrixClient } from "matrix-js-sdk/src/client"; import type { Room } from "matrix-js-sdk/src/models/room"; @@ -44,9 +45,38 @@ export const useLoadGroupCall = ( useEffect(() => { setState({ loading: true }); + const waitForRoom = async (roomId: string): Promise => { + const room = client.getRoom(roomId); + if (room) return room; + console.log(`Room ${roomId} hasn't arrived yet: waiting`); + + const waitPromise = new Promise((resolve) => { + const onRoomEvent = async (room: Room) => { + if (room.roomId === roomId) { + client.removeListener(ClientEvent.Room, onRoomEvent); + resolve(room); + } + }; + client.on(ClientEvent.Room, onRoomEvent); + }); + + // race the promise with a timeout so we don't + // wait forever for the room + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => { + reject(new Error("Timed out trying to join room")); + }, 30000); + }); + + return Promise.race([waitPromise, timeoutPromise]); + }; + const fetchOrCreateRoom = async (): Promise => { try { - return await client.joinRoom(roomIdOrAlias, { viaServers }); + const room = await client.joinRoom(roomIdOrAlias, { viaServers }); + // wait for the room to come down the sync stream, otherwise + // client.getRoom() won't return the room. + return waitForRoom(room.roomId); } catch (error) { if ( isLocalRoomId(roomIdOrAlias) && @@ -55,8 +85,12 @@ export const useLoadGroupCall = ( error.message.indexOf("Failed to fetch alias") !== -1)) ) { // The room doesn't exist, but we can create it - await createRoom(client, roomNameFromRoomId(roomIdOrAlias)); - return await client.joinRoom(roomIdOrAlias, { viaServers }); + const [, roomId] = await createRoom( + client, + roomNameFromRoomId(roomIdOrAlias) + ); + // likewise, wait for the room + return await waitForRoom(roomId); } else { throw error; }