diff --git a/src/components/views/right_panel/RoomHeaderButtons.tsx b/src/components/views/right_panel/RoomHeaderButtons.tsx index d7f0af13b6e0..668ba2bdea80 100644 --- a/src/components/views/right_panel/RoomHeaderButtons.tsx +++ b/src/components/views/right_panel/RoomHeaderButtons.tsx @@ -44,6 +44,7 @@ import { NotificationStateEvents } from "../../../stores/notifications/Notificat import PosthogTrackers from "../../../PosthogTrackers"; import { ButtonEvent } from "../elements/AccessibleButton"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { doesRoomOrThreadHaveUnreadMessages } from "../../../Unread"; const ROOM_INFO_PHASES = [ RightPanelPhases.RoomSummary, @@ -191,9 +192,17 @@ export default class RoomHeaderButtons extends HeaderButtons { return NotificationColor.Red; case NotificationCountType.Total: return NotificationColor.Grey; - default: - return NotificationColor.None; } + // We don't have any notified messages, but we might have unread messages. Let's + // find out. + for (const thread of this.props.room!.getThreads()) { + // If the current thread has unread messages, we're done. + if (doesRoomOrThreadHaveUnreadMessages(thread)) { + return NotificationColor.Bold; + } + } + // Otherwise, no notification color. + return NotificationColor.None; } private onUpdateStatus = (notificationState: SummarizedNotificationState): void => { diff --git a/test/components/views/right_panel/RoomHeaderButtons-test.tsx b/test/components/views/right_panel/RoomHeaderButtons-test.tsx index f9a3572aa821..76118d6ad385 100644 --- a/test/components/views/right_panel/RoomHeaderButtons-test.tsx +++ b/test/components/views/right_panel/RoomHeaderButtons-test.tsx @@ -24,6 +24,7 @@ import RoomHeaderButtons from "../../../../src/components/views/right_panel/Room import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import SettingsStore from "../../../../src/settings/SettingsStore"; import { stubClient } from "../../../test-utils"; +import { mkThread } from "../../../test-utils/threads"; describe("RoomHeaderButtons-test.tsx", function () { const ROOM_ID = "!roomId:example.org"; @@ -52,7 +53,7 @@ describe("RoomHeaderButtons-test.tsx", function () { return container.querySelector(".mx_RightPanel_threadsButton"); } - function isIndicatorOfType(container, type: "red" | "gray") { + function isIndicatorOfType(container, type: "red" | "gray" | "bold") { return container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator").className.includes(type); } @@ -76,7 +77,7 @@ describe("RoomHeaderButtons-test.tsx", function () { expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull(); }); - it("room wide notification does not change the thread button", () => { + it("thread notification does change the thread button", () => { const { container } = getComponent(room); room.setThreadUnreadNotificationCount("$123", NotificationCountType.Total, 1); @@ -89,6 +90,10 @@ describe("RoomHeaderButtons-test.tsx", function () { room.setThreadUnreadNotificationCount("$123", NotificationCountType.Highlight, 0); expect(container.querySelector(".mx_RightPanel_threadsButton .mx_Indicator")).toBeNull(); + + // Thread activity should appear on the icon. + mkThread({ room, client, authorId: client.getUserId()!, participantUserIds: ["@alice:example.org"] }); + expect(isIndicatorOfType(getComponent(room), "bold")).toBe(true); }); it("does not explode without a room", () => {