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(() => {
|
useEffect(() => {
|
||||||
// We'll take this opportunity to tidy up our room state
|
// We'll take this opportunity to tidy up our room state
|
||||||
|
// Only needed for jitsi.
|
||||||
call.clean();
|
call.clean();
|
||||||
}, [call]);
|
}, [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)
|
// (this will start the lobby view in the widget and connect to all required widget events)
|
||||||
call.start();
|
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]);
|
}, [call]);
|
||||||
const disconnectAllOtherCalls: () => Promise<void> = useCallback(async () => {
|
const disconnectAllOtherCalls: () => Promise<void> = useCallback(async () => {
|
||||||
// The stickyPromise has to resolve before the widget actually becomes sticky.
|
// 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 }) => {
|
export const CallView: FC<CallViewProps> = ({ room, resizing, waitForCall, skipLobby, role }) => {
|
||||||
const call = useCall(room.roomId);
|
const call = useCall(room.roomId);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (call === null && !waitForCall) {
|
|
||||||
ElementCall.create(room, skipLobby);
|
|
||||||
}
|
|
||||||
}, [call, room, skipLobby, waitForCall]);
|
|
||||||
if (call === null) {
|
if (call === null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -740,7 +740,7 @@ export class ElementCall extends Call {
|
|||||||
// To use Element Call without touching room state, we create a virtual
|
// To use Element Call without touching room state, we create a virtual
|
||||||
// widget (one that doesn't have a corresponding state event)
|
// widget (one that doesn't have a corresponding state event)
|
||||||
const url = ElementCall.generateWidgetUrl(client, roomId);
|
const url = ElementCall.generateWidgetUrl(client, roomId);
|
||||||
return WidgetStore.instance.addVirtualWidget(
|
const createdWidget = WidgetStore.instance.addVirtualWidget(
|
||||||
{
|
{
|
||||||
id: secureRandomString(24), // So that it's globally unique
|
id: secureRandomString(24), // So that it's globally unique
|
||||||
creatorUserId: client.getUserId()!,
|
creatorUserId: client.getUserId()!,
|
||||||
@@ -761,6 +761,8 @@ export class ElementCall extends Call {
|
|||||||
},
|
},
|
||||||
roomId,
|
roomId,
|
||||||
);
|
);
|
||||||
|
WidgetStore.instance.emit(UPDATE_EVENT, null);
|
||||||
|
return createdWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static getWidgetData(
|
private static getWidgetData(
|
||||||
@@ -829,7 +831,6 @@ export class ElementCall extends Call {
|
|||||||
|
|
||||||
public static async create(room: Room, skipLobby = false): Promise<void> {
|
public static async create(room: Room, skipLobby = false): Promise<void> {
|
||||||
ElementCall.createOrGetCallWidget(room.roomId, room.client, skipLobby, false, isVideoRoom(room));
|
ElementCall.createOrGetCallWidget(room.roomId, room.client, skipLobby, false, isVideoRoom(room));
|
||||||
WidgetStore.instance.emit(UPDATE_EVENT, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async sendCallNotify(): Promise<void> {
|
protected async sendCallNotify(): Promise<void> {
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import { type CancelAskToJoinPayload } from "../dispatcher/payloads/CancelAskToJ
|
|||||||
import { type SubmitAskToJoinPayload } from "../dispatcher/payloads/SubmitAskToJoinPayload";
|
import { type SubmitAskToJoinPayload } from "../dispatcher/payloads/SubmitAskToJoinPayload";
|
||||||
import { ModuleRunner } from "../modules/ModuleRunner";
|
import { ModuleRunner } from "../modules/ModuleRunner";
|
||||||
import { setMarkedUnreadState } from "../utils/notifications";
|
import { setMarkedUnreadState } from "../utils/notifications";
|
||||||
|
import { ElementCall } from "../models/Call";
|
||||||
|
|
||||||
const NUM_JOIN_RETRY = 5;
|
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 (SettingsStore.getValue("feature_sliding_sync") && this.state.roomId !== payload.room_id) {
|
||||||
if (this.state.subscribingRoomId && this.state.subscribingRoomId !== 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.
|
// 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