ElementCall fix strict mode call creation loop
In strict mode there is a call create -> destroy -> create infinite loop wen pressing the call button. This loop was a consequence of relying on component creation/destruction to handle creating and removing the call. This logic: - destroying a call if it was in the lobby but leaving it if it is connected when the user stops viewing the room the call belongs to. - Creating an ElementCall if there is not yet once when the user starts viewing a call. Belongs into the roomViewStore and not the components that are just a sideffect in the call livecycle. (view model separation)
This commit is contained in:
@@ -29,6 +29,7 @@ const JoinCallView: FC<JoinCallViewProps> = ({ room, resizing, call, skipLobby,
|
||||
|
||||
useEffect(() => {
|
||||
// We'll take this opportunity to tidy up our room state
|
||||
// Only needed for jitsi.
|
||||
call.clean();
|
||||
}, [call]);
|
||||
|
||||
@@ -44,10 +45,6 @@ const JoinCallView: FC<JoinCallViewProps> = ({ room, resizing, call, skipLobby,
|
||||
// (this will start the lobby view in the widget and connect to all required widget events)
|
||||
call.start();
|
||||
}
|
||||
return (): void => {
|
||||
// If we are connected the widget is sticky and we do not want to destroy the call.
|
||||
if (!call.connected) call.destroy();
|
||||
};
|
||||
}, [call]);
|
||||
const disconnectAllOtherCalls: () => Promise<void> = useCallback(async () => {
|
||||
// The stickyPromise has to resolve before the widget actually becomes sticky.
|
||||
@@ -88,11 +85,6 @@ interface CallViewProps {
|
||||
export const CallView: FC<CallViewProps> = ({ room, resizing, waitForCall, skipLobby, role }) => {
|
||||
const call = useCall(room.roomId);
|
||||
|
||||
useEffect(() => {
|
||||
if (call === null && !waitForCall) {
|
||||
ElementCall.create(room, skipLobby);
|
||||
}
|
||||
}, [call, room, skipLobby, waitForCall]);
|
||||
if (call === null) {
|
||||
return null;
|
||||
} else {
|
||||
|
||||
@@ -740,7 +740,7 @@ export class ElementCall extends Call {
|
||||
// To use Element Call without touching room state, we create a virtual
|
||||
// widget (one that doesn't have a corresponding state event)
|
||||
const url = ElementCall.generateWidgetUrl(client, roomId);
|
||||
return WidgetStore.instance.addVirtualWidget(
|
||||
const createdWidget = WidgetStore.instance.addVirtualWidget(
|
||||
{
|
||||
id: secureRandomString(24), // So that it's globally unique
|
||||
creatorUserId: client.getUserId()!,
|
||||
@@ -761,6 +761,8 @@ export class ElementCall extends Call {
|
||||
},
|
||||
roomId,
|
||||
);
|
||||
WidgetStore.instance.emit(UPDATE_EVENT, null);
|
||||
return createdWidget;
|
||||
}
|
||||
|
||||
private static getWidgetData(
|
||||
@@ -829,7 +831,6 @@ export class ElementCall extends Call {
|
||||
|
||||
public static async create(room: Room, skipLobby = false): Promise<void> {
|
||||
ElementCall.createOrGetCallWidget(room.roomId, room.client, skipLobby, false, isVideoRoom(room));
|
||||
WidgetStore.instance.emit(UPDATE_EVENT, null);
|
||||
}
|
||||
|
||||
protected async sendCallNotify(): Promise<void> {
|
||||
|
||||
@@ -50,6 +50,7 @@ import { type CancelAskToJoinPayload } from "../dispatcher/payloads/CancelAskToJ
|
||||
import { type SubmitAskToJoinPayload } from "../dispatcher/payloads/SubmitAskToJoinPayload";
|
||||
import { ModuleRunner } from "../modules/ModuleRunner";
|
||||
import { setMarkedUnreadState } from "../utils/notifications";
|
||||
import { ElementCall } from "../models/Call";
|
||||
|
||||
const NUM_JOIN_RETRY = 5;
|
||||
|
||||
@@ -353,6 +354,19 @@ export class RoomViewStore extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
// Start call when requested
|
||||
const currentRoomCall = this.state.roomId ? CallStore.instance.getCall(this.state.roomId) : null;
|
||||
if (payload.view_call && room) {
|
||||
if (!currentRoomCall) {
|
||||
ElementCall.create(room, false);
|
||||
}
|
||||
}
|
||||
// Destroy call when requested leaving call view
|
||||
const prevRoomCall = this.state.roomId ? CallStore.instance.getCall(this.state.roomId) : null;
|
||||
if (prevRoomCall && !prevRoomCall.connected) {
|
||||
currentRoomCall?.destroy();
|
||||
}
|
||||
|
||||
if (SettingsStore.getValue("feature_sliding_sync") && this.state.roomId !== payload.room_id) {
|
||||
if (this.state.subscribingRoomId && this.state.subscribingRoomId !== payload.room_id) {
|
||||
// unsubscribe from this room, but don't await it as we don't care when this gets done.
|
||||
|
||||
Reference in New Issue
Block a user