From 6ca731e9b69962a0023df2c5314562293bb4b6b6 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 8 Aug 2024 22:20:52 +0200 Subject: [PATCH] Change unread notification count to only cover the selected notification type (#31326) --- .../features/notifications_v2/index.tsx | 31 +--------- .../mastodon/selectors/notifications.ts | 57 +++++++++++++++++-- 2 files changed, 54 insertions(+), 34 deletions(-) diff --git a/app/javascript/mastodon/features/notifications_v2/index.tsx b/app/javascript/mastodon/features/notifications_v2/index.tsx index 21afd9516ee..63e602bdcc1 100644 --- a/app/javascript/mastodon/features/notifications_v2/index.tsx +++ b/app/javascript/mastodon/features/notifications_v2/index.tsx @@ -4,8 +4,6 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { Helmet } from 'react-helmet'; -import { createSelector } from '@reduxjs/toolkit'; - import { useDebouncedCallback } from 'use-debounce'; import DoneAllIcon from '@/material-icons/400-24px/done_all.svg?react'; @@ -27,16 +25,13 @@ import { selectUnreadNotificationGroupsCount, selectPendingNotificationGroupsCount, selectAnyPendingNotification, + selectNotificationGroups, } from 'mastodon/selectors/notifications'; import { selectNeedsNotificationPermission, - selectSettingsNotificationsExcludedTypes, - selectSettingsNotificationsQuickFilterActive, - selectSettingsNotificationsQuickFilterShow, selectSettingsNotificationsShowUnread, } from 'mastodon/selectors/settings'; import { useAppDispatch, useAppSelector } from 'mastodon/store'; -import type { RootState } from 'mastodon/store'; import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; import { submitMarkers } from '../../actions/markers'; @@ -62,34 +57,12 @@ const messages = defineMessages({ }, }); -const getNotifications = createSelector( - [ - selectSettingsNotificationsQuickFilterShow, - selectSettingsNotificationsQuickFilterActive, - selectSettingsNotificationsExcludedTypes, - (state: RootState) => state.notificationGroups.groups, - ], - (showFilterBar, allowedType, excludedTypes, notifications) => { - if (!showFilterBar || allowedType === 'all') { - // used if user changed the notification settings after loading the notifications from the server - // otherwise a list of notifications will come pre-filtered from the backend - // we need to turn it off for FilterBar in order not to block ourselves from seeing a specific category - return notifications.filter( - (item) => item.type === 'gap' || !excludedTypes.includes(item.type), - ); - } - return notifications.filter( - (item) => item.type === 'gap' || allowedType === item.type, - ); - }, -); - export const Notifications: React.FC<{ columnId?: string; multiColumn?: boolean; }> = ({ columnId, multiColumn }) => { const intl = useIntl(); - const notifications = useAppSelector(getNotifications); + const notifications = useAppSelector(selectNotificationGroups); const dispatch = useAppDispatch(); const isLoading = useAppSelector((s) => s.notificationGroups.isLoading); const hasMore = notifications.at(-1)?.type === 'gap'; diff --git a/app/javascript/mastodon/selectors/notifications.ts b/app/javascript/mastodon/selectors/notifications.ts index 962dedd6504..ea640406ea1 100644 --- a/app/javascript/mastodon/selectors/notifications.ts +++ b/app/javascript/mastodon/selectors/notifications.ts @@ -1,15 +1,62 @@ import { createSelector } from '@reduxjs/toolkit'; import { compareId } from 'mastodon/compare_id'; +import type { NotificationGroup } from 'mastodon/models/notification_group'; +import type { NotificationGap } from 'mastodon/reducers/notification_groups'; import type { RootState } from 'mastodon/store'; +import { + selectSettingsNotificationsExcludedTypes, + selectSettingsNotificationsQuickFilterActive, + selectSettingsNotificationsQuickFilterShow, +} from './settings'; + +const filterNotificationsByAllowedTypes = ( + showFilterBar: boolean, + allowedType: string, + excludedTypes: string[], + notifications: (NotificationGroup | NotificationGap)[], +) => { + if (!showFilterBar || allowedType === 'all') { + // used if user changed the notification settings after loading the notifications from the server + // otherwise a list of notifications will come pre-filtered from the backend + // we need to turn it off for FilterBar in order not to block ourselves from seeing a specific category + return notifications.filter( + (item) => item.type === 'gap' || !excludedTypes.includes(item.type), + ); + } + return notifications.filter( + (item) => item.type === 'gap' || allowedType === item.type, + ); +}; + +export const selectNotificationGroups = createSelector( + [ + selectSettingsNotificationsQuickFilterShow, + selectSettingsNotificationsQuickFilterActive, + selectSettingsNotificationsExcludedTypes, + (state: RootState) => state.notificationGroups.groups, + ], + filterNotificationsByAllowedTypes, +); + +const selectPendingNotificationGroups = createSelector( + [ + selectSettingsNotificationsQuickFilterShow, + selectSettingsNotificationsQuickFilterActive, + selectSettingsNotificationsExcludedTypes, + (state: RootState) => state.notificationGroups.pendingGroups, + ], + filterNotificationsByAllowedTypes, +); + export const selectUnreadNotificationGroupsCount = createSelector( [ (s: RootState) => s.notificationGroups.lastReadId, - (s: RootState) => s.notificationGroups.pendingGroups, - (s: RootState) => s.notificationGroups.groups, + selectNotificationGroups, + selectPendingNotificationGroups, ], - (notificationMarker, pendingGroups, groups) => { + (notificationMarker, groups, pendingGroups) => { return ( groups.filter( (group) => @@ -31,7 +78,7 @@ export const selectUnreadNotificationGroupsCount = createSelector( export const selectAnyPendingNotification = createSelector( [ (s: RootState) => s.notificationGroups.readMarkerId, - (s: RootState) => s.notificationGroups.groups, + selectNotificationGroups, ], (notificationMarker, groups) => { return groups.some( @@ -44,7 +91,7 @@ export const selectAnyPendingNotification = createSelector( ); export const selectPendingNotificationGroupsCount = createSelector( - [(s: RootState) => s.notificationGroups.pendingGroups], + [selectPendingNotificationGroups], (pendingGroups) => pendingGroups.filter((group) => group.type !== 'gap').length, );