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

Commit 9220a0c

Browse files
committed
Mark a thread as unread in the threads list due to activity.
1 parent 9de5654 commit 9220a0c

File tree

4 files changed

+57
-16
lines changed

4 files changed

+57
-16
lines changed

src/Unread.ts

+1-1
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

+8-5
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

@@ -70,12 +71,14 @@ export const useUnreadNotifications = (room: Room, threadId?: string): {
7071
setColor(NotificationColor.Red);
7172
} else if (greyNotifs > 0) {
7273
setColor(NotificationColor.Grey);
73-
} else if (!threadId) {
74-
// TODO: No support for `Bold` on threads at the moment
75-
74+
} else {
7675
// We don't have any notified messages, but we might have unread messages. Let's
7776
// find out.
78-
const hasUnread = doesRoomHaveUnreadMessages(room);
77+
let roomOrThread: Room | Thread = room;
78+
if (threadId) {
79+
roomOrThread = room.getThread(threadId)!;
80+
}
81+
const hasUnread = doesRoomOrThreadHaveUnreadMessages(roomOrThread);
7982
setColor(hasUnread ? NotificationColor.Bold : NotificationColor.None);
8083
}
8184
}

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ describe("EventTile", () => {
133133
it("shows an unread notification bage", () => {
134134
const { container } = getComponent({}, TimelineRenderingType.ThreadsList);
135135

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

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

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

+46-9
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@ 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 } 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

2525
import {
2626
UnreadNotificationBadge,
2727
} from "../../../../../src/components/views/rooms/NotificationBadge/UnreadNotificationBadge";
28-
import { mkMessage, stubClient } from "../../../../test-utils/test-utils";
28+
import { mkEvent, mkMessage, stubClient } from "../../../../test-utils/test-utils";
29+
import { mkThread } from "../../../../test-utils/threads";
2930
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
3031
import * as RoomNotifs from "../../../../../src/RoomNotifs";
3132

@@ -36,28 +37,35 @@ jest.mock('../../../../../src/RoomNotifs', () => ({
3637
}));
3738

3839
const ROOM_ID = "!roomId:example.org";
39-
let THREAD_ID;
40+
let THREAD_ID: string;
4041

4142
describe("UnreadNotificationBadge", () => {
42-
let mockClient: MatrixClient;
43+
stubClient();
44+
const client = MatrixClientPeg.get();
4345
let room: Room;
4446

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

51+
beforeAll(() => {
52+
client.supportsExperimentalThreads = () => true;
53+
});
54+
4955
beforeEach(() => {
5056
jest.clearAllMocks();
5157

52-
stubClient();
53-
mockClient = mocked(MatrixClientPeg.get());
54-
55-
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
58+
room = new Room(ROOM_ID, client, client.getUserId()!, {
5659
pendingEventOrdering: PendingEventOrdering.Detached,
5760
});
5861
room.setUnreadNotificationCount(NotificationCountType.Total, 1);
5962
room.setUnreadNotificationCount(NotificationCountType.Highlight, 0);
6063

64+
const { rootEvent } = mkThread(
65+
{ room, client, authorId: client.getUserId()!, participantUserIds: [client.getUserId()!] },
66+
);
67+
THREAD_ID = rootEvent.getId()!;
68+
6169
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 1);
6270
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 0);
6371

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

0 commit comments

Comments
 (0)