diff --git a/src/RoomNotifs.ts b/src/RoomNotifs.ts index 7a65acadfc8..66be248f4f9 100644 --- a/src/RoomNotifs.ts +++ b/src/RoomNotifs.ts @@ -80,10 +80,19 @@ export function setRoomNotifsState(client: MatrixClient, roomId: string, newStat } } -export function getUnreadNotificationCount(room: Room, type: NotificationCountType, threadId?: string): number { +export function getUnreadNotificationCount( + room: Room, + type: NotificationCountType, + includeThreads: boolean, + threadId?: string, +): number { + const getCountShownForRoom = (r: Room, type: NotificationCountType): number => { + return includeThreads ? r.getUnreadNotificationCount(type) : r.getRoomUnreadNotificationCount(type); + }; + let notificationCount = !!threadId ? room.getThreadUnreadNotificationCount(threadId, type) - : room.getUnreadNotificationCount(type); + : getCountShownForRoom(room, type); // Check notification counts in the old room just in case there's some lost // there. We only go one level down to avoid performance issues, and theory @@ -99,7 +108,7 @@ export function getUnreadNotificationCount(room: Room, type: NotificationCountTy // notifying the user for unread messages because they would have extreme // difficulty changing their notification preferences away from "All Messages" // and "Noisy". - notificationCount += oldRoom.getUnreadNotificationCount(NotificationCountType.Highlight); + notificationCount += getCountShownForRoom(oldRoom, NotificationCountType.Highlight); } } @@ -224,9 +233,18 @@ function isMuteRule(rule: IPushRule): boolean { ); } +/** + * Returns an object giving information about the unread state of a room or thread + * @param room The room to query, or the room the thread is in + * @param threadId The thread to check the unread state of, or undefined to query the main thread + * @param includeThreads If threadId is undefined, true to include threads other than the main thread, or + * false to exclude them. Ignored if threadId is specified. + * @returns + */ export function determineUnreadState( room?: Room, threadId?: string, + includeThreads?: boolean, ): { level: NotificationLevel; symbol: string | null; count: number } { if (!room) { return { symbol: null, count: 0, level: NotificationLevel.None }; @@ -248,8 +266,13 @@ export function determineUnreadState( return { symbol: null, count: 0, level: NotificationLevel.None }; } - const redNotifs = getUnreadNotificationCount(room, NotificationCountType.Highlight, threadId); - const greyNotifs = getUnreadNotificationCount(room, NotificationCountType.Total, threadId); + const redNotifs = getUnreadNotificationCount( + room, + NotificationCountType.Highlight, + includeThreads ?? false, + threadId, + ); + const greyNotifs = getUnreadNotificationCount(room, NotificationCountType.Total, includeThreads ?? false, threadId); const trueCount = greyNotifs || redNotifs; if (redNotifs > 0) { @@ -269,7 +292,7 @@ export function determineUnreadState( } // If the thread does not exist, assume it contains no unreads } else { - hasUnread = doesRoomHaveUnreadMessages(room); + hasUnread = doesRoomHaveUnreadMessages(room, includeThreads ?? false); } return { diff --git a/src/Unread.ts b/src/Unread.ts index 7b2da855dd7..3a177fedaec 100644 --- a/src/Unread.ts +++ b/src/Unread.ts @@ -50,14 +50,19 @@ export function eventTriggersUnreadCount(client: MatrixClient, ev: MatrixEvent): return haveRendererForEvent(ev, client, false /* hidden messages should never trigger unread counts anyways */); } -export function doesRoomHaveUnreadMessages(room: Room): boolean { +export function doesRoomHaveUnreadMessages(room: Room, includeThreads: boolean): boolean { if (SettingsStore.getValue("feature_sliding_sync")) { // TODO: https://github.com/vector-im/element-web/issues/23207 // Sliding Sync doesn't support unread indicator dots (yet...) return false; } - for (const withTimeline of [room, ...room.getThreads()]) { + const toCheck: Array = [room]; + if (includeThreads) { + toCheck.push(...room.getThreads()); + } + + for (const withTimeline of toCheck) { if (doesTimelineHaveUnreadMessages(room, withTimeline.timeline)) { // We found an unread, so the room is unread return true; diff --git a/src/components/views/dialogs/devtools/RoomNotifications.tsx b/src/components/views/dialogs/devtools/RoomNotifications.tsx index 234746b74a1..5d03ee7c3a5 100644 --- a/src/components/views/dialogs/devtools/RoomNotifications.tsx +++ b/src/components/views/dialogs/devtools/RoomNotifications.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import { NotificationCountType, Room, Thread, ReceiptType } from "matrix-js-sdk/src/matrix"; -import React, { useContext } from "react"; +import React, { useContext, useMemo } from "react"; import { ReadReceipt } from "matrix-js-sdk/src/models/read-receipt"; import MatrixClientContext from "../../../../contexts/MatrixClientContext"; @@ -25,6 +25,7 @@ import { determineUnreadState } from "../../../../RoomNotifs"; import { humanReadableNotificationLevel } from "../../../../stores/notifications/NotificationLevel"; import { doesRoomOrThreadHaveUnreadMessages } from "../../../../Unread"; import BaseTool, { DevtoolsContext, IDevtoolsProps } from "./BaseTool"; +import SettingsStore from "../../../../settings/SettingsStore"; function UserReadUpTo({ target }: { target: ReadReceipt }): JSX.Element { const cli = useContext(MatrixClientContext); @@ -65,10 +66,12 @@ function UserReadUpTo({ target }: { target: ReadReceipt }): JSX.Elemen } export default function RoomNotifications({ onBack }: IDevtoolsProps): JSX.Element { + const tacEnabled = useMemo(() => SettingsStore.getValue("threadsActivityCentre"), []); + const { room } = useContext(DevtoolsContext); const cli = useContext(MatrixClientContext); - const { level, count } = determineUnreadState(room); + const { level, count } = determineUnreadState(room, undefined, !tacEnabled); const [notificationState] = useNotificationState(room); return ( diff --git a/src/hooks/useUnreadNotifications.ts b/src/hooks/useUnreadNotifications.ts index fd4bab9edfe..e0a2f1eeff2 100644 --- a/src/hooks/useUnreadNotifications.ts +++ b/src/hooks/useUnreadNotifications.ts @@ -15,12 +15,13 @@ limitations under the License. */ import { RoomEvent } from "matrix-js-sdk/src/matrix"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import type { NotificationCount, Room } from "matrix-js-sdk/src/matrix"; import { determineUnreadState } from "../RoomNotifs"; import { NotificationLevel } from "../stores/notifications/NotificationLevel"; import { useEventEmitter } from "./useEventEmitter"; +import SettingsStore from "../settings/SettingsStore"; export const useUnreadNotifications = ( room?: Room, @@ -30,6 +31,8 @@ export const useUnreadNotifications = ( count: number; level: NotificationLevel; } => { + const tacEnabled = useMemo(() => SettingsStore.getValue("threadsActivityCentre"), []); + const [symbol, setSymbol] = useState(null); const [count, setCount] = useState(0); const [level, setLevel] = useState(NotificationLevel.None); @@ -50,11 +53,11 @@ export const useUnreadNotifications = ( useEventEmitter(room, RoomEvent.MyMembership, () => updateNotificationState()); const updateNotificationState = useCallback(() => { - const { symbol, count, level } = determineUnreadState(room, threadId); + const { symbol, count, level } = determineUnreadState(room, threadId, !tacEnabled); setSymbol(symbol); setCount(count); setLevel(level); - }, [room, threadId]); + }, [room, threadId, tacEnabled]); useEffect(() => { updateNotificationState(); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 43f6d6bbce4..1bca9964a6d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1419,6 +1419,7 @@ "group_rooms": "Rooms", "group_spaces": "Spaces", "group_themes": "Themes", + "group_threads": "Threads", "group_voip": "Voice & Video", "group_widgets": "Widgets", "hidebold": "Hide notification dot (only display counters badges)", @@ -1462,6 +1463,7 @@ "sliding_sync_server_no_support": "Your server lacks native support", "sliding_sync_server_specify_proxy": "Your server lacks native support, you must specify a proxy", "sliding_sync_server_support": "Your server has native support", + "threads_activity_centre": "Threads Activity Centre (in development). Currently this just removes thread notification counts from the count total in the room list", "under_active_development": "Under active development.", "unrealiable_e2e": "Unreliable in encrypted rooms", "video_rooms": "Video rooms", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 3a21d6f6dda..d93e83a2d44 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -81,6 +81,7 @@ export enum LabGroup { Spaces, Widgets, Rooms, + Threads, VoiceAndVideo, Moderation, Analytics, @@ -104,6 +105,7 @@ export const labGroupNames: Record = { [LabGroup.Spaces]: _td("labs|group_spaces"), [LabGroup.Widgets]: _td("labs|group_widgets"), [LabGroup.Rooms]: _td("labs|group_rooms"), + [LabGroup.Threads]: _td("labs|group_threads"), [LabGroup.VoiceAndVideo]: _td("labs|group_voip"), [LabGroup.Moderation]: _td("labs|group_moderation"), [LabGroup.Analytics]: _td("common|analytics"), @@ -1113,6 +1115,14 @@ export const SETTINGS: { [setting: string]: ISetting } = { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS, default: [], }, + "threadsActivityCentre": { + supportedLevels: LEVELS_ACCOUNT_SETTINGS, + labsGroup: LabGroup.Threads, + controller: new ReloadOnChangeController(), + displayName: _td("labs|threads_activity_centre"), + default: false, + isFeature: true, + }, [UIFeature.RoomHistorySettings]: { supportedLevels: LEVELS_UI_FEATURE, default: true, diff --git a/src/stores/notifications/RoomNotificationState.ts b/src/stores/notifications/RoomNotificationState.ts index be5d5918342..0503485584d 100644 --- a/src/stores/notifications/RoomNotificationState.ts +++ b/src/stores/notifications/RoomNotificationState.ts @@ -25,7 +25,10 @@ import { NotificationState } from "./NotificationState"; import SettingsStore from "../../settings/SettingsStore"; export class RoomNotificationState extends NotificationState implements IDestroyable { - public constructor(public readonly room: Room) { + public constructor( + public readonly room: Room, + private includeThreads: boolean, + ) { super(); const cli = this.room.client; this.room.on(RoomEvent.Receipt, this.handleReadReceipt); @@ -90,7 +93,7 @@ export class RoomNotificationState extends NotificationState implements IDestroy private updateNotificationState(): void { const snapshot = this.snapshot(); - const { level, symbol, count } = RoomNotifs.determineUnreadState(this.room); + const { level, symbol, count } = RoomNotifs.determineUnreadState(this.room, undefined, this.includeThreads); const muted = RoomNotifs.getRoomNotifsState(this.room.client, this.room.roomId) === RoomNotifs.RoomNotifState.Mute; const knocked = SettingsStore.getValue("feature_ask_to_join") && this.room.getMyMembership() === "knock"; diff --git a/src/stores/notifications/RoomNotificationStateStore.ts b/src/stores/notifications/RoomNotificationStateStore.ts index 5c8161a3383..f2d10ac4fb1 100644 --- a/src/stores/notifications/RoomNotificationStateStore.ts +++ b/src/stores/notifications/RoomNotificationStateStore.ts @@ -42,6 +42,8 @@ export class RoomNotificationStateStore extends AsyncStoreWithClient { private listMap = new Map(); private _globalState = new SummarizedNotificationState(); + private tacEnabled = SettingsStore.getValue("threadsActivityCentre"); + private constructor(dispatcher = defaultDispatcher) { super(dispatcher, {}); SettingsStore.watchSetting("feature_dynamic_room_predecessors", null, () => { @@ -97,7 +99,7 @@ export class RoomNotificationStateStore extends AsyncStoreWithClient { */ public getRoomState(room: Room): RoomNotificationState { if (!this.roomMap.has(room)) { - this.roomMap.set(room, new RoomNotificationState(room)); + this.roomMap.set(room, new RoomNotificationState(room, !this.tacEnabled)); } return this.roomMap.get(room)!; } diff --git a/test/RoomNotifs-test.ts b/test/RoomNotifs-test.ts index f558ccc68ae..371ffea9104 100644 --- a/test/RoomNotifs-test.ts +++ b/test/RoomNotifs-test.ts @@ -109,16 +109,16 @@ describe("RoomNotifs test", () => { }); it("counts room notification type", () => { - expect(getUnreadNotificationCount(room, NotificationCountType.Total)).toBe(0); - expect(getUnreadNotificationCount(room, NotificationCountType.Highlight)).toBe(0); + expect(getUnreadNotificationCount(room, NotificationCountType.Total, false)).toBe(0); + expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, false)).toBe(0); }); it("counts notifications type", () => { room.setUnreadNotificationCount(NotificationCountType.Total, 2); room.setUnreadNotificationCount(NotificationCountType.Highlight, 1); - expect(getUnreadNotificationCount(room, NotificationCountType.Total)).toBe(2); - expect(getUnreadNotificationCount(room, NotificationCountType.Highlight)).toBe(1); + expect(getUnreadNotificationCount(room, NotificationCountType.Total, false)).toBe(2); + expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, false)).toBe(1); }); describe("when there is a room predecessor", () => { @@ -156,8 +156,8 @@ describe("RoomNotifs test", () => { it("and there is a predecessor in the create event, it should count predecessor highlight", () => { room.addLiveEvents([mkCreateEvent(OLD_ROOM_ID)]); - expect(getUnreadNotificationCount(room, NotificationCountType.Total)).toBe(8); - expect(getUnreadNotificationCount(room, NotificationCountType.Highlight)).toBe(7); + expect(getUnreadNotificationCount(room, NotificationCountType.Total, false)).toBe(8); + expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, false)).toBe(7); }); }; @@ -167,8 +167,8 @@ describe("RoomNotifs test", () => { room.addLiveEvents([mkCreateEvent(OLD_ROOM_ID)]); upsertRoomStateEvents(room, [mkPredecessorEvent(OLD_ROOM_ID)]); - expect(getUnreadNotificationCount(room, NotificationCountType.Total)).toBe(8); - expect(getUnreadNotificationCount(room, NotificationCountType.Highlight)).toBe(7); + expect(getUnreadNotificationCount(room, NotificationCountType.Total, false)).toBe(8); + expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, false)).toBe(7); }); }; @@ -195,8 +195,8 @@ describe("RoomNotifs test", () => { room.addLiveEvents([mkCreateEvent()]); upsertRoomStateEvents(room, [mkPredecessorEvent(OLD_ROOM_ID)]); - expect(getUnreadNotificationCount(room, NotificationCountType.Total)).toBe(2); - expect(getUnreadNotificationCount(room, NotificationCountType.Highlight)).toBe(1); + expect(getUnreadNotificationCount(room, NotificationCountType.Total, false)).toBe(2); + expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, false)).toBe(1); }); }); @@ -214,31 +214,31 @@ describe("RoomNotifs test", () => { room.addLiveEvents([mkCreateEvent()]); upsertRoomStateEvents(room, [mkPredecessorEvent(OLD_ROOM_ID)]); - expect(getUnreadNotificationCount(room, NotificationCountType.Total)).toBe(8); - expect(getUnreadNotificationCount(room, NotificationCountType.Highlight)).toBe(7); + expect(getUnreadNotificationCount(room, NotificationCountType.Total, false)).toBe(8); + expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, false)).toBe(7); }); it("and there is an unknown room in the predecessor event, it should not count predecessor highlight", () => { room.addLiveEvents([mkCreateEvent()]); upsertRoomStateEvents(room, [mkPredecessorEvent("!unknon:example.com")]); - expect(getUnreadNotificationCount(room, NotificationCountType.Total)).toBe(2); - expect(getUnreadNotificationCount(room, NotificationCountType.Highlight)).toBe(1); + expect(getUnreadNotificationCount(room, NotificationCountType.Total, false)).toBe(2); + expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, false)).toBe(1); }); }); }); it("counts thread notification type", () => { - expect(getUnreadNotificationCount(room, NotificationCountType.Total, THREAD_ID)).toBe(0); - expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, THREAD_ID)).toBe(0); + expect(getUnreadNotificationCount(room, NotificationCountType.Total, false, THREAD_ID)).toBe(0); + expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, false, THREAD_ID)).toBe(0); }); it("counts thread notifications type", () => { room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 2); room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 1); - expect(getUnreadNotificationCount(room, NotificationCountType.Total, THREAD_ID)).toBe(2); - expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, THREAD_ID)).toBe(1); + expect(getUnreadNotificationCount(room, NotificationCountType.Total, false, THREAD_ID)).toBe(2); + expect(getUnreadNotificationCount(room, NotificationCountType.Highlight, false, THREAD_ID)).toBe(1); }); }); diff --git a/test/Unread-test.ts b/test/Unread-test.ts index 2ad0982a18e..843490b4256 100644 --- a/test/Unread-test.ts +++ b/test/Unread-test.ts @@ -152,7 +152,7 @@ describe("Unread", () => { }); it("returns true for a room with no receipts", () => { - expect(doesRoomHaveUnreadMessages(room)).toBe(true); + expect(doesRoomHaveUnreadMessages(room, false)).toBe(true); }); it("returns false for a room when the latest event was sent by the current user", () => { @@ -166,7 +166,7 @@ describe("Unread", () => { // Only for timeline events. room.addLiveEvents([event]); - expect(doesRoomHaveUnreadMessages(room)).toBe(false); + expect(doesRoomHaveUnreadMessages(room, false)).toBe(false); }); it("returns false for a room when the read receipt is at the latest event", () => { @@ -183,7 +183,7 @@ describe("Unread", () => { }); room.addReceipt(receipt); - expect(doesRoomHaveUnreadMessages(room)).toBe(false); + expect(doesRoomHaveUnreadMessages(room, false)).toBe(false); }); it("returns true for a room when the read receipt is earlier than the latest event", () => { @@ -210,7 +210,7 @@ describe("Unread", () => { // Only for timeline events. room.addLiveEvents([event2]); - expect(doesRoomHaveUnreadMessages(room)).toBe(true); + expect(doesRoomHaveUnreadMessages(room, false)).toBe(true); }); it("returns true for a room with an unread message in a thread", async () => { @@ -247,7 +247,7 @@ describe("Unread", () => { // Create a thread as a different user. await populateThread({ room, client, authorId: myId, participantUserIds: [aliceId] }); - expect(doesRoomHaveUnreadMessages(room)).toBe(true); + expect(doesRoomHaveUnreadMessages(room, true)).toBe(true); }); it("returns false for a room when the latest thread event was sent by the current user", async () => { @@ -268,7 +268,7 @@ describe("Unread", () => { // Create a thread as the current user. await populateThread({ room, client, authorId: myId, participantUserIds: [myId] }); - expect(doesRoomHaveUnreadMessages(room)).toBe(false); + expect(doesRoomHaveUnreadMessages(room, true)).toBe(false); }); it("returns false for a room with read thread messages", async () => { @@ -308,7 +308,7 @@ describe("Unread", () => { }); room.addReceipt(receipt); - expect(doesRoomHaveUnreadMessages(room)).toBe(false); + expect(doesRoomHaveUnreadMessages(room, true)).toBe(false); }); it("returns true for a room when read receipt is not on the latest thread messages", async () => { @@ -348,7 +348,7 @@ describe("Unread", () => { }); room.addReceipt(receipt); - expect(doesRoomHaveUnreadMessages(room)).toBe(true); + expect(doesRoomHaveUnreadMessages(room, true)).toBe(true); }); it("returns true when the event for a thread receipt can't be found", async () => { @@ -394,7 +394,7 @@ describe("Unread", () => { }); room.addReceipt(receipt); - expect(doesRoomHaveUnreadMessages(room)).toBe(true); + expect(doesRoomHaveUnreadMessages(room, true)).toBe(true); }); }); @@ -412,7 +412,7 @@ describe("Unread", () => { // Only for timeline events. room.addLiveEvents([redactedEvent]); - expect(doesRoomHaveUnreadMessages(room)).toBe(true); + expect(doesRoomHaveUnreadMessages(room, true)).toBe(true); expect(logger.warn).toHaveBeenCalledWith( "Falling back to unread room because of no read receipt or counting message found", { diff --git a/test/components/views/rooms/LegacyRoomHeader-test.tsx b/test/components/views/rooms/LegacyRoomHeader-test.tsx index ed82f74630c..7dadf14dbee 100644 --- a/test/components/views/rooms/LegacyRoomHeader-test.tsx +++ b/test/components/views/rooms/LegacyRoomHeader-test.tsx @@ -792,8 +792,11 @@ function createRoom(info: IRoomCreationInfo) { const userId = client.getUserId()!; if (info.isDm) { client.getAccountData = (eventType) => { - expect(eventType).toEqual("m.direct"); - return mkDirectEvent(roomId, userId, info.userIds); + if (eventType === "m.direct") { + return mkDirectEvent(roomId, userId, info.userIds); + } else { + return undefined; + } }; } diff --git a/test/components/views/rooms/RoomHeader/VideoRoomChatButton-test.tsx b/test/components/views/rooms/RoomHeader/VideoRoomChatButton-test.tsx index bc9eb10b560..7981a1b03dc 100644 --- a/test/components/views/rooms/RoomHeader/VideoRoomChatButton-test.tsx +++ b/test/components/views/rooms/RoomHeader/VideoRoomChatButton-test.tsx @@ -47,7 +47,7 @@ describe("", () => { }; const mockRoomNotificationState = (room: Room, level: NotificationLevel): RoomNotificationState => { - const roomNotificationState = new RoomNotificationState(room); + const roomNotificationState = new RoomNotificationState(room, false); // @ts-ignore ugly mocking roomNotificationState._level = level; diff --git a/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx b/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx index 0b34ef63438..83f489f411e 100644 --- a/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx +++ b/test/components/views/settings/tabs/user/LabsUserSettingsTab-test.tsx @@ -60,7 +60,7 @@ describe("", () => { // non-beta labs section expect(screen.getByText("Early previews")).toBeInTheDocument(); const labsSections = container.getElementsByClassName("mx_SettingsSubsection"); - expect(labsSections).toHaveLength(9); + expect(labsSections).toHaveLength(10); }); describe("Rust crypto setting", () => { diff --git a/test/stores/RoomNotificationStateStore-test.ts b/test/stores/RoomNotificationStateStore-test.ts index acb6a593471..46b57425d6b 100644 --- a/test/stores/RoomNotificationStateStore-test.ts +++ b/test/stores/RoomNotificationStateStore-test.ts @@ -125,6 +125,7 @@ describe("RoomNotificationStateStore", function () { ret.getPendingEvents = jest.fn().mockReturnValue([]); ret.isSpaceRoom = jest.fn().mockReturnValue(false); ret.getUnreadNotificationCount = jest.fn().mockReturnValue(numUnreads); + ret.getRoomUnreadNotificationCount = jest.fn().mockReturnValue(numUnreads); return ret; } }); diff --git a/test/stores/notifications/RoomNotificationState-test.ts b/test/stores/notifications/RoomNotificationState-test.ts index f556afb6dfc..1e124d15272 100644 --- a/test/stores/notifications/RoomNotificationState-test.ts +++ b/test/stores/notifications/RoomNotificationState-test.ts @@ -81,7 +81,7 @@ describe("RoomNotificationState", () => { } it("Updates on event decryption", () => { - const roomNotifState = new RoomNotificationState(room); + const roomNotifState = new RoomNotificationState(room, true); const listener = jest.fn(); roomNotifState.addListener(NotificationStateEvents.Update, listener); const testEvent = { @@ -93,12 +93,12 @@ describe("RoomNotificationState", () => { }); it("removes listeners", () => { - const roomNotifState = new RoomNotificationState(room); + const roomNotifState = new RoomNotificationState(room, false); expect(() => roomNotifState.destroy()).not.toThrow(); }); it("suggests an 'unread' ! if there are unsent messages", () => { - const roomNotifState = new RoomNotificationState(room); + const roomNotifState = new RoomNotificationState(room, false); const event = mkEvent({ event: true, @@ -115,7 +115,7 @@ describe("RoomNotificationState", () => { }); it("suggests nothing if the room is muted", () => { - const roomNotifState = new RoomNotificationState(room); + const roomNotifState = new RoomNotificationState(room, false); muteRoom(room); setUnreads(room, 1234, 0); @@ -127,7 +127,7 @@ describe("RoomNotificationState", () => { }); it("suggests a red ! if the user has been invited to a room", () => { - const roomNotifState = new RoomNotificationState(room); + const roomNotifState = new RoomNotificationState(room, false); room.updateMyMembership("invite"); // emit @@ -137,7 +137,7 @@ describe("RoomNotificationState", () => { }); it("returns a proper count and color for regular unreads", () => { - const roomNotifState = new RoomNotificationState(room); + const roomNotifState = new RoomNotificationState(room, false); setUnreads(room, 4321, 0); room.updateMyMembership("join"); // emit @@ -148,7 +148,7 @@ describe("RoomNotificationState", () => { }); it("returns a proper count and color for highlights", () => { - const roomNotifState = new RoomNotificationState(room); + const roomNotifState = new RoomNotificationState(room, false); setUnreads(room, 0, 69); room.updateMyMembership("join"); // emit @@ -159,7 +159,7 @@ describe("RoomNotificationState", () => { }); it("includes threads", async () => { - const roomNotifState = new RoomNotificationState(room); + const roomNotifState = new RoomNotificationState(room, true); room.timeline.push( new MatrixEvent({