diff --git a/spec/unit/event-timeline-set.spec.ts b/spec/unit/event-timeline-set.spec.ts index e86840ec5b2..a817127569c 100644 --- a/spec/unit/event-timeline-set.spec.ts +++ b/spec/unit/event-timeline-set.spec.ts @@ -303,13 +303,8 @@ describe("EventTimelineSet", () => { messageEventIsDecryptionFailureSpy.mockReturnValue(true); replyEventIsDecryptionFailureSpy.mockReturnValue(true); - messageEvent.emit( - MatrixEventEvent.Decrypted, - messageEvent, - undefined, - messageEvent.getPushDetails(), - ); - replyEvent.emit(MatrixEventEvent.Decrypted, replyEvent, undefined, replyEvent.getPushDetails()); + messageEvent.emit(MatrixEventEvent.Decrypted, messageEvent); + replyEvent.emit(MatrixEventEvent.Decrypted, replyEvent); // simulate decryption messageEventIsDecryptionFailureSpy.mockReturnValue(false); @@ -318,13 +313,8 @@ describe("EventTimelineSet", () => { messageEventShouldAttemptDecryptionSpy.mockReturnValue(false); replyEventShouldAttemptDecryptionSpy.mockReturnValue(false); - messageEvent.emit( - MatrixEventEvent.Decrypted, - messageEvent, - undefined, - messageEvent.getPushDetails(), - ); - replyEvent.emit(MatrixEventEvent.Decrypted, replyEvent, undefined, replyEvent.getPushDetails()); + messageEvent.emit(MatrixEventEvent.Decrypted, messageEvent); + replyEvent.emit(MatrixEventEvent.Decrypted, replyEvent); }); itShouldReturnTheRelatedEvents(); diff --git a/spec/unit/notifications.spec.ts b/spec/unit/notifications.spec.ts index 2f845f34d76..b0ebd23d952 100644 --- a/spec/unit/notifications.spec.ts +++ b/spec/unit/notifications.spec.ts @@ -54,7 +54,7 @@ describe("fixNotificationCountOnDecryption", () => { mockClient = getMockClientWithEventEmitter({ ...mockClientMethodsUser(), isInitialSyncComplete: jest.fn().mockReturnValue(false), - getPushActionsForEvent: jest.fn((ev) => event.getPushActions() ?? mkPushAction(true, true)), + getPushActionsForEvent: jest.fn().mockReturnValue(mkPushAction(true, true)), getRoom: jest.fn().mockImplementation(() => room), decryptEventIfNeeded: jest.fn().mockResolvedValue(void 0), supportsThreads: jest.fn().mockReturnValue(true), @@ -125,15 +125,15 @@ describe("fixNotificationCountOnDecryption", () => { room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 1); room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 0); - event.getPushActions = jest.fn().mockReturnValue(mkPushAction(true, true)); - threadEvent.getPushActions = jest.fn().mockReturnValue(mkPushAction(true, true)); + event.getPushActions = jest.fn().mockReturnValue(mkPushAction(false, false)); + threadEvent.getPushActions = jest.fn().mockReturnValue(mkPushAction(false, false)); }); it("changes the room count to highlight on decryption", () => { expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toBe(2); expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toBe(0); - fixNotificationCountOnDecryption(mockClient, event, {}); + fixNotificationCountOnDecryption(mockClient, event); expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toBe(3); expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toBe(1); @@ -143,7 +143,7 @@ describe("fixNotificationCountOnDecryption", () => { room.setUnreadNotificationCount(NotificationCountType.Total, 0); room.setUnreadNotificationCount(NotificationCountType.Highlight, 0); - fixNotificationCountOnDecryption(mockClient, event, {}); + fixNotificationCountOnDecryption(mockClient, event); expect(room.getRoomUnreadNotificationCount(NotificationCountType.Total)).toBe(1); expect(room.getRoomUnreadNotificationCount(NotificationCountType.Highlight)).toBe(1); @@ -153,7 +153,7 @@ describe("fixNotificationCountOnDecryption", () => { expect(room.getThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total)).toBe(1); expect(room.getThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight)).toBe(0); - fixNotificationCountOnDecryption(mockClient, threadEvent, {}); + fixNotificationCountOnDecryption(mockClient, threadEvent); expect(room.getThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total)).toBe(2); expect(room.getThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight)).toBe(1); @@ -163,7 +163,7 @@ describe("fixNotificationCountOnDecryption", () => { room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 0); room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 0); - fixNotificationCountOnDecryption(mockClient, event, {}); + fixNotificationCountOnDecryption(mockClient, event); expect(room.getThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total)).toBe(0); expect(room.getThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight)).toBe(0); @@ -187,7 +187,7 @@ describe("fixNotificationCountOnDecryption", () => { event: true, }); - fixNotificationCountOnDecryption(mockClient, unknownThreadEvent, {}); + fixNotificationCountOnDecryption(mockClient, unknownThreadEvent); expect(room.getThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total)).toBe(0); expect(room.getThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight)).toBe(0); @@ -201,7 +201,7 @@ describe("fixNotificationCountOnDecryption", () => { event.getPushActions = jest.fn().mockReturnValue(mkPushAction(true, false)); mockClient.getPushActionsForEvent = jest.fn().mockReturnValue(mkPushAction(false, false)); - fixNotificationCountOnDecryption(mockClient, event, {}); + fixNotificationCountOnDecryption(mockClient, event); expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toBe(0); expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toBe(0); }); @@ -213,7 +213,7 @@ describe("fixNotificationCountOnDecryption", () => { threadEvent.getPushActions = jest.fn().mockReturnValue(mkPushAction(true, false)); mockClient.getPushActionsForEvent = jest.fn().mockReturnValue(mkPushAction(false, false)); - fixNotificationCountOnDecryption(mockClient, event, {}); + fixNotificationCountOnDecryption(mockClient, event); expect(room.getThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total)).toBe(0); expect(room.getThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight)).toBe(0); }); @@ -231,15 +231,4 @@ describe("fixNotificationCountOnDecryption", () => { room.setThreadUnreadNotificationCount("$123", NotificationCountType.Highlight, 5); expect(cb).toHaveBeenLastCalledWith({ highlight: 5 }, "$123"); }); - - it("should not increment notification count where event was already contributing notification", () => { - expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toBe(2); - expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toBe(0); - - event.getPushActions = jest.fn().mockReturnValue(mkPushAction(true, false)); - fixNotificationCountOnDecryption(mockClient, event, { actions: { notify: true, tweaks: {} } }); - - expect(room.getUnreadNotificationCount(NotificationCountType.Total)).toBe(2); - expect(room.getUnreadNotificationCount(NotificationCountType.Highlight)).toBe(0); - }); }); diff --git a/spec/unit/room-state.spec.ts b/spec/unit/room-state.spec.ts index 261c7b120e8..c8d249870d8 100644 --- a/spec/unit/room-state.spec.ts +++ b/spec/unit/room-state.spec.ts @@ -1037,12 +1037,7 @@ describe("RoomState", function () { // this event is a message after decryption decryptingRelatedEvent.event.type = EventType.RoomMessage; - decryptingRelatedEvent.emit( - MatrixEventEvent.Decrypted, - decryptingRelatedEvent, - undefined, - decryptingRelatedEvent.getPushDetails(), - ); + decryptingRelatedEvent.emit(MatrixEventEvent.Decrypted, decryptingRelatedEvent); expect(addLocationsSpy).not.toHaveBeenCalled(); }); diff --git a/spec/unit/room.spec.ts b/spec/unit/room.spec.ts index df57ea7355b..5dee474459f 100644 --- a/spec/unit/room.spec.ts +++ b/spec/unit/room.spec.ts @@ -3428,13 +3428,13 @@ describe("Room", function () { expect(room.polls.get(pollStartEventId)).toBeUndefined(); // now emit a Decrypted event but keep the decryption failure - pollStartEvent.emit(MatrixEventEvent.Decrypted, pollStartEvent, undefined, pollStartEvent.getPushDetails()); + pollStartEvent.emit(MatrixEventEvent.Decrypted, pollStartEvent); // still do not expect a poll to show up for the room expect(room.polls.get(pollStartEventId)).toBeUndefined(); // clear decryption failure and emit a Decrypted event again isDecryptionFailureSpy.mockRestore(); - pollStartEvent.emit(MatrixEventEvent.Decrypted, pollStartEvent, undefined, pollStartEvent.getPushDetails()); + pollStartEvent.emit(MatrixEventEvent.Decrypted, pollStartEvent); // the poll should now show up in the room's polls const poll = room.polls.get(pollStartEventId); diff --git a/src/client.ts b/src/client.ts index 7dc4d211f14..f50a1c74058 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1371,8 +1371,8 @@ export class MatrixClient extends TypedEventEmitter { - fixNotificationCountOnDecryption(this, event, pushDetails); + this.on(MatrixEventEvent.Decrypted, (event) => { + fixNotificationCountOnDecryption(this, event); }); // Like above, we have to listen for read receipts from ourselves in order to @@ -9851,23 +9851,26 @@ export class MatrixClient extends TypedEventEmitter 0) { + // TODO: Handle mentions received while the client is offline + // See also https://github.com/vector-im/element-web/issues/9069 + let newCount = currentHighlightCount; + if (newHighlight && !oldHighlight) newCount++; + if (!newHighlight && oldHighlight) newCount--; + + if (isThreadEvent) { + room.setThreadUnreadNotificationCount(event.threadRootId, NotificationCountType.Highlight, newCount); } else { - oldValue = !!oldActions?.tweaks?.highlight; - newValue = !!actions?.tweaks?.highlight; + room.setUnreadNotificationCount(NotificationCountType.Highlight, newCount); } + } - if (oldValue !== newValue || count > 0) { - if (newValue && !oldValue) count++; - if (!newValue && oldValue) count--; + // Total count is used to typically increment a room notification counter, but not loudly highlight it. + const currentTotalCount = room.getUnreadCountForEventContext(NotificationCountType.Total, event); - if (isThreadEvent) { - room.setThreadUnreadNotificationCount(event.threadRootId, type, count); - } else { - room.setUnreadNotificationCount(type, count); - } + // `notify` is used in practice for incrementing the total count + const newNotify = !!actions?.notify; + + // The room total count is NEVER incremented by the server for encrypted rooms. We basically ignore + // the server here as it's always going to tell us to increment for encrypted events. + if (newNotify) { + if (isThreadEvent) { + room.setThreadUnreadNotificationCount( + event.threadRootId, + NotificationCountType.Total, + currentTotalCount + 1, + ); + } else { + room.setUnreadNotificationCount(NotificationCountType.Total, currentTotalCount + 1); } } } diff --git a/src/models/event.ts b/src/models/event.ts index 693fa87c2eb..72c6212db9a 100644 --- a/src/models/event.ts +++ b/src/models/event.ts @@ -226,7 +226,7 @@ export type MatrixEventHandlerMap = { * @param event - The matrix event which has been decrypted * @param err - The error that occurred during decryption, or `undefined` if no error occurred. */ - [MatrixEventEvent.Decrypted]: (event: MatrixEvent, err: Error | undefined, pushDetails: PushDetails) => void; + [MatrixEventEvent.Decrypted]: (event: MatrixEvent, err?: Error) => void; [MatrixEventEvent.BeforeRedaction]: (event: MatrixEvent, redactionEvent: MatrixEvent) => void; [MatrixEventEvent.VisibilityChange]: (event: MatrixEvent, visible: boolean) => void; [MatrixEventEvent.LocalEventIdReplaced]: (event: MatrixEvent) => void; @@ -916,8 +916,6 @@ export class MatrixEvent extends TypedEventEmitter