Fix sequencing of call state updates

This commit is contained in:
Fedor Indutny
2025-03-17 13:06:51 -07:00
committed by GitHub
parent 3758e8138a
commit 9a8b42d835

View File

@@ -1457,7 +1457,9 @@ export class CallingClass {
this.#callsLookup[conversationId] = groupCall;
// NOTE: This assumes only one active call at a time. See comment above.
if (localDeviceState.videoMuted) {
if (localDeviceState.sharingScreen) {
// Controlled by `#startPresenting`/`#stopPresenting`
} else if (localDeviceState.videoMuted) {
this.disableLocalVideo();
} else {
drop(this.enableCaptureAndSend(groupCall, null, logId));
@@ -2196,10 +2198,13 @@ export class CallingClass {
return;
}
await window.reduxActions.globalModals.ensureSystemMediaPermissions(
'camera',
'call'
);
if (enabled) {
// Make sure we have access to camera
await window.reduxActions.globalModals.ensureSystemMediaPermissions(
'camera',
'call'
);
}
if (call instanceof Call) {
RingRTC.setOutgoingVideo(call.callId, enabled);
@@ -2210,16 +2215,56 @@ export class CallingClass {
}
}
#setOutgoingVideoIsScreenShare(
async #startPresenting(
call: Call | GroupCall,
enabled: boolean
): void {
mediaStream: MediaStream
): Promise<void> {
if (call instanceof Call) {
RingRTC.setOutgoingVideoIsScreenShare(call.callId, enabled);
// Note: there is no "presenting" API for direct calls.
RingRTC.setOutgoingVideoIsScreenShare(call.callId, true);
} else if (call instanceof GroupCall) {
call.setOutgoingVideoIsScreenShare(enabled);
call.setPresenting(enabled);
call.setOutgoingVideoIsScreenShare(true);
call.setPresenting(true);
} else {
throw missingCaseError(call);
}
// Start screen sharing stream
await this.enableCaptureAndSend(call, {
maxFramerate: REQUESTED_SCREEN_SHARE_FRAMERATE,
maxHeight: REQUESTED_SCREEN_SHARE_HEIGHT,
maxWidth: REQUESTED_SCREEN_SHARE_WIDTH,
mediaStream,
onEnded: () => {
this.#reduxInterface?.cancelPresenting();
},
});
// Enable the video transmission once the stream is running
if (call instanceof Call) {
RingRTC.setOutgoingVideo(call.callId, true);
} else if (call instanceof GroupCall) {
call.setOutgoingVideoMuted(false);
} else {
throw missingCaseError(call);
}
}
async #stopPresenting(
call: Call | GroupCall,
hasLocalVideo: boolean
): Promise<void> {
if (call instanceof Call) {
// Disable video transmission first
RingRTC.setOutgoingVideo(call.callId, hasLocalVideo);
// Stop screenshare
RingRTC.setOutgoingVideoIsScreenShare(call.callId, false);
} else if (call instanceof GroupCall) {
// Ditto
call.setOutgoingVideoMuted(!hasLocalVideo);
call.setOutgoingVideoIsScreenShare(false);
call.setPresenting(false);
} else {
throw missingCaseError(call);
}
@@ -2242,30 +2287,14 @@ export class CallingClass {
const isPresenting = mediaStream != null;
if (isPresenting) {
this.#hadLocalVideoBeforePresenting = hasLocalVideo;
drop(
this.enableCaptureAndSend(call, {
maxFramerate: REQUESTED_SCREEN_SHARE_FRAMERATE,
maxHeight: REQUESTED_SCREEN_SHARE_HEIGHT,
maxWidth: REQUESTED_SCREEN_SHARE_WIDTH,
mediaStream,
onEnded: () => {
this.#reduxInterface?.cancelPresenting();
},
})
);
drop(this.setOutgoingVideo(conversationId, true));
await this.#startPresenting(call, mediaStream);
} else {
drop(
this.setOutgoingVideo(
conversationId,
this.#hadLocalVideoBeforePresenting ?? hasLocalVideo
)
);
const prevHasLocalVideo =
this.#hadLocalVideoBeforePresenting ?? hasLocalVideo;
this.#hadLocalVideoBeforePresenting = undefined;
await this.#stopPresenting(call, prevHasLocalVideo);
}
this.#setOutgoingVideoIsScreenShare(call, isPresenting);
if (isPresenting) {
ipcRenderer.send('show-screen-share', source?.name);