Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit f4b6719

Browse files
[Backport staging] Start voice broadcast recording while listening (#9659)
Co-authored-by: Michael Weimann <[email protected]>
1 parent 1216580 commit f4b6719

File tree

11 files changed

+135
-40
lines changed

11 files changed

+135
-40
lines changed

src/components/views/rooms/MessageComposer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ export class MessageComposer extends React.Component<IProps, IState> {
584584
setUpVoiceBroadcastPreRecording(
585585
this.props.room,
586586
MatrixClientPeg.get(),
587+
SdkContextClass.instance.voiceBroadcastPlaybacksStore,
587588
VoiceBroadcastRecordingsStore.instance(),
588589
SdkContextClass.instance.voiceBroadcastPreRecordingStore,
589590
);

src/components/views/voip/PipView.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,14 +367,14 @@ class PipView extends React.Component<IProps, IState> {
367367
const pipMode = true;
368368
let pipContent: CreatePipChildren | null = null;
369369

370-
if (this.props.voiceBroadcastPreRecording) {
371-
pipContent = this.createVoiceBroadcastPreRecordingPipContent(this.props.voiceBroadcastPreRecording);
372-
}
373-
374370
if (this.props.voiceBroadcastPlayback) {
375371
pipContent = this.createVoiceBroadcastPlaybackPipContent(this.props.voiceBroadcastPlayback);
376372
}
377373

374+
if (this.props.voiceBroadcastPreRecording) {
375+
pipContent = this.createVoiceBroadcastPreRecordingPipContent(this.props.voiceBroadcastPreRecording);
376+
}
377+
378378
if (this.props.voiceBroadcastRecording) {
379379
pipContent = this.createVoiceBroadcastRecordingPipContent(this.props.voiceBroadcastRecording);
380380
}

src/voice-broadcast/models/VoiceBroadcastPreRecording.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { MatrixClient, Room, RoomMember } from "matrix-js-sdk/src/matrix";
1818
import { TypedEventEmitter } from "matrix-js-sdk/src/models/typed-event-emitter";
1919

2020
import { IDestroyable } from "../../utils/IDestroyable";
21+
import { VoiceBroadcastPlaybacksStore } from "../stores/VoiceBroadcastPlaybacksStore";
2122
import { VoiceBroadcastRecordingsStore } from "../stores/VoiceBroadcastRecordingsStore";
2223
import { startNewVoiceBroadcastRecording } from "../utils/startNewVoiceBroadcastRecording";
2324

@@ -34,6 +35,7 @@ export class VoiceBroadcastPreRecording
3435
public room: Room,
3536
public sender: RoomMember,
3637
private client: MatrixClient,
38+
private playbacksStore: VoiceBroadcastPlaybacksStore,
3739
private recordingsStore: VoiceBroadcastRecordingsStore,
3840
) {
3941
super();
@@ -43,6 +45,7 @@ export class VoiceBroadcastPreRecording
4345
await startNewVoiceBroadcastRecording(
4446
this.room,
4547
this.client,
48+
this.playbacksStore,
4649
this.recordingsStore,
4750
);
4851
this.emit("dismiss", this);

src/voice-broadcast/utils/setUpVoiceBroadcastPreRecording.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
1818

1919
import {
2020
checkVoiceBroadcastPreConditions,
21+
VoiceBroadcastPlaybacksStore,
2122
VoiceBroadcastPreRecording,
2223
VoiceBroadcastPreRecordingStore,
2324
VoiceBroadcastRecordingsStore,
@@ -26,6 +27,7 @@ import {
2627
export const setUpVoiceBroadcastPreRecording = (
2728
room: Room,
2829
client: MatrixClient,
30+
playbacksStore: VoiceBroadcastPlaybacksStore,
2931
recordingsStore: VoiceBroadcastRecordingsStore,
3032
preRecordingStore: VoiceBroadcastPreRecordingStore,
3133
): VoiceBroadcastPreRecording | null => {
@@ -39,7 +41,11 @@ export const setUpVoiceBroadcastPreRecording = (
3941
const sender = room.getMember(userId);
4042
if (!sender) return null;
4143

42-
const preRecording = new VoiceBroadcastPreRecording(room, sender, client, recordingsStore);
44+
// pause and clear current playback (if any)
45+
playbacksStore.getCurrent()?.pause();
46+
playbacksStore.clearCurrent();
47+
48+
const preRecording = new VoiceBroadcastPreRecording(room, sender, client, playbacksStore, recordingsStore);
4349
preRecordingStore.setCurrent(preRecording);
4450
return preRecording;
4551
};

src/voice-broadcast/utils/startNewVoiceBroadcastRecording.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
VoiceBroadcastRecordingsStore,
2525
VoiceBroadcastRecording,
2626
getChunkLength,
27+
VoiceBroadcastPlaybacksStore,
2728
} from "..";
2829
import { checkVoiceBroadcastPreConditions } from "./checkVoiceBroadcastPreConditions";
2930

@@ -80,17 +81,23 @@ const startBroadcast = async (
8081
/**
8182
* Starts a new Voice Broadcast Recording, if
8283
* - the user has the permissions to do so in the room
84+
* - the user is not already recording a voice broadcast
8385
* - there is no other broadcast being recorded in the room, yet
8486
* Sends a voice_broadcast_info state event and waits for the event to actually appear in the room state.
8587
*/
8688
export const startNewVoiceBroadcastRecording = async (
8789
room: Room,
8890
client: MatrixClient,
91+
playbacksStore: VoiceBroadcastPlaybacksStore,
8992
recordingsStore: VoiceBroadcastRecordingsStore,
9093
): Promise<VoiceBroadcastRecording | null> => {
9194
if (!checkVoiceBroadcastPreConditions(room, client, recordingsStore)) {
9295
return null;
9396
}
9497

98+
// pause and clear current playback (if any)
99+
playbacksStore.getCurrent()?.pause();
100+
playbacksStore.clearCurrent();
101+
95102
return startBroadcast(room, client, recordingsStore);
96103
};

test/components/views/voip/PipView-test.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ describe("PipView", () => {
184184
room,
185185
alice,
186186
client,
187+
voiceBroadcastPlaybacksStore,
187188
voiceBroadcastRecordingsStore,
188189
);
189190
voiceBroadcastPreRecordingStore.setCurrent(voiceBroadcastPreRecording);
@@ -271,6 +272,19 @@ describe("PipView", () => {
271272
});
272273
});
273274

275+
describe("when there is a voice broadcast playback and pre-recording", () => {
276+
beforeEach(() => {
277+
startVoiceBroadcastPlayback(room);
278+
setUpVoiceBroadcastPreRecording();
279+
renderPip();
280+
});
281+
282+
it("should render the voice broadcast pre-recording PiP", () => {
283+
// check for the „Go live“ button
284+
expect(screen.queryByText("Go live")).toBeInTheDocument();
285+
});
286+
});
287+
274288
describe("when there is a voice broadcast pre-recording", () => {
275289
beforeEach(() => {
276290
setUpVoiceBroadcastPreRecording();

test/voice-broadcast/components/molecules/VoiceBroadcastPreRecordingPip-test.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { act, render, RenderResult, screen } from "@testing-library/react";
2121
import userEvent from "@testing-library/user-event";
2222

2323
import {
24+
VoiceBroadcastPlaybacksStore,
2425
VoiceBroadcastPreRecording,
2526
VoiceBroadcastPreRecordingPip,
2627
VoiceBroadcastRecordingsStore,
@@ -42,6 +43,7 @@ jest.mock("../../../../src/components/views/avatars/RoomAvatar", () => ({
4243
describe("VoiceBroadcastPreRecordingPip", () => {
4344
let renderResult: RenderResult;
4445
let preRecording: VoiceBroadcastPreRecording;
46+
let playbacksStore: VoiceBroadcastPlaybacksStore;
4547
let recordingsStore: VoiceBroadcastRecordingsStore;
4648
let client: MatrixClient;
4749
let room: Room;
@@ -51,6 +53,7 @@ describe("VoiceBroadcastPreRecordingPip", () => {
5153
client = stubClient();
5254
room = new Room("[email protected]", client, client.getUserId() || "");
5355
sender = new RoomMember(room.roomId, client.getUserId() || "");
56+
playbacksStore = new VoiceBroadcastPlaybacksStore();
5457
recordingsStore = new VoiceBroadcastRecordingsStore();
5558
mocked(requestMediaPermissions).mockReturnValue(new Promise<MediaStream>((r) => {
5659
r({
@@ -76,6 +79,7 @@ describe("VoiceBroadcastPreRecordingPip", () => {
7679
room,
7780
sender,
7881
client,
82+
playbacksStore,
7983
recordingsStore,
8084
);
8185
});

test/voice-broadcast/models/VoiceBroadcastPreRecording-test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { MatrixClient, Room, RoomMember } from "matrix-js-sdk/src/matrix";
1818

1919
import {
2020
startNewVoiceBroadcastRecording,
21+
VoiceBroadcastPlaybacksStore,
2122
VoiceBroadcastPreRecording,
2223
VoiceBroadcastRecordingsStore,
2324
} from "../../../src/voice-broadcast";
@@ -30,6 +31,7 @@ describe("VoiceBroadcastPreRecording", () => {
3031
let client: MatrixClient;
3132
let room: Room;
3233
let sender: RoomMember;
34+
let playbacksStore: VoiceBroadcastPlaybacksStore;
3335
let recordingsStore: VoiceBroadcastRecordingsStore;
3436
let preRecording: VoiceBroadcastPreRecording;
3537
let onDismiss: (voiceBroadcastPreRecording: VoiceBroadcastPreRecording) => void;
@@ -38,12 +40,13 @@ describe("VoiceBroadcastPreRecording", () => {
3840
client = stubClient();
3941
room = new Room(roomId, client, client.getUserId() || "");
4042
sender = new RoomMember(roomId, client.getUserId() || "");
43+
playbacksStore = new VoiceBroadcastPlaybacksStore();
4144
recordingsStore = new VoiceBroadcastRecordingsStore();
4245
});
4346

4447
beforeEach(() => {
4548
onDismiss = jest.fn();
46-
preRecording = new VoiceBroadcastPreRecording(room, sender, client, recordingsStore);
49+
preRecording = new VoiceBroadcastPreRecording(room, sender, client, playbacksStore, recordingsStore);
4750
preRecording.on("dismiss", onDismiss);
4851
});
4952

@@ -56,6 +59,7 @@ describe("VoiceBroadcastPreRecording", () => {
5659
expect(startNewVoiceBroadcastRecording).toHaveBeenCalledWith(
5760
room,
5861
client,
62+
playbacksStore,
5963
recordingsStore,
6064
);
6165
});

test/voice-broadcast/stores/VoiceBroadcastPreRecordingStore-test.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { mocked } from "jest-mock";
1818
import { MatrixClient, Room, RoomMember } from "matrix-js-sdk/src/matrix";
1919

2020
import {
21+
VoiceBroadcastPlaybacksStore,
2122
VoiceBroadcastPreRecording,
2223
VoiceBroadcastPreRecordingStore,
2324
VoiceBroadcastRecordingsStore,
@@ -31,6 +32,7 @@ describe("VoiceBroadcastPreRecordingStore", () => {
3132
let client: MatrixClient;
3233
let room: Room;
3334
let sender: RoomMember;
35+
let playbacksStore: VoiceBroadcastPlaybacksStore;
3436
let recordingsStore: VoiceBroadcastRecordingsStore;
3537
let store: VoiceBroadcastPreRecordingStore;
3638
let preRecording1: VoiceBroadcastPreRecording;
@@ -39,14 +41,15 @@ describe("VoiceBroadcastPreRecordingStore", () => {
3941
client = stubClient();
4042
room = new Room(roomId, client, client.getUserId() || "");
4143
sender = new RoomMember(roomId, client.getUserId() || "");
44+
playbacksStore = new VoiceBroadcastPlaybacksStore();
4245
recordingsStore = new VoiceBroadcastRecordingsStore();
4346
});
4447

4548
beforeEach(() => {
4649
store = new VoiceBroadcastPreRecordingStore();
4750
jest.spyOn(store, "emit");
4851
jest.spyOn(store, "removeAllListeners");
49-
preRecording1 = new VoiceBroadcastPreRecording(room, sender, client, recordingsStore);
52+
preRecording1 = new VoiceBroadcastPreRecording(room, sender, client, playbacksStore, recordingsStore);
5053
jest.spyOn(preRecording1, "off");
5154
});
5255

@@ -117,7 +120,7 @@ describe("VoiceBroadcastPreRecordingStore", () => {
117120
beforeEach(() => {
118121
mocked(store.emit).mockClear();
119122
mocked(preRecording1.off).mockClear();
120-
preRecording2 = new VoiceBroadcastPreRecording(room, sender, client, recordingsStore);
123+
preRecording2 = new VoiceBroadcastPreRecording(room, sender, client, playbacksStore, recordingsStore);
121124
store.setCurrent(preRecording2);
122125
});
123126

test/voice-broadcast/utils/setUpVoiceBroadcastPreRecording-test.ts

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,20 @@ limitations under the License.
1515
*/
1616

1717
import { mocked } from "jest-mock";
18-
import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
18+
import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
1919

2020
import {
2121
checkVoiceBroadcastPreConditions,
22+
VoiceBroadcastInfoState,
23+
VoiceBroadcastPlayback,
24+
VoiceBroadcastPlaybacksStore,
2225
VoiceBroadcastPreRecording,
2326
VoiceBroadcastPreRecordingStore,
2427
VoiceBroadcastRecordingsStore,
2528
} from "../../../src/voice-broadcast";
2629
import { setUpVoiceBroadcastPreRecording } from "../../../src/voice-broadcast/utils/setUpVoiceBroadcastPreRecording";
2730
import { mkRoomMemberJoinEvent, stubClient } from "../../test-utils";
31+
import { mkVoiceBroadcastInfoStateEvent } from "./test-utils";
2832

2933
jest.mock("../../../src/voice-broadcast/utils/checkVoiceBroadcastPreConditions");
3034

@@ -34,11 +38,20 @@ describe("setUpVoiceBroadcastPreRecording", () => {
3438
let userId: string;
3539
let room: Room;
3640
let preRecordingStore: VoiceBroadcastPreRecordingStore;
41+
let infoEvent: MatrixEvent;
42+
let playback: VoiceBroadcastPlayback;
43+
let playbacksStore: VoiceBroadcastPlaybacksStore;
3744
let recordingsStore: VoiceBroadcastRecordingsStore;
3845

3946
const itShouldReturnNull = () => {
4047
it("should return null", () => {
41-
expect(setUpVoiceBroadcastPreRecording(room, client, recordingsStore, preRecordingStore)).toBeNull();
48+
expect(setUpVoiceBroadcastPreRecording(
49+
room,
50+
client,
51+
playbacksStore,
52+
recordingsStore,
53+
preRecordingStore,
54+
)).toBeNull();
4255
expect(checkVoiceBroadcastPreConditions).toHaveBeenCalledWith(room, client, recordingsStore);
4356
});
4457
};
@@ -51,7 +64,16 @@ describe("setUpVoiceBroadcastPreRecording", () => {
5164
userId = clientUserId;
5265

5366
room = new Room(roomId, client, userId);
67+
infoEvent = mkVoiceBroadcastInfoStateEvent(
68+
roomId,
69+
VoiceBroadcastInfoState.Started,
70+
client.getUserId()!,
71+
client.getDeviceId()!,
72+
);
5473
preRecordingStore = new VoiceBroadcastPreRecordingStore();
74+
playback = new VoiceBroadcastPlayback(infoEvent, client);
75+
jest.spyOn(playback, "pause");
76+
playbacksStore = new VoiceBroadcastPlaybacksStore();
5577
recordingsStore = new VoiceBroadcastRecordingsStore();
5678
});
5779

@@ -85,15 +107,25 @@ describe("setUpVoiceBroadcastPreRecording", () => {
85107
itShouldReturnNull();
86108
});
87109

88-
describe("and there is a room member", () => {
110+
describe("and there is a room member and listening to another broadcast", () => {
89111
beforeEach(() => {
112+
playbacksStore.setCurrent(playback);
90113
room.currentState.setStateEvents([
91114
mkRoomMemberJoinEvent(userId, roomId),
92115
]);
93116
});
94117

95-
it("should create a voice broadcast pre-recording", () => {
96-
const result = setUpVoiceBroadcastPreRecording(room, client, recordingsStore, preRecordingStore);
118+
it("should pause the current playback and create a voice broadcast pre-recording", () => {
119+
const result = setUpVoiceBroadcastPreRecording(
120+
room,
121+
client,
122+
playbacksStore,
123+
recordingsStore,
124+
preRecordingStore,
125+
);
126+
expect(playback.pause).toHaveBeenCalled();
127+
expect(playbacksStore.getCurrent()).toBeNull();
128+
97129
expect(checkVoiceBroadcastPreConditions).toHaveBeenCalledWith(room, client, recordingsStore);
98130
expect(result).toBeInstanceOf(VoiceBroadcastPreRecording);
99131
});

0 commit comments

Comments
 (0)