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

Commit 2434749

Browse files
author
Kerry
authored
Highlight event when any version triggered a highlight (#10502)
* check previous events pushactions when deciding to highlight * test event highlight * strict fix * highlight edited text to red
1 parent 1024ced commit 2434749

File tree

3 files changed

+121
-9
lines changed

3 files changed

+121
-9
lines changed

res/css/views/rooms/_EventTile.pcss

+2-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ $left-gutter: 64px;
132132
}
133133

134134
&.mx_EventTile_highlight,
135-
&.mx_EventTile_highlight .markdown-body {
135+
&.mx_EventTile_highlight .markdown-body,
136+
&.mx_EventTile_highlight .mx_EventTile_edited {
136137
color: $alert;
137138
}
138139

src/components/views/rooms/EventTile.tsx

+17-6
Original file line numberDiff line numberDiff line change
@@ -653,15 +653,26 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
653653
return true;
654654
}
655655

656+
/**
657+
* Determine whether an event should be highlighted
658+
* For edited events, if a previous version of the event was highlighted
659+
* the event should remain highlighted as the user may have been notified
660+
* (Clearer explanation of why an event is highlighted is planned -
661+
* https://github.com/vector-im/element-web/issues/24927)
662+
* @returns boolean
663+
*/
656664
private shouldHighlight(): boolean {
657665
if (this.props.forExport) return false;
658666
if (this.context.timelineRenderingType === TimelineRenderingType.Notification) return false;
659667
if (this.context.timelineRenderingType === TimelineRenderingType.ThreadsList) return false;
660668

661-
const actions = MatrixClientPeg.get().getPushActionsForEvent(
662-
this.props.mxEvent.replacingEvent() || this.props.mxEvent,
663-
);
664-
if (!actions || !actions.tweaks) {
669+
const cli = MatrixClientPeg.get();
670+
const actions = cli.getPushActionsForEvent(this.props.mxEvent.replacingEvent() || this.props.mxEvent);
671+
// get the actions for the previous version of the event too if it is an edit
672+
const previousActions = this.props.mxEvent.replacingEvent()
673+
? cli.getPushActionsForEvent(this.props.mxEvent)
674+
: undefined;
675+
if (!actions?.tweaks && !previousActions?.tweaks) {
665676
return false;
666677
}
667678

@@ -670,13 +681,13 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
670681
return false;
671682
}
672683

673-
return actions.tweaks.highlight;
684+
return !!(actions?.tweaks.highlight || previousActions?.tweaks.highlight);
674685
}
675686

676687
private onSenderProfileClick = (): void => {
677688
dis.dispatch<ComposerInsertPayload>({
678689
action: Action.ComposerInsert,
679-
userId: this.props.mxEvent.getSender(),
690+
userId: this.props.mxEvent.getSender()!,
680691
timelineRenderingType: this.context.timelineRenderingType,
681692
});
682693
};

test/components/views/rooms/EventTile-test.tsx

+102-2
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@ limitations under the License.
1515
*/
1616

