Chat folders: for unread, check setting and active notification profile

This commit is contained in:
Scott Nonnenberg
2025-11-06 07:06:52 +10:00
committed by GitHub
parent aa78798be6
commit 1925044e9d
7 changed files with 42 additions and 18 deletions

View File

@@ -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',

View File

@@ -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) {

View File

@@ -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

View File

@@ -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<UnreadStats> =
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<AllChatFoldersUnreadSta
getCurrentChatFolders,
getAllConversations,
getBadgeCountMutedConversations,
(currentChatFolders, allConversations, badgeCountMutedConversations) => {
getActiveProfile,
(
currentChatFolders,
allConversations,
badgeCountMutedConversations,
activeProfile
) => {
return countAllChatFoldersUnreadStats(
currentChatFolders,
allConversations,
{
activeProfile,
includeMuted: badgeCountMutedConversations
? 'setting-on'
: 'setting-off',

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -72,7 +72,10 @@ function filterConversationsByUnread(
includeMuted: UnreadStatsIncludeMuted
): Array<ConversationType> {
return conversations.filter(conversation => {
return isConversationUnread(conversation, { includeMuted });
return isConversationUnread(conversation, {
activeProfile: undefined,
includeMuted,
});
});
}