@@ -57,6 +57,7 @@ import {
5757 ReceiptContent ,
5858 synthesizeReceipt ,
5959} from "./read-receipt" ;
60+ import { Feature , ServerSupport } from "../feature" ;
6061
6162// These constants are used as sane defaults when the homeserver doesn't support
6263// the m.room_versions capability. In practice, KNOWN_SAFE_ROOM_VERSION should be
@@ -96,7 +97,7 @@ export interface IRecommendedVersion {
9697// price to pay to keep matrix-js-sdk responsive.
9798const MAX_NUMBER_OF_VISIBILITY_EVENTS_TO_SCAN_THROUGH = 30 ;
9899
99- type NotificationCount = Partial < Record < NotificationCountType , number > > ;
100+ export type NotificationCount = Partial < Record < NotificationCountType , number > > ;
100101
101102export enum NotificationCountType {
102103 Highlight = "highlight" ,
@@ -127,6 +128,7 @@ export enum RoomEvent {
127128 OldStateUpdated = "Room.OldStateUpdated" ,
128129 CurrentStateUpdated = "Room.CurrentStateUpdated" ,
129130 HistoryImportedWithinTimeline = "Room.historyImportedWithinTimeline" ,
131+ UnreadNotifications = "Room.UnreadNotifications" ,
130132}
131133
132134type EmittedEvents = RoomEvent
@@ -164,6 +166,10 @@ export type RoomEventHandlerMap = {
164166 markerEvent : MatrixEvent ,
165167 room : Room ,
166168 ) => void ;
169+ [ RoomEvent . UnreadNotifications ] : (
170+ unreadNotifications : NotificationCount ,
171+ threadId ?: string ,
172+ ) => void ;
167173 [ RoomEvent . TimelineRefresh ] : ( room : Room , eventTimelineSet : EventTimelineSet ) => void ;
168174 [ ThreadEvent . New ] : ( thread : Thread , toStartOfTimeline : boolean ) => void ;
169175} & ThreadHandlerMap
@@ -186,7 +192,8 @@ export class Room extends ReadReceipt<EmittedEvents, RoomEventHandlerMap> {
186192 public readonly reEmitter : TypedReEmitter < EmittedEvents , RoomEventHandlerMap > ;
187193 private txnToEvent : Record < string , MatrixEvent > = { } ; // Pending in-flight requests { string: MatrixEvent }
188194 private notificationCounts : NotificationCount = { } ;
189- private threadNotifications : Map < string , NotificationCount > = new Map ( ) ;
195+ private readonly threadNotifications = new Map < string , NotificationCount > ( ) ;
196+ private roomThreadsNotificationType : NotificationCountType | null = null ;
190197 private readonly timelineSets : EventTimelineSet [ ] ;
191198 public readonly threadsTimelineSets : EventTimelineSet [ ] = [ ] ;
192199 // any filtered timeline sets we're maintaining for this room
@@ -1182,38 +1189,97 @@ export class Room extends ReadReceipt<EmittedEvents, RoomEventHandlerMap> {
11821189 * @return {Number } The notification count, or undefined if there is no count
11831190 * for this type.
11841191 */
1185- public getUnreadNotificationCount ( type = NotificationCountType . Total ) : number | undefined {
1186- return this . notificationCounts [ type ] ;
1192+ public getUnreadNotificationCount ( type = NotificationCountType . Total ) : number {
1193+ let count = this . notificationCounts [ type ] ?? 0 ;
1194+ if ( this . client . canSupport . get ( Feature . ThreadUnreadNotifications ) !== ServerSupport . Unsupported ) {
1195+ for ( const threadNotification of this . threadNotifications . values ( ) ) {
1196+ count += threadNotification [ type ] ?? 0 ;
1197+ }
1198+ }
1199+ return count ;
11871200 }
11881201
11891202 /**
1203+ * @experimental
11901204 * Get one of the notification counts for a thread
11911205 * @param threadId the root event ID
11921206 * @param type The type of notification count to get. default: 'total'
11931207 * @returns The notification count, or undefined if there is no count
11941208 * for this type.
11951209 */
1196- public getThreadUnreadNotificationCount ( threadId : string , type = NotificationCountType . Total ) : number | undefined {
1197- return this . threadNotifications . get ( threadId ) ?. [ type ] ;
1210+ public getThreadUnreadNotificationCount ( threadId : string , type = NotificationCountType . Total ) : number {
1211+ return this . threadNotifications . get ( threadId ) ?. [ type ] ?? 0 ;
11981212 }
11991213
12001214 /**
1215+ * @experimental
1216+ * Checks if the current room has unread thread notifications
1217+ * @returns {boolean }
1218+ */
1219+ public hasThreadUnreadNotification ( ) : boolean {
1220+ for ( const notification of this . threadNotifications . values ( ) ) {
1221+ if ( ( notification . highlight ?? 0 ) > 0 || ( notification . total ?? 0 ) > 0 ) {
1222+ return true ;
1223+ }
1224+ }
1225+ return false ;
1226+ }
1227+
1228+ /**
1229+ * @experimental
12011230 * Swet one of the notification count for a thread
12021231 * @param threadId the root event ID
12031232 * @param type The type of notification count to get. default: 'total'
12041233 * @returns {void }
12051234 */
12061235 public setThreadUnreadNotificationCount ( threadId : string , type : NotificationCountType , count : number ) : void {
1207- this . threadNotifications . set ( threadId , {
1236+ const notification : NotificationCount = {
12081237 highlight : this . threadNotifications . get ( threadId ) ?. highlight ,
12091238 total : this . threadNotifications . get ( threadId ) ?. total ,
12101239 ...{
12111240 [ type ] : count ,
12121241 } ,
1213- } ) ;
1242+ } ;
1243+
1244+ this . threadNotifications . set ( threadId , notification ) ;
1245+
1246+ // Remember what the global threads notification count type is
1247+ // for all the threads in the room
1248+ if ( count > 0 ) {
1249+ switch ( this . roomThreadsNotificationType ) {
1250+ case NotificationCountType . Highlight :
1251+ break ;
1252+ case NotificationCountType . Total :
1253+ if ( type === NotificationCountType . Highlight ) {
1254+ this . roomThreadsNotificationType = type ;
1255+ }
1256+ break ;
1257+ default :
1258+ this . roomThreadsNotificationType = type ;
1259+ }
1260+ }
1261+
1262+ this . emit (
1263+ RoomEvent . UnreadNotifications ,
1264+ notification ,
1265+ threadId ,
1266+ ) ;
12141267 }
12151268
1269+ /**
1270+ * @experimental
1271+ * @returns the notification count type for all the threads in the room
1272+ */
1273+ public getThreadsAggregateNotificationType ( ) : NotificationCountType | null {
1274+ return this . roomThreadsNotificationType ;
1275+ }
1276+
1277+ /**
1278+ * @experimental
1279+ * Resets the thread notifications for this room
1280+ */
12161281 public resetThreadUnreadNotificationCount ( ) : void {
1282+ this . roomThreadsNotificationType = null ;
12171283 this . threadNotifications . clear ( ) ;
12181284 }
12191285
@@ -1224,6 +1290,7 @@ export class Room extends ReadReceipt<EmittedEvents, RoomEventHandlerMap> {
12241290 */
12251291 public setUnreadNotificationCount ( type : NotificationCountType , count : number ) : void {
12261292 this . notificationCounts [ type ] = count ;
1293+ this . emit ( RoomEvent . UnreadNotifications , this . notificationCounts ) ;
12271294 }
12281295
12291296 public setSummary ( summary : IRoomSummary ) : void {
0 commit comments