Consolidate all group call creation into useLoadGroupCall
This enables us to automatically create a group call in rooms that exist, but contain no calls.
This commit is contained in:
parent
b4a56f6dd7
commit
fae4c504c9
4 changed files with 124 additions and 130 deletions
|
@ -10,10 +10,6 @@ import { ICreateClientOpts } from "matrix-js-sdk/src/matrix";
|
||||||
import { ClientEvent } from "matrix-js-sdk/src/client";
|
import { ClientEvent } from "matrix-js-sdk/src/client";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { Visibility, Preset } from "matrix-js-sdk/src/@types/partials";
|
import { Visibility, Preset } from "matrix-js-sdk/src/@types/partials";
|
||||||
import {
|
|
||||||
GroupCallIntent,
|
|
||||||
GroupCallType,
|
|
||||||
} from "matrix-js-sdk/src/webrtc/groupCall";
|
|
||||||
import { ISyncStateData, SyncState } from "matrix-js-sdk/src/sync";
|
import { ISyncStateData, SyncState } from "matrix-js-sdk/src/sync";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
@ -224,8 +220,7 @@ export function isLocalRoomId(roomId: string): boolean {
|
||||||
|
|
||||||
export async function createRoom(
|
export async function createRoom(
|
||||||
client: MatrixClient,
|
client: MatrixClient,
|
||||||
name: string,
|
name: string
|
||||||
isPtt = false
|
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
let setExpectedRoomId: (roomId: string) => void;
|
let setExpectedRoomId: (roomId: string) => void;
|
||||||
const expectedRoomId = new Promise<string>(
|
const expectedRoomId = new Promise<string>(
|
||||||
|
@ -278,15 +273,6 @@ export async function createRoom(
|
||||||
setExpectedRoomId(createRoomResult.room_id);
|
setExpectedRoomId(createRoomResult.room_id);
|
||||||
await roomReceived;
|
await roomReceived;
|
||||||
|
|
||||||
console.log(`Creating ${isPtt ? "PTT" : "video"} group call room`);
|
|
||||||
|
|
||||||
await client.createGroupCall(
|
|
||||||
createRoomResult.room_id,
|
|
||||||
isPtt ? GroupCallType.Voice : GroupCallType.Video,
|
|
||||||
isPtt,
|
|
||||||
GroupCallIntent.Prompt
|
|
||||||
);
|
|
||||||
|
|
||||||
return fullAliasFromRoomName(name, client);
|
return fullAliasFromRoomName(name, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ export function GroupCallLoader({
|
||||||
client,
|
client,
|
||||||
roomId,
|
roomId,
|
||||||
viaServers,
|
viaServers,
|
||||||
true,
|
|
||||||
createPtt
|
createPtt
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2022 Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
|
||||||
import { isLocalRoomId, createRoom, roomNameFromRoomId } from "../matrix-utils";
|
|
||||||
|
|
||||||
async function fetchGroupCall(
|
|
||||||
client,
|
|
||||||
roomIdOrAlias,
|
|
||||||
viaServers = undefined,
|
|
||||||
timeout = 5000
|
|
||||||
) {
|
|
||||||
const { roomId } = await client.joinRoom(roomIdOrAlias, { viaServers });
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let timeoutId;
|
|
||||||
|
|
||||||
function onGroupCallIncoming(groupCall) {
|
|
||||||
if (groupCall && groupCall.room.roomId === roomId) {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
client.removeListener("GroupCall.incoming", onGroupCallIncoming);
|
|
||||||
resolve(groupCall);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const groupCall = client.getGroupCallForRoom(roomId);
|
|
||||||
|
|
||||||
if (groupCall) {
|
|
||||||
resolve(groupCall);
|
|
||||||
}
|
|
||||||
|
|
||||||
client.on("GroupCall.incoming", onGroupCallIncoming);
|
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
timeoutId = setTimeout(() => {
|
|
||||||
client.removeListener("GroupCall.incoming", onGroupCallIncoming);
|
|
||||||
reject(new Error("Fetching group call timed out."));
|
|
||||||
}, timeout);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useLoadGroupCall(
|
|
||||||
client,
|
|
||||||
roomId,
|
|
||||||
viaServers,
|
|
||||||
createIfNotFound,
|
|
||||||
createPtt
|
|
||||||
) {
|
|
||||||
const [state, setState] = useState({
|
|
||||||
loading: true,
|
|
||||||
error: undefined,
|
|
||||||
groupCall: undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
async function fetchOrCreateGroupCall() {
|
|
||||||
try {
|
|
||||||
const groupCall = await fetchGroupCall(
|
|
||||||
client,
|
|
||||||
roomId,
|
|
||||||
viaServers,
|
|
||||||
30000
|
|
||||||
);
|
|
||||||
return groupCall;
|
|
||||||
} catch (error) {
|
|
||||||
if (
|
|
||||||
createIfNotFound &&
|
|
||||||
(error.errcode === "M_NOT_FOUND" ||
|
|
||||||
(error.message &&
|
|
||||||
error.message.indexOf("Failed to fetch alias") !== -1)) &&
|
|
||||||
isLocalRoomId(roomId)
|
|
||||||
) {
|
|
||||||
const roomName = roomNameFromRoomId(roomId);
|
|
||||||
await createRoom(client, roomName, createPtt);
|
|
||||||
const groupCall = await fetchGroupCall(
|
|
||||||
client,
|
|
||||||
roomId,
|
|
||||||
viaServers,
|
|
||||||
30000
|
|
||||||
);
|
|
||||||
return groupCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setState({ loading: true });
|
|
||||||
|
|
||||||
fetchOrCreateGroupCall()
|
|
||||||
.then((groupCall) =>
|
|
||||||
setState((prevState) => ({ ...prevState, loading: false, groupCall }))
|
|
||||||
)
|
|
||||||
.catch((error) =>
|
|
||||||
setState((prevState) => ({ ...prevState, loading: false, error }))
|
|
||||||
);
|
|
||||||
}, [client, roomId, state.reloadId, createIfNotFound, viaServers, createPtt]);
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
123
src/room/useLoadGroupCall.ts
Normal file
123
src/room/useLoadGroupCall.ts
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { EventType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
import {
|
||||||
|
GroupCallType,
|
||||||
|
GroupCallIntent,
|
||||||
|
} from "matrix-js-sdk/src/webrtc/groupCall";
|
||||||
|
import { GroupCallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/groupCallEventHandler";
|
||||||
|
|
||||||
|
import type { MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
|
import type { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
import type { GroupCall } from "matrix-js-sdk/src/webrtc/groupCall";
|
||||||
|
import { isLocalRoomId, createRoom, roomNameFromRoomId } from "../matrix-utils";
|
||||||
|
|
||||||
|
export interface GroupCallLoadState {
|
||||||
|
loading: boolean;
|
||||||
|
error?: Error;
|
||||||
|
groupCall?: GroupCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useLoadGroupCall = (
|
||||||
|
client: MatrixClient,
|
||||||
|
roomIdOrAlias: string,
|
||||||
|
viaServers: string[],
|
||||||
|
createPtt: boolean
|
||||||
|
) => {
|
||||||
|
const [state, setState] = useState<GroupCallLoadState>({ loading: true });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setState({ loading: true });
|
||||||
|
|
||||||
|
const fetchOrCreateRoom = async (): Promise<Room> => {
|
||||||
|
try {
|
||||||
|
return await client.joinRoom(roomIdOrAlias, { viaServers });
|
||||||
|
} catch (error) {
|
||||||
|
if (
|
||||||
|
isLocalRoomId(roomIdOrAlias) &&
|
||||||
|
(error.errcode === "M_NOT_FOUND" ||
|
||||||
|
(error.message &&
|
||||||
|
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 });
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchOrCreateGroupCall = async (): Promise<GroupCall> => {
|
||||||
|
const room = await fetchOrCreateRoom();
|
||||||
|
const groupCall = client.getGroupCallForRoom(room.roomId);
|
||||||
|
|
||||||
|
if (groupCall) {
|
||||||
|
return groupCall;
|
||||||
|
} else if (
|
||||||
|
room.currentState.mayClientSendStateEvent(
|
||||||
|
EventType.GroupCallPrefix,
|
||||||
|
client
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// The call doesn't exist, but we can create it
|
||||||
|
console.log(`Creating ${createPtt ? "PTT" : "video"} group call room`);
|
||||||
|
return await client.createGroupCall(
|
||||||
|
room.roomId,
|
||||||
|
createPtt ? GroupCallType.Voice : GroupCallType.Video,
|
||||||
|
createPtt,
|
||||||
|
GroupCallIntent.Room
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// We don't have permission to create the call, so all we can do is wait
|
||||||
|
// for one to come in
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const onGroupCallIncoming = (groupCall: GroupCall) => {
|
||||||
|
if (groupCall?.room.roomId === room.roomId) {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
client.off(
|
||||||
|
GroupCallEventHandlerEvent.Incoming,
|
||||||
|
onGroupCallIncoming
|
||||||
|
);
|
||||||
|
resolve(groupCall);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
client.on(GroupCallEventHandlerEvent.Incoming, onGroupCallIncoming);
|
||||||
|
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
client.off(
|
||||||
|
GroupCallEventHandlerEvent.Incoming,
|
||||||
|
onGroupCallIncoming
|
||||||
|
);
|
||||||
|
reject(new Error("Fetching group call timed out."));
|
||||||
|
}, 30000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchOrCreateGroupCall()
|
||||||
|
.then((groupCall) =>
|
||||||
|
setState((prevState) => ({ ...prevState, loading: false, groupCall }))
|
||||||
|
)
|
||||||
|
.catch((error) =>
|
||||||
|
setState((prevState) => ({ ...prevState, loading: false, error }))
|
||||||
|
);
|
||||||
|
}, [client, roomIdOrAlias, viaServers, createPtt]);
|
||||||
|
|
||||||
|
return state;
|
||||||
|
};
|
Loading…
Reference in a new issue