Don't allow pin or edit of messages with a send status (#31158)

* Don't allow pin or edit of messages with a send status

* lint and improve comments.
This commit is contained in:
David Langley
2025-11-03 17:33:18 +00:00
committed by GitHub
parent 18a5565b70
commit dcf3e536ab
4 changed files with 35 additions and 3 deletions

View File

@@ -70,7 +70,9 @@ export function canEditContent(matrixClient: MatrixClient, mxEvent: MatrixEvent)
if (
!isCancellable ||
mxEvent.status === EventStatus.CANCELLED ||
// Editing local echos is not supported(results in send a message that references the local ID).
// We need to ensure the event is not local, and therefore has no send status.
mxEvent.status !== null ||
mxEvent.isRedacted() ||
mxEvent.isRelation(RelationType.Replace) ||
mxEvent.getSender() !== matrixClient.getUserId()

View File

@@ -81,6 +81,9 @@ export default class PinningUtils {
const room = matrixClient.getRoom(mxEvent.getRoomId());
if (!room) return false;
// Should have a non-local event id
if (mxEvent.status !== null) return false;
return PinningUtils.userHasPinOrUnpinPermission(matrixClient, room) && PinningUtils.isPinnable(mxEvent);
}
@@ -94,6 +97,9 @@ export default class PinningUtils {
const room = matrixClient.getRoom(mxEvent.getRoomId());
if (!room) return false;
// Should have a non-local event id
if (mxEvent.status !== null) return false;
return PinningUtils.userHasPinOrUnpinPermission(matrixClient, room) && PinningUtils.isUnpinnable(mxEvent);
}
@@ -123,6 +129,9 @@ export default class PinningUtils {
const eventId = mxEvent.getId();
if (!eventId) return;
// Should have a non-local event id
if (mxEvent.status !== null) return;
// Get the current pinned events of the room
const pinnedIds: Array<string> =
room

View File

@@ -748,7 +748,8 @@ function createMenu(
// @ts-ignore illegally set private prop
room.currentState.beacons = beacons;
mxEvent.setStatus(EventStatus.SENT);
// The base case is that we have received the remote echo and have an eventId. No sending status.
mxEvent.setStatus(null);
client.getUserId = jest.fn().mockReturnValue("@user:example.com");
client.getRoom = jest.fn().mockReturnValue(room);

View File

@@ -125,7 +125,8 @@ describe("<MessageActionBar />", () => {
beforeEach(() => {
jest.clearAllMocks();
alicesMessageEvent.setStatus(EventStatus.SENT);
// The base case is that we have received the remote echo and have an eventId. No sending status.
alicesMessageEvent.setStatus(null);
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);
jest.spyOn(SettingsStore, "setValue").mockResolvedValue(undefined);
});
@@ -376,6 +377,25 @@ describe("<MessageActionBar />", () => {
expect(queryByLabelText("Delete")).toBeTruthy();
});
it("only shows retry and delete buttons when event could not be sent", () => {
// Enable pin and other features
jest.spyOn(SettingsStore, "getValue").mockReturnValue(true);
alicesMessageEvent.setStatus(EventStatus.NOT_SENT);
const { queryByLabelText } = getComponent({ mxEvent: alicesMessageEvent });
// Should show retry and cancel buttons
expect(queryByLabelText("Retry")).toBeTruthy();
expect(queryByLabelText("Delete")).toBeTruthy();
// Should NOT show edit, pin, react, reply buttons
expect(queryByLabelText("Edit")).toBeFalsy();
expect(queryByLabelText("Pin")).toBeFalsy();
expect(queryByLabelText("React")).toBeFalsy();
expect(queryByLabelText("Reply")).toBeFalsy();
expect(queryByLabelText("Reply in thread")).toBeFalsy();
});
it.todo("unsends event on cancel click");
it.todo("retrys event on retry click");
});