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

Commit 07a1e9a

Browse files
authored
Stop voice broadcast recording on redaction (#9455)
1 parent d5a4718 commit 07a1e9a

File tree

5 files changed

+76
-30
lines changed

5 files changed

+76
-30
lines changed

src/voice-broadcast/hooks/useVoiceBroadcastRecording.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import {
2020
VoiceBroadcastInfoState,
2121
VoiceBroadcastRecording,
2222
VoiceBroadcastRecordingEvent,
23-
VoiceBroadcastRecordingsStore,
2423
} from "..";
2524
import QuestionDialog from "../../components/views/dialogs/QuestionDialog";
2625
import { useTypedEventEmitter } from "../../hooks/useEventEmitter";
@@ -54,7 +53,6 @@ export const useVoiceBroadcastRecording = (recording: VoiceBroadcastRecording) =
5453

5554
if (confirmed) {
5655
recording.stop();
57-
VoiceBroadcastRecordingsStore.instance().clearCurrent();
5856
}
5957
};
6058

src/voice-broadcast/models/VoiceBroadcastRecording.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ limitations under the License.
1515
*/
1616

1717
import { logger } from "matrix-js-sdk/src/logger";
18-
import { MatrixClient, MatrixEvent, RelationType } from "matrix-js-sdk/src/matrix";
18+
import { MatrixClient, MatrixEvent, MatrixEventEvent, RelationType } from "matrix-js-sdk/src/matrix";
1919
import { TypedEventEmitter } from "matrix-js-sdk/src/models/typed-event-emitter";
2020

2121
import {
@@ -67,6 +67,7 @@ export class VoiceBroadcastRecording
6767
}) ? VoiceBroadcastInfoState.Started : VoiceBroadcastInfoState.Stopped;
6868
// TODO Michael W: add listening for updates
6969

70+
this.infoEvent.on(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);
7071
this.dispatcherRef = dis.register(this.onAction);
7172
}
7273

@@ -99,10 +100,19 @@ export class VoiceBroadcastRecording
99100
this.recorder.stop();
100101
}
101102

103+
this.infoEvent.off(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);
102104
this.removeAllListeners();
103105
dis.unregister(this.dispatcherRef);
104106
}
105107

108+
private onBeforeRedaction = () => {
109+
if (this.getState() !== VoiceBroadcastInfoState.Stopped) {
110+
this.setState(VoiceBroadcastInfoState.Stopped);
111+
// destroy cleans up everything
112+
this.destroy();
113+
}
114+
};
115+
106116
private onAction = (payload: ActionPayload) => {
107117
if (payload.action !== "call_state") return;
108118

src/voice-broadcast/stores/VoiceBroadcastRecordingsStore.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ limitations under the License.
1717
import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
1818
import { TypedEventEmitter } from "matrix-js-sdk/src/models/typed-event-emitter";
1919

20-
import { VoiceBroadcastRecording } from "..";
20+
import { VoiceBroadcastInfoState, VoiceBroadcastRecording, VoiceBroadcastRecordingEvent } from "..";
2121

2222
export enum VoiceBroadcastRecordingsStoreEvent {
2323
CurrentChanged = "current_changed",
@@ -41,7 +41,12 @@ export class VoiceBroadcastRecordingsStore extends TypedEventEmitter<VoiceBroadc
4141
public setCurrent(current: VoiceBroadcastRecording): void {
4242
if (this.current === current) return;
4343

44+
if (this.current) {
45+
this.current.off(VoiceBroadcastRecordingEvent.StateChanged, this.onCurrentStateChanged);
46+
}
47+
4448
this.current = current;
49+
this.current.on(VoiceBroadcastRecordingEvent.StateChanged, this.onCurrentStateChanged);
4550
this.recordings.set(current.infoEvent.getId(), current);
4651
this.emit(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, current);
4752
}
@@ -51,8 +56,9 @@ export class VoiceBroadcastRecordingsStore extends TypedEventEmitter<VoiceBroadc
5156
}
5257

5358
public clearCurrent(): void {
54-
if (this.current === null) return;
59+
if (!this.current) return;
5560

61+
this.current.off(VoiceBroadcastRecordingEvent.StateChanged, this.onCurrentStateChanged);
5662
this.current = null;
5763
this.emit(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, null);
5864
}
@@ -67,6 +73,12 @@ export class VoiceBroadcastRecordingsStore extends TypedEventEmitter<VoiceBroadc
6773
return this.recordings.get(infoEventId);
6874
}
6975

76+
private onCurrentStateChanged = (state: VoiceBroadcastInfoState) => {
77+
if (state === VoiceBroadcastInfoState.Stopped) {
78+
this.clearCurrent();
79+
}
80+
};
81+
7082
private static readonly cachedInstance = new VoiceBroadcastRecordingsStore();
7183

