diff --git a/src/client.ts b/src/client.ts index d965524cf..b2d52d085 100644 --- a/src/client.ts +++ b/src/client.ts @@ -842,8 +842,39 @@ export class MatrixClient extends EventEmitter { // actions for themselves, so we have to kinda help them out when they are encrypted. // We do this so that push rules are correctly executed on events in their decrypted // state, such as highlights when the user's name is mentioned. - this.on("Event.decrypted", (event: MatrixEvent) => { - this.updateEncryptedRoomNotificationCount(event); + this.on("Event.decrypted", (event) => { + const oldActions = event.getPushActions(); + const actions = this.pushProcessor.actionsForEvent(event); + event.setPushActions(actions); // Might as well while we're here + + const room = this.getRoom(event.getRoomId()); + if (!room) return; + + const currentCount = room.getUnreadNotificationCount(NotificationCountType.Highlight); + + // Ensure the unread counts are kept up to date if the event is encrypted + // We also want to make sure that the notification count goes up if we already + // have encrypted events to avoid other code from resetting 'highlight' to zero. + const oldHighlight = oldActions && oldActions.tweaks + ? !!oldActions.tweaks.highlight : false; + const newHighlight = actions && actions.tweaks + ? !!actions.tweaks.highlight : false; + if (oldHighlight !== newHighlight || currentCount > 0) { + // TODO: Handle mentions received while the client is offline + // See also https://github.com/vector-im/element-web/issues/9069 + if (!room.hasUserReadEvent(this.getUserId(), event.getId())) { + let newCount = currentCount; + if (newHighlight && !oldHighlight) newCount++; + if (!newHighlight && oldHighlight) newCount--; + room.setUnreadNotificationCount(NotificationCountType.Highlight, newCount); + + // Fix 'Mentions Only' rooms from not having the right badge count + const totalCount = room.getUnreadNotificationCount(NotificationCountType.Total); + if (totalCount < newCount) { + room.setUnreadNotificationCount(NotificationCountType.Total, newCount); + } + } + } }); // Like above, we have to listen for read receipts from ourselves in order to @@ -889,38 +920,6 @@ export class MatrixClient extends EventEmitter { }); } - /** - * In encrypted rooms we can't rely on the server giving as the right - * notification count as it can't see the event type and message content. - * Therefore we increment the counters manually client-side - */ - private updateEncryptedRoomNotificationCount(event: MatrixEvent): void { - // TODO: Handle mentions received while the client is offline - // See also https://github.com/vector-im/element-web/issues/9069 - - const room = this.getRoom(event.getRoomId()); - const actions = this.pushProcessor.actionsForEvent(event); - event.setPushActions(actions); // Might as well while we're here - - if (!room) return; - // If the user has already read the message don't increase counters - if (room.hasUserReadEvent(this.getUserId(), event.getId())) return; - - const currentHighlightCount = room.getUnreadNotificationCount(NotificationCountType.Highlight); - const currentTotalCount = room.getUnreadNotificationCount(NotificationCountType.Total); - - const newHighlight = Boolean(actions?.tweaks?.highlight); - const newNotify = Boolean(actions?.notify); - - if (newHighlight) { - room.setUnreadNotificationCount(NotificationCountType.Highlight, currentHighlightCount + 1); - } - - if (newNotify) { - room.setUnreadNotificationCount(NotificationCountType.Total, currentTotalCount + 1); - } - } - /** * High level helper method to begin syncing and poll for new events. To listen for these * events, add a listener for {@link module:client~MatrixClient#event:"event"} diff --git a/src/models/event.ts b/src/models/event.ts index 05070cdac..317377b1a 100644 --- a/src/models/event.ts +++ b/src/models/event.ts @@ -157,7 +157,6 @@ export interface IDecryptOptions { export class MatrixEvent extends EventEmitter { private pushActions: IActionsObject = null; - private wirePushActions: IActionsObject = null; private _replacingEvent: MatrixEvent = null; private _localRedactionEvent: MatrixEvent = null; private _isCancelled = false; @@ -989,16 +988,7 @@ export class MatrixEvent extends EventEmitter { * @return {?Object} push actions */ public getPushActions(): IActionsObject | null { - return this.pushActions || this.wirePushActions; - } - - /** - * Get the push actions, if known, for this event - * - * @return {?Object} push actions - */ - public getWirePushActions(): IActionsObject | null { - return this.wirePushActions; + return this.pushActions; } /** @@ -1007,11 +997,7 @@ export class MatrixEvent extends EventEmitter { * @param {Object} pushActions push actions */ public setPushActions(pushActions: IActionsObject): void { - if (this._decryptionPromise) { - this.wirePushActions = pushActions; - } else { - this.pushActions = pushActions; - } + this.pushActions = pushActions; } /** diff --git a/src/sync.ts b/src/sync.ts index 53d245aeb..5cbe5c2eb 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -1222,18 +1222,24 @@ export class SyncApi { const accountDataEvents = this.mapSyncEventsFormat(joinObj.account_data); const encrypted = client.isRoomEncrypted(room.roomId); - // We do this first so it's correct when any of the events fire. We - // track unread notifications ourselves in encrypted rooms in - // MatrixClient::updateEncryptedRoomNotificationCount() - if (!encrypted && joinObj.unread_notifications) { + // we do this first so it's correct when any of the events fire + if (joinObj.unread_notifications) { room.setUnreadNotificationCount( NotificationCountType.Total, joinObj.unread_notifications.notification_count, ); - room.setUnreadNotificationCount( - NotificationCountType.Highlight, - joinObj.unread_notifications.highlight_count, - ); + + // We track unread notifications ourselves in encrypted rooms, so don't + // bother setting it here. We trust our calculations better than the + // server's for this case, and therefore will assume that our non-zero + // count is accurate. + if (!encrypted + || (encrypted && room.getUnreadNotificationCount(NotificationCountType.Highlight) <= 0)) { + room.setUnreadNotificationCount( + NotificationCountType.Highlight, + joinObj.unread_notifications.highlight_count, + ); + } } joinObj.timeline = joinObj.timeline || {} as ITimeline;