diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index 0d04bd1597..de8cc70efd 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -57,6 +57,7 @@ import { } from "../voice-broadcast"; import { IRoomStateEventsActionPayload } from "../actions/MatrixActionCreators"; import { showCantStartACallDialog } from "../voice-broadcast/utils/showCantStartACallDialog"; +import { pauseNonLiveBroadcastFromOtherRoom } from "../voice-broadcast/utils/pauseNonLiveBroadcastFromOtherRoom"; const NUM_JOIN_RETRY = 5; @@ -445,6 +446,7 @@ export class RoomViewStore extends EventEmitter { } if (room) { + pauseNonLiveBroadcastFromOtherRoom(room, this.stores.voiceBroadcastPlaybacksStore); this.doMaybeSetCurrentVoiceBroadcastPlayback(room); } } else if (payload.room_alias) { diff --git a/src/voice-broadcast/stores/VoiceBroadcastPlaybacksStore.ts b/src/voice-broadcast/stores/VoiceBroadcastPlaybacksStore.ts index 57f944b45b..4e92524025 100644 --- a/src/voice-broadcast/stores/VoiceBroadcastPlaybacksStore.ts +++ b/src/voice-broadcast/stores/VoiceBroadcastPlaybacksStore.ts @@ -37,7 +37,7 @@ export class VoiceBroadcastPlaybacksStore extends TypedEventEmitter implements IDestroyable { - private current: VoiceBroadcastPlayback | null; + private current: VoiceBroadcastPlayback | null = null; /** Playbacks indexed by their info event id. */ private playbacks = new Map(); diff --git a/src/voice-broadcast/utils/pauseNonLiveBroadcastFromOtherRoom.ts b/src/voice-broadcast/utils/pauseNonLiveBroadcastFromOtherRoom.ts new file mode 100644 index 0000000000..3af24a0c31 --- /dev/null +++ b/src/voice-broadcast/utils/pauseNonLiveBroadcastFromOtherRoom.ts @@ -0,0 +1,37 @@ +/* +Copyright 2022 The 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 { Room } from "matrix-js-sdk/src/matrix"; + +import { VoiceBroadcastPlaybacksStore } from ".."; + +export const pauseNonLiveBroadcastFromOtherRoom = ( + room: Room, + voiceBroadcastPlaybacksStore: VoiceBroadcastPlaybacksStore, +): void => { + const playingBroadcast = voiceBroadcastPlaybacksStore.getCurrent(); + + if ( + !playingBroadcast || + playingBroadcast?.getLiveness() === "live" || + playingBroadcast?.infoEvent.getRoomId() === room.roomId + ) { + return; + } + + voiceBroadcastPlaybacksStore.clearCurrent(); + playingBroadcast.pause(); +}; diff --git a/test/voice-broadcast/utils/pauseNonLiveBroadcastFromOtherRoom-test.ts b/test/voice-broadcast/utils/pauseNonLiveBroadcastFromOtherRoom-test.ts new file mode 100644 index 0000000000..1aba3a6b11 --- /dev/null +++ b/test/voice-broadcast/utils/pauseNonLiveBroadcastFromOtherRoom-test.ts @@ -0,0 +1,103 @@ +/* +Copyright 2022 The 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 { MatrixClient, Room } from "matrix-js-sdk/src/matrix"; + +import { + VoiceBroadcastInfoState, + VoiceBroadcastPlayback, + VoiceBroadcastPlaybacksStore, +} from "../../../src/voice-broadcast"; +import { pauseNonLiveBroadcastFromOtherRoom } from "../../../src/voice-broadcast/utils/pauseNonLiveBroadcastFromOtherRoom"; +import { stubClient } from "../../test-utils"; +import { mkVoiceBroadcastInfoStateEvent } from "./test-utils"; + +describe("pauseNonLiveBroadcastFromOtherRoom", () => { + const roomId = "!room:example.com"; + const roomId2 = "!room2@example.com"; + let room: Room; + let client: MatrixClient; + let playback: VoiceBroadcastPlayback; + let playbacks: VoiceBroadcastPlaybacksStore; + + const mkPlayback = (infoState: VoiceBroadcastInfoState, roomId: string): VoiceBroadcastPlayback => { + const infoEvent = mkVoiceBroadcastInfoStateEvent( + roomId, + infoState, + client.getSafeUserId(), + client.getDeviceId()!, + ); + const playback = new VoiceBroadcastPlayback(infoEvent, client); + jest.spyOn(playback, "pause"); + playbacks.setCurrent(playback); + return playback; + }; + + beforeEach(() => { + client = stubClient(); + room = new Room(roomId, client, client.getSafeUserId()); + playbacks = new VoiceBroadcastPlaybacksStore(); + jest.spyOn(playbacks, "clearCurrent"); + }); + + afterEach(() => { + playback?.destroy(); + playbacks.destroy(); + }); + + describe("when there is no current playback", () => { + it("should not clear the current playback", () => { + pauseNonLiveBroadcastFromOtherRoom(room, playbacks); + expect(playbacks.clearCurrent).not.toHaveBeenCalled(); + }); + }); + + describe("when listening to a live broadcast in another room", () => { + beforeEach(() => { + playback = mkPlayback(VoiceBroadcastInfoState.Started, roomId2); + }); + + it("should not clear current / pause the playback", () => { + pauseNonLiveBroadcastFromOtherRoom(room, playbacks); + expect(playbacks.clearCurrent).not.toHaveBeenCalled(); + expect(playback.pause).not.toHaveBeenCalled(); + }); + }); + + describe("when listening to a non-live broadcast in the same room", () => { + beforeEach(() => { + playback = mkPlayback(VoiceBroadcastInfoState.Stopped, roomId); + }); + + it("should not clear current / pause the playback", () => { + pauseNonLiveBroadcastFromOtherRoom(room, playbacks); + expect(playbacks.clearCurrent).not.toHaveBeenCalled(); + expect(playback.pause).not.toHaveBeenCalled(); + }); + }); + + describe("when listening to a non-live broadcast in another room", () => { + beforeEach(() => { + playback = mkPlayback(VoiceBroadcastInfoState.Stopped, roomId2); + }); + + it("should clear current and pause the playback", () => { + pauseNonLiveBroadcastFromOtherRoom(room, playbacks); + expect(playbacks.getCurrent()).toBeNull(); + expect(playback.pause).toHaveBeenCalled(); + }); + }); +});