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

Commit ad4feef

Browse files
committed
Display threads in the threads list as unread (bold).
1 parent 511fbd7 commit ad4feef

File tree

4 files changed

+60
-16
lines changed

4 files changed

+60
-16
lines changed

src/Unread.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export function doesRoomHaveUnreadMessages(room: Room): boolean {
7070
return false;
7171
}
7272

73-
function doesRoomOrThreadHaveUnreadMessages(room: Room | Thread): boolean {
73+
export function doesRoomOrThreadHaveUnreadMessages(room: Room | Thread): boolean {
7474
const myUserId = MatrixClientPeg.get().getUserId();
7575

7676
// as we don't send RRs for our own messages, make sure we special case that

src/hooks/useUnreadNotifications.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ limitations under the License.
1515
*/
1616

1717
import { NotificationCount, NotificationCountType, Room, RoomEvent } from "matrix-js-sdk/src/models/room";
18+
import { Thread } from "matrix-js-sdk/src/models/thread";
1819
import { useCallback, useEffect, useState } from "react";
1920

2021
import { getUnsentMessages } from "../components/structures/RoomStatusBar";
2122
import { getRoomNotifsState, getUnreadNotificationCount, RoomNotifState } from "../RoomNotifs";
2223
import { NotificationColor } from "../stores/notifications/NotificationColor";
23-
import { doesRoomHaveUnreadMessages } from "../Unread";
24+
import { doesRoomOrThreadHaveUnreadMessages } from "../Unread";
2425
import { EffectiveMembership, getEffectiveMembership } from "../utils/membership";
2526
import { useEventEmitter } from "./useEventEmitter";
2627

@@ -75,12 +76,14 @@ export const useUnreadNotifications = (
7576
setColor(NotificationColor.Red);
7677
} else if (greyNotifs > 0) {
7778
setColor(NotificationColor.Grey);
78-
} else if (!threadId) {
79-
// TODO: No support for `Bold` on threads at the moment
80-
79+
} else {
8180
// We don't have any notified messages, but we might have unread messages. Let's
8281
// find out.
83-
const hasUnread = doesRoomHaveUnreadMessages(room);
82+
let roomOrThread: Room | Thread = room;
83+
if (threadId) {
84+
roomOrThread = room.getThread(threadId)!;
85+
}
86+
const hasUnread = doesRoomOrThreadHaveUnreadMessages(roomOrThread);
8487
setColor(hasUnread ? NotificationColor.Bold : NotificationColor.None);
8588
}
8689
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ describe("EventTile", () => {
137137
it("shows an unread notification bage", () => {
138138
const { container } = getComponent({}, TimelineRenderingType.ThreadsList);
139139

140-
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(0);
140+
// By default, the thread will assume there's unread activity in it.
141+
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(1);
141142

142143
act(() => {
143144
room.setThreadUnreadNotificationCount(mxEvent.getId(), NotificationCountType.Total, 3);

test/components/views/rooms/NotificationBadge/UnreadNotificationBadge-test.tsx

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,14 @@ limitations under the License.
1717
import React from "react";
1818
import "jest-mock";
1919
import { screen, act, render } from "@testing-library/react";
20-
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
20+
import { MsgType, RelationType } from "matrix-js-sdk/src/matrix";
21+
import { PendingEventOrdering } from "matrix-js-sdk/src/client";
2122
import { NotificationCountType, Room } from "matrix-js-sdk/src/models/room";
22-
import { mocked } from "jest-mock";
2323
import { EventStatus } from "matrix-js-sdk/src/models/event-status";
2424

25+
import { mkThread } from "../../../../test-utils/threads";
2526
import { UnreadNotificationBadge } from "../../../../../src/components/views/rooms/NotificationBadge/UnreadNotificationBadge";
26-
import { mkMessage, stubClient } from "../../../../test-utils/test-utils";
27+
import { mkEvent, mkMessage, stubClient } from "../../../../test-utils/test-utils";
2728
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
2829
import * as RoomNotifs from "../../../../../src/RoomNotifs";
2930

@@ -34,28 +35,38 @@ jest.mock("../../../../../src/RoomNotifs", () => ({
3435
}));
3536

3637
const ROOM_ID = "!roomId:example.org";
37-
let THREAD_ID;
38+
let THREAD_ID: string;
3839

3940
describe("UnreadNotificationBadge", () => {
40-
let mockClient: MatrixClient;
41+
stubClient();
42+
const client = MatrixClientPeg.get();
4143
let room: Room;
4244

4345
function getComponent(threadId?: string) {
4446
return <UnreadNotificationBadge room={room} threadId={threadId} />;
4547
}
4648

49+
beforeAll(() => {
50+
client.supportsExperimentalThreads = () => true;
51+
});
52+
4753
beforeEach(() => {
4854
jest.clearAllMocks();
4955

50-
stubClient();
51-
mockClient = mocked(MatrixClientPeg.get());
52-
53-
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
56+
room = new Room(ROOM_ID, client, client.getUserId()!, {
5457
pendingEventOrdering: PendingEventOrdering.Detached,
5558
});
5659
room.setUnreadNotificationCount(NotificationCountType.Total, 1);
5760
room.setUnreadNotificationCount(NotificationCountType.Highlight, 0);
5861

62+
const { rootEvent } = mkThread({
63+
room,
64+
client,
65+
authorId: client.getUserId()!,
66+
participantUserIds: [client.getUserId()!],
67+
});
68+
THREAD_ID = rootEvent.getId()!;
69+
5970
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 1);
6071
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 0);
6172

@@ -125,4 +136,33 @@ describe("UnreadNotificationBadge", () => {
125136
const { container } = render(getComponent());
126137
expect(container.querySelector(".mx_NotificationBadge")).toBeNull();
127138
});
139+
140+
it("activity renders unread notification badge", () => {
141+
act(() => {
142+
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 0);
143+
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 0);
144+
145+
// Add another event on the thread which is not sent by us.
146+
const event = mkEvent({
147+
event: true,
148+
type: "m.room.message",
149+
user: "@alice:server.org",
150+
room: room.roomId,
151+
content: {
152+
"msgtype": MsgType.Text,
153+
"body": "Hello from Bob",
154+
"m.relates_to": {
155+
event_id: THREAD_ID,
156+
rel_type: RelationType.Thread,
157+
},
158+
},
159+
});
160+
room.addLiveEvents([event]);
161+
});
162+
163+
const { container } = render(getComponent(THREAD_ID));
164+
expect(container.querySelector(".mx_NotificationBadge_dot")).toBeTruthy();
165+
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeTruthy();
166+
expect(container.querySelector(".mx_NotificationBadge_highlighted")).toBeFalsy();
167+
});
128168
});

0 commit comments

Comments
 (0)