diff --git a/ts/ConversationController.preload.ts b/ts/ConversationController.preload.ts index 3f103fca4b..f28593c204 100644 --- a/ts/ConversationController.preload.ts +++ b/ts/ConversationController.preload.ts @@ -391,13 +391,6 @@ export class ConversationController { const unreadStats = countAllConversationsUnreadStats( this.#_conversations.map( (conversation): ConversationPropsForUnreadStats | undefined => { - if ( - activeProfile && - !activeProfile.allowedMembers.has(conversation.id) - ) { - return undefined; - } - // Need to pull this out manually into the Redux shape // because `conversation.format()` can return cached props by the // time this runs @@ -414,6 +407,7 @@ export class ConversationController { } ), { + activeProfile, includeMuted: badgeCountMutedConversationsSetting ? 'setting-on' : 'setting-off', diff --git a/ts/services/notificationProfilesService.preload.ts b/ts/services/notificationProfilesService.preload.ts index 39ce8cc061..9672ef0a53 100644 --- a/ts/services/notificationProfilesService.preload.ts +++ b/ts/services/notificationProfilesService.preload.ts @@ -177,7 +177,7 @@ export class NotificationProfilesService { updateCurrentState(currentState, currentActiveProfile); // The active profile can influence the overall badge count - window.ConversationController.updateUnreadCount(); + window.Whisper.events.emit('updateUnreadCount'); } if (previousActiveProfile?.id === currentActiveProfileId) { diff --git a/ts/state/ducks/search.preload.ts b/ts/state/ducks/search.preload.ts index eda06221fa..b2102239a4 100644 --- a/ts/state/ducks/search.preload.ts +++ b/ts/state/ducks/search.preload.ts @@ -333,7 +333,10 @@ function shouldRemoveConversationFromUnreadList( conversation && (selectedConversationId == null || selectedConversationId !== conversation.id) && - !isConversationUnread(conversation, { includeMuted: 'force-exclude' }) + !isConversationUnread(conversation, { + activeProfile: undefined, + includeMuted: 'force-exclude', + }) ) { return true; } @@ -499,6 +502,7 @@ const doSearch = debounce( selectedConversation && state.search.conversationIds.includes(selectedConversationId) && !isConversationUnread(selectedConversation, { + activeProfile: undefined, includeMuted: 'force-include', }) ? selectedConversation diff --git a/ts/state/selectors/conversations.dom.ts b/ts/state/selectors/conversations.dom.ts index 2a5ce58688..784c6bc30b 100644 --- a/ts/state/selectors/conversations.dom.ts +++ b/ts/state/selectors/conversations.dom.ts @@ -89,6 +89,7 @@ import { } from '../../util/countUnreadStats.std.js'; import type { AllChatFoldersMutedStats } from '../../util/countMutedStats.std.js'; import { countAllChatFoldersMutedStats } from '../../util/countMutedStats.std.js'; +import { getActiveProfile } from './notificationProfiles.dom.js'; const { isNumber, pick } = lodash; @@ -699,8 +700,10 @@ export const getAllConversationsUnreadStats: StateSelector = createSelector( getAllConversations, getBadgeCountMutedConversations, - (conversations, badgeCountMutedConversations) => { + getActiveProfile, + (conversations, badgeCountMutedConversations, activeProfile) => { return countAllConversationsUnreadStats(conversations, { + activeProfile, includeMuted: badgeCountMutedConversations ? 'setting-on' : 'setting-off', @@ -713,11 +716,18 @@ export const getAllChatFoldersUnreadStats: StateSelector { + getActiveProfile, + ( + currentChatFolders, + allConversations, + badgeCountMutedConversations, + activeProfile + ) => { return countAllChatFoldersUnreadStats( currentChatFolders, allConversations, { + activeProfile, includeMuted: badgeCountMutedConversations ? 'setting-on' : 'setting-off', diff --git a/ts/test-node/util/countUnreadStats_test.node.ts b/ts/test-node/util/countUnreadStats_test.node.ts index 72ac734159..5a3ecb3d89 100644 --- a/ts/test-node/util/countUnreadStats_test.node.ts +++ b/ts/test-node/util/countUnreadStats_test.node.ts @@ -90,7 +90,10 @@ describe('countUnreadStats', () => { expected: boolean, includeMuted: UnreadStatsIncludeMuted = 'force-include' ) { - const actual = _canCountConversation(mockChat(chat), { includeMuted }); + const actual = _canCountConversation(mockChat(chat), { + activeProfile: undefined, + includeMuted, + }); assert.equal(actual, expected); } @@ -172,7 +175,10 @@ describe('countUnreadStats', () => { expected: boolean, includeMuted: UnreadStatsIncludeMuted = 'force-exclude' ) { - const actual = isConversationUnread(mockChat(chat), { includeMuted }); + const actual = isConversationUnread(mockChat(chat), { + activeProfile: undefined, + includeMuted, + }); assert.equal(actual, expected); } @@ -213,6 +219,7 @@ describe('countUnreadStats', () => { includeMuted: UnreadStatsIncludeMuted = 'force-exclude' ) { const actual = countConversationUnreadStats(mockChat(chat), { + activeProfile: undefined, includeMuted, }); assert.deepEqual(actual, mockStats(expected)); @@ -252,6 +259,7 @@ describe('countUnreadStats', () => { includeMuted: UnreadStatsIncludeMuted = 'force-exclude' ) { const actual = countAllConversationsUnreadStats(chats.map(mockChat), { + activeProfile: undefined, includeMuted, }); assert.deepEqual(actual, mockStats(expected)); @@ -323,7 +331,7 @@ describe('countUnreadStats', () => { const actual = countAllChatFoldersUnreadStats( CurrentChatFolders.fromArray(folders), chats.map(mockChat), - { includeMuted } + { activeProfile: undefined, includeMuted } ); assert.deepEqual(actual, expected); diff --git a/ts/util/countUnreadStats.std.ts b/ts/util/countUnreadStats.std.ts index d732fbc777..fc2bfe2f56 100644 --- a/ts/util/countUnreadStats.std.ts +++ b/ts/util/countUnreadStats.std.ts @@ -1,12 +1,14 @@ // Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import type { ConversationType } from '../state/ducks/conversations.preload.js'; import { isConversationInChatFolder } from '../types/ChatFolder.std.js'; -import type { ChatFolderId } from '../types/ChatFolder.std.js'; import { CurrentChatFolders } from '../types/CurrentChatFolders.std.js'; import { isConversationMuted } from './isConversationMuted.std.js'; +import type { ConversationType } from '../state/ducks/conversations.preload.js'; +import type { ChatFolderId } from '../types/ChatFolder.std.js'; +import type { NotificationProfileType } from '../types/NotificationProfile.std.js'; + type MutableUnreadStats = { /** * Total of `conversation.unreadCount` @@ -53,6 +55,7 @@ export type UnreadStatsIncludeMuted = export type UnreadStatsOptions = Readonly<{ includeMuted: UnreadStatsIncludeMuted; + activeProfile: NotificationProfileType | undefined; }>; export type ConversationPropsForUnreadStats = Readonly< @@ -93,7 +96,9 @@ export function _canCountConversation( if ( _shouldExcludeMuted(options.includeMuted) && - isConversationMuted(conversation) + (isConversationMuted(conversation) || + (options.activeProfile && + !options.activeProfile.allowedMembers.has(conversation.id))) ) { return false; } diff --git a/ts/util/filterAndSortConversations.std.ts b/ts/util/filterAndSortConversations.std.ts index 8f2c7aa71f..5b321aa636 100644 --- a/ts/util/filterAndSortConversations.std.ts +++ b/ts/util/filterAndSortConversations.std.ts @@ -72,7 +72,10 @@ function filterConversationsByUnread( includeMuted: UnreadStatsIncludeMuted ): Array { return conversations.filter(conversation => { - return isConversationUnread(conversation, { includeMuted }); + return isConversationUnread(conversation, { + activeProfile: undefined, + includeMuted, + }); }); }