From cc01d5044285c13e023e6a1567a955cd8da7ff4a Mon Sep 17 00:00:00 2001 From: Clark Fischer Date: Thu, 19 Jan 2023 15:39:31 -0800 Subject: [PATCH] Unify room unread state determination Have both the class-based facility and the hook use the new unified logic in `RoomNotifs#determineUnreadState`. Addresses https://github.com/vector-im/element-web/issues/24229 Signed-off-by: Clark Fischer --- src/hooks/useUnreadNotifications.ts | 48 ++----------- .../notifications/RoomNotificationState.ts | 68 ++----------------- 2 files changed, 13 insertions(+), 103 deletions(-) diff --git a/src/hooks/useUnreadNotifications.ts b/src/hooks/useUnreadNotifications.ts index 22236d832f9d..b5a5cb52e2b6 100644 --- a/src/hooks/useUnreadNotifications.ts +++ b/src/hooks/useUnreadNotifications.ts @@ -1,5 +1,5 @@ /* -Copyright 2022 The Matrix.org Foundation C.I.C. +Copyright 2022 - 2023 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,15 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { NotificationCount, NotificationCountType, Room, RoomEvent } from "matrix-js-sdk/src/models/room"; -import { Thread } from "matrix-js-sdk/src/models/thread"; +import { NotificationCount, Room, RoomEvent } from "matrix-js-sdk/src/models/room"; import { useCallback, useEffect, useState } from "react"; -import { getUnsentMessages } from "../components/structures/RoomStatusBar"; -import { getRoomNotifsState, getUnreadNotificationCount, RoomNotifState } from "../RoomNotifs"; +import { determineUnreadState } from "../RoomNotifs"; import { NotificationColor } from "../stores/notifications/NotificationColor"; -import { doesRoomOrThreadHaveUnreadMessages } from "../Unread"; -import { EffectiveMembership, getEffectiveMembership } from "../utils/membership"; import { useEventEmitter } from "./useEventEmitter"; export const useUnreadNotifications = ( @@ -53,40 +49,10 @@ export const useUnreadNotifications = ( useEventEmitter(room, RoomEvent.MyMembership, () => updateNotificationState()); const updateNotificationState = useCallback(() => { - if (getUnsentMessages(room, threadId).length > 0) { - setSymbol("!"); - setCount(1); - setColor(NotificationColor.Unsent); - } else if (getEffectiveMembership(room.getMyMembership()) === EffectiveMembership.Invite) { - setSymbol("!"); - setCount(1); - setColor(NotificationColor.Red); - } else if (getRoomNotifsState(room.client, room.roomId) === RoomNotifState.Mute) { - setSymbol(null); - setCount(0); - setColor(NotificationColor.None); - } else { - const redNotifs = getUnreadNotificationCount(room, NotificationCountType.Highlight, threadId); - const greyNotifs = getUnreadNotificationCount(room, NotificationCountType.Total, threadId); - - const trueCount = greyNotifs || redNotifs; - setCount(trueCount); - setSymbol(null); - if (redNotifs > 0) { - setColor(NotificationColor.Red); - } else if (greyNotifs > 0) { - setColor(NotificationColor.Grey); - } else { - // We don't have any notified messages, but we might have unread messages. Let's - // find out. - let roomOrThread: Room | Thread = room; - if (threadId) { - roomOrThread = room.getThread(threadId)!; - } - const hasUnread = doesRoomOrThreadHaveUnreadMessages(roomOrThread); - setColor(hasUnread ? NotificationColor.Bold : NotificationColor.None); - } - } + const { symbol, count, color } = determineUnreadState(room, threadId); + setSymbol(symbol); + setCount(count); + setColor(color); }, [room, threadId]); useEffect(() => { diff --git a/src/stores/notifications/RoomNotificationState.ts b/src/stores/notifications/RoomNotificationState.ts index 1b3adeafcc26..bdf58e350991 100644 --- a/src/stores/notifications/RoomNotificationState.ts +++ b/src/stores/notifications/RoomNotificationState.ts @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020, 2023 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,19 +15,15 @@ limitations under the License. */ import { MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/models/event"; -import { NotificationCountType, Room, RoomEvent } from "matrix-js-sdk/src/models/room"; +import { Room, RoomEvent } from "matrix-js-sdk/src/models/room"; import { ClientEvent } from "matrix-js-sdk/src/client"; import { Feature, ServerSupport } from "matrix-js-sdk/src/feature"; -import { NotificationColor } from "./NotificationColor"; import { IDestroyable } from "../../utils/IDestroyable"; import { MatrixClientPeg } from "../../MatrixClientPeg"; -import { EffectiveMembership, getEffectiveMembership } from "../../utils/membership"; import { readReceiptChangeIsFor } from "../../utils/read-receipts"; import * as RoomNotifs from "../../RoomNotifs"; -import * as Unread from "../../Unread"; import { NotificationState, NotificationStateEvents } from "./NotificationState"; -import { getUnsentMessages } from "../../components/structures/RoomStatusBar"; import { ThreadsRoomNotificationState } from "./ThreadsRoomNotificationState"; export class RoomNotificationState extends NotificationState implements IDestroyable { @@ -49,10 +45,6 @@ export class RoomNotificationState extends NotificationState implements IDestroy this.updateNotificationState(); } - private get roomIsInvite(): boolean { - return getEffectiveMembership(this.room.getMyMembership()) === EffectiveMembership.Invite; - } - public destroy(): void { super.destroy(); const cli = this.room.client; @@ -112,58 +104,10 @@ export class RoomNotificationState extends NotificationState implements IDestroy private updateNotificationState(): void { const snapshot = this.snapshot(); - if (getUnsentMessages(this.room).length > 0) { - // When there are unsent messages we show a red `!` - this._color = NotificationColor.Unsent; - this._symbol = "!"; - this._count = 1; // not used, technically - } else if ( - RoomNotifs.getRoomNotifsState(this.room.client, this.room.roomId) === RoomNotifs.RoomNotifState.Mute - ) { - // When muted we suppress all notification states, even if we have context on them. - this._color = NotificationColor.None; - this._symbol = null; - this._count = 0; - } else if (this.roomIsInvite) { - this._color = NotificationColor.Red; - this._symbol = "!"; - this._count = 1; // not used, technically - } else { - const redNotifs = RoomNotifs.getUnreadNotificationCount(this.room, NotificationCountType.Highlight); - const greyNotifs = RoomNotifs.getUnreadNotificationCount(this.room, NotificationCountType.Total); - - // For a 'true count' we pick the grey notifications first because they include the - // red notifications. If we don't have a grey count for some reason we use the red - // count. If that count is broken for some reason, assume zero. This avoids us showing - // a badge for 'NaN' (which formats as 'NaNB' for NaN Billion). - const trueCount = greyNotifs ? greyNotifs : redNotifs ? redNotifs : 0; - - // Note: we only set the symbol if we have an actual count. We don't want to show - // zero on badges. - - if (redNotifs > 0) { - this._color = NotificationColor.Red; - this._count = trueCount; - this._symbol = null; // symbol calculated by component - } else if (greyNotifs > 0) { - this._color = NotificationColor.Grey; - this._count = trueCount; - this._symbol = null; // symbol calculated by component - } else { - // We don't have any notified messages, but we might have unread messages. Let's - // find out. - const hasUnread = Unread.doesRoomHaveUnreadMessages(this.room); - if (hasUnread) { - this._color = NotificationColor.Bold; - } else { - this._color = NotificationColor.None; - } - - // no symbol or count for this state - this._count = 0; - this._symbol = null; - } - } + const { color, symbol, count } = RoomNotifs.determineUnreadState(this.room); + this._color = color; + this._symbol = symbol; + this._count = count; // finally, publish an update if needed this.emitIfUpdated(snapshot);