7284
/**

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
EventType,
2121
MatrixClient,
2222
MatrixEvent,
23+
MatrixEventEvent,
2324
MsgType,
2425
RelationType,
2526
Room,
@@ -81,6 +82,7 @@ describe("VoiceBroadcastRecording", () => {
8182
const setUpVoiceBroadcastRecording = () => {
8283
voiceBroadcastRecording = new VoiceBroadcastRecording(infoEvent, client);
8384
voiceBroadcastRecording.on(VoiceBroadcastRecordingEvent.StateChanged, onStateChanged);
85+
jest.spyOn(voiceBroadcastRecording, "destroy");
8486
jest.spyOn(voiceBroadcastRecording, "removeAllListeners");
8587
};
8688

@@ -214,6 +216,18 @@ describe("VoiceBroadcastRecording", () => {
214216
expect(voiceBroadcastRecorder.start).toHaveBeenCalled();
215217
});
216218

219+
describe("and the info event is redacted", () => {
220+
beforeEach(() => {
221+
infoEvent.emit(MatrixEventEvent.BeforeRedaction, null, null);
222+
});
223+
224+
itShouldBeInState(VoiceBroadcastInfoState.Stopped);
225+
226+
it("should destroy the recording", () => {
227+
expect(voiceBroadcastRecording.destroy).toHaveBeenCalled();
228+
});
229+
});
230+
217231
describe("and receiving a call action", () => {
218232
beforeEach(() => {
219233
dis.dispatch({

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

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,22 @@ import { mocked } from "jest-mock";
1818
import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
1919

2020
import {
21-
VoiceBroadcastInfoEventType,
2221
VoiceBroadcastRecordingsStore,
2322
VoiceBroadcastRecordingsStoreEvent,
2423
VoiceBroadcastRecording,
24+
VoiceBroadcastInfoState,
2525
} from "../../../src/voice-broadcast";
26-
import { mkEvent, mkStubRoom, stubClient } from "../../test-utils";
27-
28-
jest.mock("../../../src/voice-broadcast/models/VoiceBroadcastRecording.ts", () => ({
29-
VoiceBroadcastRecording: jest.fn().mockImplementation(
30-
(
31-
infoEvent: MatrixEvent,
32-
client: MatrixClient,
33-
) => ({ infoEvent, client }),
34-
),
35-
}));
26+
import { mkStubRoom, stubClient } from "../../test-utils";
27+
import { mkVoiceBroadcastInfoStateEvent } from "../utils/test-utils";
3628

3729
describe("VoiceBroadcastRecordingsStore", () => {
3830
const roomId = "!room:example.com";
3931
let client: MatrixClient;
4032
let room: Room;
4133
let infoEvent: MatrixEvent;
34+
let otherInfoEvent: MatrixEvent;
4235
let recording: VoiceBroadcastRecording;
36+
let otherRecording: VoiceBroadcastRecording;
4337
let recordings: VoiceBroadcastRecordingsStore;
4438
let onCurrentChanged: (recording: VoiceBroadcastRecording) => void;
4539

@@ -51,22 +45,17 @@ describe("VoiceBroadcastRecordingsStore", () => {
5145
return room;
5246
}
5347
});
54-
infoEvent = mkEvent({
55-
event: true,
56-
type: VoiceBroadcastInfoEventType,
57-
user: client.getUserId(),
58-
room: roomId,
59-
content: {},
60-
});
61-
recording = {
62-
infoEvent,
63-
} as unknown as VoiceBroadcastRecording;
48+
infoEvent = mkVoiceBroadcastInfoStateEvent(roomId, VoiceBroadcastInfoState.Started, client.getUserId());
49+
otherInfoEvent = mkVoiceBroadcastInfoStateEvent(roomId, VoiceBroadcastInfoState.Started, client.getUserId());
50+
recording = new VoiceBroadcastRecording(infoEvent, client);
51+
otherRecording = new VoiceBroadcastRecording(otherInfoEvent, client);
6452
recordings = new VoiceBroadcastRecordingsStore();
6553
onCurrentChanged = jest.fn();
6654
recordings.on(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, onCurrentChanged);
6755
});
6856

6957
afterEach(() => {
58+
recording.destroy();
7059
recordings.off(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, onCurrentChanged);
7160
});
7261

@@ -110,6 +99,32 @@ describe("VoiceBroadcastRecordingsStore", () => {
11099
it("should emit a current changed event", () => {
111100
expect(onCurrentChanged).toHaveBeenCalledWith(null);
112101
});
102+
103+
it("and calling it again should work", () => {
104+
recordings.clearCurrent();
105+
expect(recordings.getCurrent()).toBeNull();
106+
});
107+
});
108+
109+
describe("and setting another recording and stopping the previous recording", () => {
110+
beforeEach(() => {
111+
recordings.setCurrent(otherRecording);
112+
recording.stop();
113+
});
114+
115+
it("should keep the current recording", () => {
116+
expect(recordings.getCurrent()).toBe(otherRecording);
117+
});
118+
});
119+
120+
describe("and the recording stops", () => {
121+
beforeEach(() => {
122+
recording.stop();
123+
});
124+
125+
it("should clear the current recording", () => {
126+
expect(recordings.getCurrent()).toBeNull();
127+
});
113128
});
114129
});
115130

@@ -133,10 +148,7 @@ describe("VoiceBroadcastRecordingsStore", () => {
133148
});
134149

135150
it("should return the recording", () => {
136-
expect(returnedRecording).toEqual({
137-
infoEvent,
138-
client,
139-
});
151+
expect(returnedRecording.infoEvent).toBe(infoEvent);
140152
});
141153
});
142154
});

0 commit comments

Comments
 (0)