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

Commit 3214085

Browse files
authored
When deleting a voice broadcast, also delete related events (#9737)
1 parent a2777d3 commit 3214085

File tree

5 files changed

+178
-3
lines changed

5 files changed

+178
-3
lines changed

src/components/views/dialogs/ConfirmRedactDialog.tsx

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
17+
import { Feature, ServerSupport } from "matrix-js-sdk/src/feature";
18+
import { MatrixEvent, RelationType } from "matrix-js-sdk/src/matrix";
1819
import React from "react";
1920

2021
import { _t } from "../../../languageHandler";
2122
import { MatrixClientPeg } from "../../../MatrixClientPeg";
2223
import Modal from "../../../Modal";
24+
import { isVoiceBroadcastStartedEvent } from "../../../voice-broadcast/utils/isVoiceBroadcastStartedEvent";
2325
import ErrorDialog from "./ErrorDialog";
2426
import TextInputDialog from "./TextInputDialog";
2527

@@ -55,17 +57,42 @@ export function createRedactEventDialog({
5557
mxEvent: MatrixEvent;
5658
onCloseDialog?: () => void;
5759
}) {
60+
const eventId = mxEvent.getId();
61+
62+
if (!eventId) throw new Error("cannot redact event without ID");
63+
64+
const roomId = mxEvent.getRoomId();
65+
66+
if (!roomId) throw new Error(`cannot redact event ${mxEvent.getId()} without room ID`);
67+
5868
Modal.createDialog(
5969
ConfirmRedactDialog,
6070
{
6171
onFinished: async (proceed: boolean, reason?: string) => {
6272
if (!proceed) return;
6373

6474
const cli = MatrixClientPeg.get();
75+
const withRelations: { with_relations?: RelationType[] } = {};
76+
77+
// redact related events if this is a voice broadcast started event and
78+
// server has support for relation based redactions
79+
if (isVoiceBroadcastStartedEvent(mxEvent)) {
80+
const relationBasedRedactionsSupport = cli.canSupport.get(Feature.RelationBasedRedactions);
81+
if (
82+
relationBasedRedactionsSupport &&
83+
relationBasedRedactionsSupport !== ServerSupport.Unsupported
84+
) {
85+
withRelations.with_relations = [RelationType.Reference];
86+
}
87+
}
88+
6589
try {
6690
onCloseDialog?.();
67-
await cli.redactEvent(mxEvent.getRoomId(), mxEvent.getId(), undefined, reason ? { reason } : {});
68-
} catch (e) {
91+
await cli.redactEvent(roomId, eventId, undefined, {
92+
...(reason ? { reason } : {}),
93+
...withRelations,
94+
});
95+
} catch (e: any) {
6996
const code = e.errcode || e.statusCode;
7097
// only show the dialog if failing for something other than a network error
7198
// (e.g. no errcode or statusCode) as in that case the redactions end up in the

src/voice-broadcast/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export * from "./utils/doMaybeSetCurrentVoiceBroadcastPlayback";
4848
export * from "./utils/getChunkLength";
4949
export * from "./utils/getMaxBroadcastLength";
5050
export * from "./utils/hasRoomLiveVoiceBroadcast";
51+
export * from "./utils/isVoiceBroadcastStartedEvent";
5152
export * from "./utils/findRoomLiveVoiceBroadcastFromUserAndDevice";
5253
export * from "./utils/retrieveStartedInfoEvent";
5354
export * from "./utils/shouldDisplayAsVoiceBroadcastRecordingTile";
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
Copyright 2022 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
18+
19+
import { VoiceBroadcastInfoEventType, VoiceBroadcastInfoState } from "../types";
20+
21+
export const isVoiceBroadcastStartedEvent = (event: MatrixEvent): boolean => {
22+
return (
23+
event.getType() === VoiceBroadcastInfoEventType && event.getContent()?.state === VoiceBroadcastInfoState.Started
24+
);
25+
};
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
Copyright 2022 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import { Feature, ServerSupport } from "matrix-js-sdk/src/feature";
18+
import { MatrixClient, MatrixEvent, RelationType } from "matrix-js-sdk/src/matrix";
19+
import { screen } from "@testing-library/react";
20+
import userEvent from "@testing-library/user-event";
21+
22+
import { flushPromises, mkEvent, stubClient } from "../../../test-utils";
23+
import { mkVoiceBroadcastInfoStateEvent } from "../../../voice-broadcast/utils/test-utils";
24+
import { VoiceBroadcastInfoState } from "../../../../src/voice-broadcast";
25+
import { createRedactEventDialog } from "../../../../src/components/views/dialogs/ConfirmRedactDialog";
26+
27+
describe("ConfirmRedactDialog", () => {
28+
const roomId = "!room:example.com";
29+
let client: MatrixClient;
30+
let mxEvent: MatrixEvent;
31+
32+
const setUpVoiceBroadcastStartedEvent = () => {
33+
mxEvent = mkVoiceBroadcastInfoStateEvent(
34+
roomId,
35+
VoiceBroadcastInfoState.Started,
36+
client.getUserId()!,
37+
client.deviceId!,
38+
);
39+
};
40+
41+
const confirmDeleteVoiceBroadcastStartedEvent = async () => {
42+
createRedactEventDialog({ mxEvent });
43+
// double-flush promises required for the dialog to show up
44+
await flushPromises();
45+
await flushPromises();
46+
47+
await userEvent.click(screen.getByTestId("dialog-primary-button"));
48+
};
49+
50+
beforeEach(() => {
51+
client = stubClient();
52+
});
53+
54+
it("should raise an error for an event without ID", async () => {
55+
mxEvent = mkEvent({
56+
event: true,
57+
type: "m.room.message",
58+
room: roomId,
59+
content: {},
60+
user: client.getSafeUserId(),
61+
});
62+
jest.spyOn(mxEvent, "getId").mockReturnValue(undefined);
63+
expect(async () => {
64+
await confirmDeleteVoiceBroadcastStartedEvent();
65+
}).rejects.toThrow("cannot redact event without ID");
66+
});
67+
68+
it("should raise an error for an event without room-ID", async () => {
69+
mxEvent = mkEvent({
70+
event: true,
71+
type: "m.room.message",
72+
room: roomId,
73+
content: {},
74+
user: client.getSafeUserId(),
75+
});
76+
jest.spyOn(mxEvent, "getRoomId").mockReturnValue(undefined);
77+
expect(async () => {
78+
await confirmDeleteVoiceBroadcastStartedEvent();
79+
}).rejects.toThrow(`cannot redact event ${mxEvent.getId()} without room ID`);
80+
});
81+
82+
describe("when redacting a voice broadcast started event", () => {
83+
beforeEach(() => {
84+
setUpVoiceBroadcastStartedEvent();
85+
});
86+
87+
describe("and the server does not support relation based redactions", () => {
88+
beforeEach(() => {
89+
client.canSupport.set(Feature.RelationBasedRedactions, ServerSupport.Unsupported);
90+
});
91+
92+
describe("and displaying and confirm the dialog for a voice broadcast", () => {
93+
beforeEach(async () => {
94+
await confirmDeleteVoiceBroadcastStartedEvent();
95+
});
96+
97+
it("should call redact without `with_relations`", () => {
98+
expect(client.redactEvent).toHaveBeenCalledWith(roomId, mxEvent.getId(), undefined, {});
99+
});
100+
});
101+
});
102+
103+
describe("and the server supports relation based redactions", () => {
104+
beforeEach(() => {
105+
client.canSupport.set(Feature.RelationBasedRedactions, ServerSupport.Unstable);
106+
});
107+
108+
describe("and displaying and confirm the dialog for a voice broadcast", () => {
109+
beforeEach(async () => {
110+
await confirmDeleteVoiceBroadcastStartedEvent();
111+
});
112+
113+
it("should call redact with `with_relations`", () => {
114+
expect(client.redactEvent).toHaveBeenCalledWith(roomId, mxEvent.getId(), undefined, {
115+
with_relations: [RelationType.Reference],
116+
});
117+
});
118+
});
119+
});
120+
});
121+
});

test/test-utils/test-utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ export function createTestClient(): MatrixClient {
206206
requestPasswordEmailToken: jest.fn().mockRejectedValue({}),
207207
setPassword: jest.fn().mockRejectedValue({}),
208208
groupCallEventHandler: { groupCalls: new Map<string, GroupCall>() },
209+
redactEvent: jest.fn(),
209210
} as unknown as MatrixClient;
210211

211212
client.reEmitter = new ReEmitter(client);

0 commit comments

Comments
 (0)