2024-07-19 00:36:09 +10:00
|
|
|
import { createSelector } from '@reduxjs/toolkit';
|
|
|
|
|
|
|
|
import { compareId } from 'mastodon/compare_id';
|
2024-08-09 06:20:52 +10:00
|
|
|
import type { NotificationGroup } from 'mastodon/models/notification_group';
|
|
|
|
import type { NotificationGap } from 'mastodon/reducers/notification_groups';
|
2024-07-19 00:36:09 +10:00
|
|
|
import type { RootState } from 'mastodon/store';
|
|
|
|
|
2024-08-09 06:20:52 +10:00
|
|
|
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,
|
|
|
|
);
|
|
|
|
|
2024-07-19 00:36:09 +10:00
|
|
|
export const selectUnreadNotificationGroupsCount = createSelector(
|
|
|
|
[
|
|
|
|
(s: RootState) => s.notificationGroups.lastReadId,
|
2024-08-09 06:20:52 +10:00
|
|
|
selectNotificationGroups,
|
|
|
|
selectPendingNotificationGroups,
|
2024-07-19 00:36:09 +10:00
|
|
|
],
|
2024-08-09 06:20:52 +10:00
|
|
|
(notificationMarker, groups, pendingGroups) => {
|
2024-07-19 00:36:09 +10:00
|
|
|
return (
|
|
|
|
groups.filter(
|
|
|
|
(group) =>
|
|
|
|
group.type !== 'gap' &&
|
|
|
|
group.page_max_id &&
|
|
|
|
compareId(group.page_max_id, notificationMarker) > 0,
|
|
|
|
).length +
|
|
|
|
pendingGroups.filter(
|
|
|
|
(group) =>
|
|
|
|
group.type !== 'gap' &&
|
|
|
|
group.page_max_id &&
|
|
|
|
compareId(group.page_max_id, notificationMarker) > 0,
|
|
|
|
).length
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2024-08-07 21:12:42 +10:00
|
|
|
// Whether there is any unread notification according to the user-facing state
|
|
|
|
export const selectAnyPendingNotification = createSelector(
|
|
|
|
[
|
|
|
|
(s: RootState) => s.notificationGroups.readMarkerId,
|
2024-08-09 06:20:52 +10:00
|
|
|
selectNotificationGroups,
|
2024-08-07 21:12:42 +10:00
|
|
|
],
|
|
|
|
(notificationMarker, groups) => {
|
|
|
|
return groups.some(
|
|
|
|
(group) =>
|
|
|
|
group.type !== 'gap' &&
|
|
|
|
group.page_max_id &&
|
|
|
|
compareId(group.page_max_id, notificationMarker) > 0,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2024-07-19 00:36:09 +10:00
|
|
|
export const selectPendingNotificationGroupsCount = createSelector(
|
2024-08-09 06:20:52 +10:00
|
|
|
[selectPendingNotificationGroups],
|
2024-07-19 00:36:09 +10:00
|
|
|
(pendingGroups) =>
|
|
|
|
pendingGroups.filter((group) => group.type !== 'gap').length,
|
|
|
|
);
|