1717
import * as React from "react";
18+
import { render, waitFor, screen, act, fireEvent } from "@testing-library/react";
19+
import { mocked } from "jest-mock";
1820
import { EventType } from "matrix-js-sdk/src/@types/event";
1921
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
22+
import { TweakName } from "matrix-js-sdk/src/matrix";
2023
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
2124
import { NotificationCountType, Room } from "matrix-js-sdk/src/models/room";
2225
import { DeviceTrustLevel, UserTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning";
2326
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo";
2427
import { IEncryptedEventInfo } from "matrix-js-sdk/src/crypto/api";
25-
import { render, waitFor, screen, act, fireEvent } from "@testing-library/react";
2628

2729
import EventTile, { EventTileProps } from "../../../../src/components/views/rooms/EventTile";
2830
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
@@ -73,7 +75,7 @@ describe("EventTile", () => {
7375
stubClient();
7476
client = MatrixClientPeg.get();
7577

76-
room = new Room(ROOM_ID, client, client.getUserId()!, {
78+
room = new Room(ROOM_ID, client, client.getSafeUserId(), {
7779
pendingEventOrdering: PendingEventOrdering.Detached,
7880
});
7981

@@ -373,4 +375,102 @@ describe("EventTile", () => {
373375
);
374376
});
375377
});
378+
379+
describe("event highlighting", () => {
380+
const isHighlighted = (container: HTMLElement): boolean =>
381+
!!container.getElementsByClassName("mx_EventTile_highlight").length;
382+
383+
beforeEach(() => {
384+
mocked(client.getPushActionsForEvent).mockReturnValue(null);
385+
});
386+
387+
it("does not highlight message where message matches no push actions", () => {
388+
const { container } = getComponent();
389+
390+
expect(client.getPushActionsForEvent).toHaveBeenCalledWith(mxEvent);
391+
expect(isHighlighted(container)).toBeFalsy();
392+
});
393+
394+
it(`does not highlight when message's push actions does not have a highlight tweak`, () => {
395+
mocked(client.getPushActionsForEvent).mockReturnValue({ notify: true, tweaks: {} });
396+
const { container } = getComponent();
397+
398+
expect(isHighlighted(container)).toBeFalsy();
399+
});
400+
401+
it(`highlights when message's push actions have a highlight tweak`, () => {
402+
mocked(client.getPushActionsForEvent).mockReturnValue({
403+
notify: true,
404+
tweaks: { [TweakName.Highlight]: true },
405+
});
406+
const { container } = getComponent();
407+
408+
expect(isHighlighted(container)).toBeTruthy();
409+
});
410+
411+
describe("when a message has been edited", () => {
412+
let editingEvent: MatrixEvent;
413+
414+
beforeEach(() => {
415+
editingEvent = new MatrixEvent({
416+
type: "m.room.message",
417+
room_id: ROOM_ID,
418+
sender: "@alice:example.org",
419+
content: {
420+
"msgtype": "m.text",
421+
"body": "* edited body",
422+
"m.new_content": {
423+
msgtype: "m.text",
424+
body: "edited body",
425+
},
426+
"m.relates_to": {
427+
rel_type: "m.replace",
428+
event_id: mxEvent.getId(),
429+
},
430+
},
431+
});
432+
mxEvent.makeReplaced(editingEvent);
433+
});
434+
435+
it("does not highlight message where no version of message matches any push actions", () => {
436+
const { container } = getComponent();
437+
438+
// get push actions for both events
439+
expect(client.getPushActionsForEvent).toHaveBeenCalledWith(mxEvent);
440+
expect(client.getPushActionsForEvent).toHaveBeenCalledWith(editingEvent);
441+
expect(isHighlighted(container)).toBeFalsy();
442+
});
443+
444+
it(`does not highlight when no version of message's push actions have a highlight tweak`, () => {
445+
mocked(client.getPushActionsForEvent).mockReturnValue({ notify: true, tweaks: {} });
446+
const { container } = getComponent();
447+
448+
expect(isHighlighted(container)).toBeFalsy();
449+
});
450+
451+
it(`highlights when previous version of message's push actions have a highlight tweak`, () => {
452+
mocked(client.getPushActionsForEvent).mockImplementation((event: MatrixEvent) => {
453+
if (event === mxEvent) {
454+
return { notify: true, tweaks: { [TweakName.Highlight]: true } };
455+
}
456+
return { notify: false, tweaks: {} };
457+
});
458+
const { container } = getComponent();
459+
460+
expect(isHighlighted(container)).toBeTruthy();
461+
});
462+
463+
it(`highlights when new version of message's push actions have a highlight tweak`, () => {
464+
mocked(client.getPushActionsForEvent).mockImplementation((event: MatrixEvent) => {
465+
if (event === editingEvent) {
466+
return { notify: true, tweaks: { [TweakName.Highlight]: true } };
467+
}
468+
return { notify: false, tweaks: {} };
469+
});
470+
const { container } = getComponent();
471+
472+
expect(isHighlighted(container)).toBeTruthy();
473+
});
474+
});
475+
});
376476
});

0 commit comments

Comments
 (0)