From 37828ab0842560712f8fb884f4e25cef9f5a1fa0 Mon Sep 17 00:00:00 2001 From: Timo <16718859+toger5@users.noreply.github.com> Date: Thu, 25 Nov 2021 22:14:19 +0100 Subject: [PATCH] Maximised widgets always force a call to be shown in PIP mode (#7163) --- src/CallHandler.tsx | 10 +++++ src/components/views/voip/CallPreview.tsx | 48 +++++++++++++++-------- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index a68337e2ed..ed884340a7 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -380,6 +380,16 @@ export default class CallHandler extends EventEmitter { return callsNotInThatRoom; } + public getAllActiveCallsForPip(roomId: string) { + const room = MatrixClientPeg.get().getRoom(roomId); + if (WidgetLayoutStore.instance.hasMaximisedWidget(room)) { + // This checks if there is space for the call view in the aux panel + // If there is no space any call should be displayed in PiP + return this.getAllActiveCalls(); + } + return this.getAllActiveCallsNotInRoom(roomId); + } + getTransfereeForCallId(callId: string): MatrixCall { return this.transferees[callId]; } diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index e34266616e..1c667e4229 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -31,6 +31,7 @@ import { EventSubscription } from 'fbemitter'; import PictureInPictureDragger from './PictureInPictureDragger'; import { logger } from "matrix-js-sdk/src/logger"; +import { WidgetLayoutStore } from '../../../stores/widgets/WidgetLayoutStore'; const SHOW_CALL_IN_STATES = [ CallState.Connected, @@ -59,7 +60,9 @@ interface IState { // (which should be a single element) of other calls. // The primary will be the one not on hold, or an arbitrary one // if they're all on hold) -function getPrimarySecondaryCalls(calls: MatrixCall[]): [MatrixCall, MatrixCall[]] { +function getPrimarySecondaryCallsForPip(roomId: string): [MatrixCall, MatrixCall[]] { + const calls = CallHandler.sharedInstance().getAllActiveCallsForPip(roomId); + let primary: MatrixCall = null; let secondaries: MatrixCall[] = []; @@ -101,9 +104,7 @@ export default class CallPreview extends React.Component { const roomId = RoomViewStore.getRoomId(); - const [primaryCall, secondaryCalls] = getPrimarySecondaryCalls( - CallHandler.sharedInstance().getAllActiveCallsNotInRoom(roomId), - ); + const [primaryCall, secondaryCalls] = getPrimarySecondaryCallsForPip(roomId); this.state = { roomId, @@ -117,6 +118,10 @@ export default class CallPreview extends React.Component { this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); this.dispatcherRef = dis.register(this.onAction); MatrixClientPeg.get().on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); + const room = MatrixClientPeg.get()?.getRoom(this.state.roomId); + if (room) { + WidgetLayoutStore.instance.on(WidgetLayoutStore.emissionForRoom(room), this.updateCalls); + } } public componentWillUnmount() { @@ -127,18 +132,29 @@ export default class CallPreview extends React.Component { } dis.unregister(this.dispatcherRef); SettingsStore.unwatchSetting(this.settingsWatcherRef); + const room = MatrixClientPeg.get().getRoom(this.state.roomId); + WidgetLayoutStore.instance.off(WidgetLayoutStore.emissionForRoom(room), this.updateCalls); } private onRoomViewStoreUpdate = () => { - if (RoomViewStore.getRoomId() === this.state.roomId) return; - - const roomId = RoomViewStore.getRoomId(); - const [primaryCall, secondaryCalls] = getPrimarySecondaryCalls( - CallHandler.sharedInstance().getAllActiveCallsNotInRoom(roomId), - ); + const newRoomId = RoomViewStore.getRoomId(); + const oldRoomId = this.state.roomId; + if (newRoomId === oldRoomId) return; + // The WidgetLayoutStore observer always tracks the currently viewed Room, + // so we don't end up with multiple observers and know what observer to remove on unmount + const oldRoom = MatrixClientPeg.get()?.getRoom(oldRoomId); + if (oldRoom) { + WidgetLayoutStore.instance.off(WidgetLayoutStore.emissionForRoom(oldRoom), this.updateCalls); + } + const newRoom = MatrixClientPeg.get()?.getRoom(newRoomId); + if (newRoom) { + WidgetLayoutStore.instance.on(WidgetLayoutStore.emissionForRoom(newRoom), this.updateCalls); + } + if (!newRoomId) return; + const [primaryCall, secondaryCalls] = getPrimarySecondaryCallsForPip(newRoomId); this.setState({ - roomId, + roomId: newRoomId, primaryCall: primaryCall, secondaryCall: secondaryCalls[0], }); @@ -157,9 +173,8 @@ export default class CallPreview extends React.Component { }; private updateCalls = () => { - const [primaryCall, secondaryCalls] = getPrimarySecondaryCalls( - CallHandler.sharedInstance().getAllActiveCallsNotInRoom(this.state.roomId), - ); + if (!this.state.roomId) return; + const [primaryCall, secondaryCalls] = getPrimarySecondaryCallsForPip(this.state.roomId); this.setState({ primaryCall: primaryCall, @@ -168,9 +183,8 @@ export default class CallPreview extends React.Component { }; private onCallRemoteHold = () => { - const [primaryCall, secondaryCalls] = getPrimarySecondaryCalls( - CallHandler.sharedInstance().getAllActiveCallsNotInRoom(this.state.roomId), - ); + if (!this.state.roomId) return; + const [primaryCall, secondaryCalls] = getPrimarySecondaryCallsForPip(this.state.roomId); this.setState({ primaryCall: primaryCall,