Stop voice broadcast recording on redaction (#9455)

pull/28788/head^2
Michael Weimann 2022-10-19 18:02:48 +02:00 committed by GitHub
parent d5a4718d46
commit 07a1e9a009
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 30 deletions

View File

@ -20,7 +20,6 @@ import {
VoiceBroadcastInfoState, VoiceBroadcastInfoState,
VoiceBroadcastRecording, VoiceBroadcastRecording,
VoiceBroadcastRecordingEvent, VoiceBroadcastRecordingEvent,
VoiceBroadcastRecordingsStore,
} from ".."; } from "..";
import QuestionDialog from "../../components/views/dialogs/QuestionDialog"; import QuestionDialog from "../../components/views/dialogs/QuestionDialog";
import { useTypedEventEmitter } from "../../hooks/useEventEmitter"; import { useTypedEventEmitter } from "../../hooks/useEventEmitter";
@ -54,7 +53,6 @@ export const useVoiceBroadcastRecording = (recording: VoiceBroadcastRecording) =
if (confirmed) { if (confirmed) {
recording.stop(); recording.stop();
VoiceBroadcastRecordingsStore.instance().clearCurrent();
} }
}; };

View File

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClient, MatrixEvent, RelationType } from "matrix-js-sdk/src/matrix"; import { MatrixClient, MatrixEvent, MatrixEventEvent, RelationType } from "matrix-js-sdk/src/matrix";
import { TypedEventEmitter } from "matrix-js-sdk/src/models/typed-event-emitter"; import { TypedEventEmitter } from "matrix-js-sdk/src/models/typed-event-emitter";
import { import {
@ -67,6 +67,7 @@ export class VoiceBroadcastRecording
}) ? VoiceBroadcastInfoState.Started : VoiceBroadcastInfoState.Stopped; }) ? VoiceBroadcastInfoState.Started : VoiceBroadcastInfoState.Stopped;
// TODO Michael W: add listening for updates // TODO Michael W: add listening for updates
this.infoEvent.on(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);
this.dispatcherRef = dis.register(this.onAction); this.dispatcherRef = dis.register(this.onAction);
} }
@ -99,10 +100,19 @@ export class VoiceBroadcastRecording
this.recorder.stop(); this.recorder.stop();
} }
this.infoEvent.off(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);
this.removeAllListeners(); this.removeAllListeners();
dis.unregister(this.dispatcherRef); dis.unregister(this.dispatcherRef);
} }
private onBeforeRedaction = () => {
if (this.getState() !== VoiceBroadcastInfoState.Stopped) {
this.setState(VoiceBroadcastInfoState.Stopped);
// destroy cleans up everything
this.destroy();
}
};
private onAction = (payload: ActionPayload) => { private onAction = (payload: ActionPayload) => {
if (payload.action !== "call_state") return; if (payload.action !== "call_state") return;

View File

@ -17,7 +17,7 @@ limitations under the License.
import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { TypedEventEmitter } from "matrix-js-sdk/src/models/typed-event-emitter"; import { TypedEventEmitter } from "matrix-js-sdk/src/models/typed-event-emitter";
import { VoiceBroadcastRecording } from ".."; import { VoiceBroadcastInfoState, VoiceBroadcastRecording, VoiceBroadcastRecordingEvent } from "..";
export enum VoiceBroadcastRecordingsStoreEvent { export enum VoiceBroadcastRecordingsStoreEvent {
CurrentChanged = "current_changed", CurrentChanged = "current_changed",
@ -41,7 +41,12 @@ export class VoiceBroadcastRecordingsStore extends TypedEventEmitter<VoiceBroadc
public setCurrent(current: VoiceBroadcastRecording): void { public setCurrent(current: VoiceBroadcastRecording): void {
if (this.current === current) return; if (this.current === current) return;
if (this.current) {
this.current.off(VoiceBroadcastRecordingEvent.StateChanged, this.onCurrentStateChanged);
}
this.current = current; this.current = current;
this.current.on(VoiceBroadcastRecordingEvent.StateChanged, this.onCurrentStateChanged);
this.recordings.set(current.infoEvent.getId(), current); this.recordings.set(current.infoEvent.getId(), current);
this.emit(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, current); this.emit(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, current);
} }
@ -51,8 +56,9 @@ export class VoiceBroadcastRecordingsStore extends TypedEventEmitter<VoiceBroadc
} }
public clearCurrent(): void { public clearCurrent(): void {
if (this.current === null) return; if (!this.current) return;
this.current.off(VoiceBroadcastRecordingEvent.StateChanged, this.onCurrentStateChanged);
this.current = null; this.current = null;
this.emit(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, null); this.emit(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, null);
} }
@ -67,6 +73,12 @@ export class VoiceBroadcastRecordingsStore extends TypedEventEmitter<VoiceBroadc
return this.recordings.get(infoEventId); return this.recordings.get(infoEventId);
} }
private onCurrentStateChanged = (state: VoiceBroadcastInfoState) => {
if (state === VoiceBroadcastInfoState.Stopped) {
this.clearCurrent();
}
};
private static readonly cachedInstance = new VoiceBroadcastRecordingsStore(); private static readonly cachedInstance = new VoiceBroadcastRecordingsStore();
/** /**

View File

@ -20,6 +20,7 @@ import {
EventType, EventType,
MatrixClient, MatrixClient,
MatrixEvent, MatrixEvent,
MatrixEventEvent,
MsgType, MsgType,
RelationType, RelationType,
Room, Room,
@ -81,6 +82,7 @@ describe("VoiceBroadcastRecording", () => {
const setUpVoiceBroadcastRecording = () => { const setUpVoiceBroadcastRecording = () => {
voiceBroadcastRecording = new VoiceBroadcastRecording(infoEvent, client); voiceBroadcastRecording = new VoiceBroadcastRecording(infoEvent, client);
voiceBroadcastRecording.on(VoiceBroadcastRecordingEvent.StateChanged, onStateChanged); voiceBroadcastRecording.on(VoiceBroadcastRecordingEvent.StateChanged, onStateChanged);
jest.spyOn(voiceBroadcastRecording, "destroy");
jest.spyOn(voiceBroadcastRecording, "removeAllListeners"); jest.spyOn(voiceBroadcastRecording, "removeAllListeners");
}; };
@ -214,6 +216,18 @@ describe("VoiceBroadcastRecording", () => {
expect(voiceBroadcastRecorder.start).toHaveBeenCalled(); expect(voiceBroadcastRecorder.start).toHaveBeenCalled();
}); });
describe("and the info event is redacted", () => {
beforeEach(() => {
infoEvent.emit(MatrixEventEvent.BeforeRedaction, null, null);
});
itShouldBeInState(VoiceBroadcastInfoState.Stopped);
it("should destroy the recording", () => {
expect(voiceBroadcastRecording.destroy).toHaveBeenCalled();
});
});
describe("and receiving a call action", () => { describe("and receiving a call action", () => {
beforeEach(() => { beforeEach(() => {
dis.dispatch({ dis.dispatch({

View File

@ -18,28 +18,22 @@ import { mocked } from "jest-mock";
import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; import { MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
import { import {
VoiceBroadcastInfoEventType,
VoiceBroadcastRecordingsStore, VoiceBroadcastRecordingsStore,
VoiceBroadcastRecordingsStoreEvent, VoiceBroadcastRecordingsStoreEvent,
VoiceBroadcastRecording, VoiceBroadcastRecording,
VoiceBroadcastInfoState,
} from "../../../src/voice-broadcast"; } from "../../../src/voice-broadcast";
import { mkEvent, mkStubRoom, stubClient } from "../../test-utils"; import { mkStubRoom, stubClient } from "../../test-utils";
import { mkVoiceBroadcastInfoStateEvent } from "../utils/test-utils";
jest.mock("../../../src/voice-broadcast/models/VoiceBroadcastRecording.ts", () => ({
VoiceBroadcastRecording: jest.fn().mockImplementation(
(
infoEvent: MatrixEvent,
client: MatrixClient,
) => ({ infoEvent, client }),
),
}));
describe("VoiceBroadcastRecordingsStore", () => { describe("VoiceBroadcastRecordingsStore", () => {
const roomId = "!room:example.com"; const roomId = "!room:example.com";
let client: MatrixClient; let client: MatrixClient;
let room: Room; let room: Room;
let infoEvent: MatrixEvent; let infoEvent: MatrixEvent;
let otherInfoEvent: MatrixEvent;
let recording: VoiceBroadcastRecording; let recording: VoiceBroadcastRecording;
let otherRecording: VoiceBroadcastRecording;
let recordings: VoiceBroadcastRecordingsStore; let recordings: VoiceBroadcastRecordingsStore;
let onCurrentChanged: (recording: VoiceBroadcastRecording) => void; let onCurrentChanged: (recording: VoiceBroadcastRecording) => void;
@ -51,22 +45,17 @@ describe("VoiceBroadcastRecordingsStore", () => {
return room; return room;
} }
}); });
infoEvent = mkEvent({ infoEvent = mkVoiceBroadcastInfoStateEvent(roomId, VoiceBroadcastInfoState.Started, client.getUserId());
event: true, otherInfoEvent = mkVoiceBroadcastInfoStateEvent(roomId, VoiceBroadcastInfoState.Started, client.getUserId());
type: VoiceBroadcastInfoEventType, recording = new VoiceBroadcastRecording(infoEvent, client);
user: client.getUserId(), otherRecording = new VoiceBroadcastRecording(otherInfoEvent, client);
room: roomId,
content: {},
});
recording = {
infoEvent,
} as unknown as VoiceBroadcastRecording;
recordings = new VoiceBroadcastRecordingsStore(); recordings = new VoiceBroadcastRecordingsStore();
onCurrentChanged = jest.fn(); onCurrentChanged = jest.fn();
recordings.on(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, onCurrentChanged); recordings.on(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, onCurrentChanged);
}); });
afterEach(() => { afterEach(() => {
recording.destroy();
recordings.off(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, onCurrentChanged); recordings.off(VoiceBroadcastRecordingsStoreEvent.CurrentChanged, onCurrentChanged);
}); });
@ -110,6 +99,32 @@ describe("VoiceBroadcastRecordingsStore", () => {
it("should emit a current changed event", () => { it("should emit a current changed event", () => {
expect(onCurrentChanged).toHaveBeenCalledWith(null); expect(onCurrentChanged).toHaveBeenCalledWith(null);
}); });
it("and calling it again should work", () => {
recordings.clearCurrent();
expect(recordings.getCurrent()).toBeNull();
});
});
describe("and setting another recording and stopping the previous recording", () => {
beforeEach(() => {
recordings.setCurrent(otherRecording);
recording.stop();
});
it("should keep the current recording", () => {
expect(recordings.getCurrent()).toBe(otherRecording);
});
});
describe("and the recording stops", () => {
beforeEach(() => {
recording.stop();
});
it("should clear the current recording", () => {
expect(recordings.getCurrent()).toBeNull();
});
}); });
}); });
@ -133,10 +148,7 @@ describe("VoiceBroadcastRecordingsStore", () => {
}); });
it("should return the recording", () => { it("should return the recording", () => {
expect(returnedRecording).toEqual({ expect(returnedRecording.infoEvent).toBe(infoEvent);
infoEvent,
client,
});
}); });
}); });
}); });