Change group notifications unread markers to only be cleared when focusing/navigating again (#31325)

This commit is contained in:
Claire 2024-08-07 13:12:42 +02:00 committed by GitHub
parent af2aec1a82
commit 6f285bb2a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 33 additions and 3 deletions

View file

@ -26,6 +26,7 @@ import type { NotificationGap } from 'mastodon/reducers/notification_groups';
import { import {
selectUnreadNotificationGroupsCount, selectUnreadNotificationGroupsCount,
selectPendingNotificationGroupsCount, selectPendingNotificationGroupsCount,
selectAnyPendingNotification,
} from 'mastodon/selectors/notifications'; } from 'mastodon/selectors/notifications';
import { import {
selectNeedsNotificationPermission, selectNeedsNotificationPermission,
@ -95,7 +96,7 @@ export const Notifications: React.FC<{
const lastReadId = useAppSelector((s) => const lastReadId = useAppSelector((s) =>
selectSettingsNotificationsShowUnread(s) selectSettingsNotificationsShowUnread(s)
? s.notificationGroups.lastReadId ? s.notificationGroups.readMarkerId
: '0', : '0',
); );
@ -105,11 +106,13 @@ export const Notifications: React.FC<{
selectUnreadNotificationGroupsCount, selectUnreadNotificationGroupsCount,
); );
const anyPendingNotification = useAppSelector(selectAnyPendingNotification);
const isUnread = unreadNotificationsCount > 0; const isUnread = unreadNotificationsCount > 0;
const canMarkAsRead = const canMarkAsRead =
useAppSelector(selectSettingsNotificationsShowUnread) && useAppSelector(selectSettingsNotificationsShowUnread) &&
unreadNotificationsCount > 0; anyPendingNotification;
const needsNotificationPermission = useAppSelector( const needsNotificationPermission = useAppSelector(
selectNeedsNotificationPermission, selectNeedsNotificationPermission,

View file

@ -48,6 +48,7 @@ interface NotificationGroupsState {
scrolledToTop: boolean; scrolledToTop: boolean;
isLoading: boolean; isLoading: boolean;
lastReadId: string; lastReadId: string;
readMarkerId: string;
mounted: number; mounted: number;
isTabVisible: boolean; isTabVisible: boolean;
} }
@ -58,7 +59,8 @@ const initialState: NotificationGroupsState = {
scrolledToTop: false, scrolledToTop: false,
isLoading: false, isLoading: false,
// The following properties are used to track unread notifications // The following properties are used to track unread notifications
lastReadId: '0', // used for unread notifications lastReadId: '0', // used internally for unread notifications
readMarkerId: '0', // user-facing and updated when focus changes
mounted: 0, // number of mounted notification list components, usually 0 or 1 mounted: 0, // number of mounted notification list components, usually 0 or 1
isTabVisible: true, isTabVisible: true,
}; };
@ -284,6 +286,12 @@ function updateLastReadId(
} }
} }
function commitLastReadId(state: NotificationGroupsState) {
if (shouldMarkNewNotificationsAsRead(state)) {
state.readMarkerId = state.lastReadId;
}
}
export const notificationGroupsReducer = createReducer<NotificationGroupsState>( export const notificationGroupsReducer = createReducer<NotificationGroupsState>(
initialState, initialState,
(builder) => { (builder) => {
@ -457,6 +465,7 @@ export const notificationGroupsReducer = createReducer<NotificationGroupsState>(
compareId(state.lastReadId, mostRecentGroup.page_max_id) < 0 compareId(state.lastReadId, mostRecentGroup.page_max_id) < 0
) )
state.lastReadId = mostRecentGroup.page_max_id; state.lastReadId = mostRecentGroup.page_max_id;
commitLastReadId(state);
}) })
.addCase(fetchMarkers.fulfilled, (state, action) => { .addCase(fetchMarkers.fulfilled, (state, action) => {
if ( if (
@ -470,6 +479,7 @@ export const notificationGroupsReducer = createReducer<NotificationGroupsState>(
}) })
.addCase(mountNotifications, (state) => { .addCase(mountNotifications, (state) => {
state.mounted += 1; state.mounted += 1;
commitLastReadId(state);
updateLastReadId(state); updateLastReadId(state);
}) })
.addCase(unmountNotifications, (state) => { .addCase(unmountNotifications, (state) => {
@ -477,6 +487,7 @@ export const notificationGroupsReducer = createReducer<NotificationGroupsState>(
}) })
.addCase(focusApp, (state) => { .addCase(focusApp, (state) => {
state.isTabVisible = true; state.isTabVisible = true;
commitLastReadId(state);
updateLastReadId(state); updateLastReadId(state);
}) })
.addCase(unfocusApp, (state) => { .addCase(unfocusApp, (state) => {

View file

@ -27,6 +27,22 @@ export const selectUnreadNotificationGroupsCount = createSelector(
}, },
); );
// Whether there is any unread notification according to the user-facing state
export const selectAnyPendingNotification = createSelector(
[
(s: RootState) => s.notificationGroups.readMarkerId,
(s: RootState) => s.notificationGroups.groups,
],
(notificationMarker, groups) => {
return groups.some(
(group) =>
group.type !== 'gap' &&
group.page_max_id &&
compareId(group.page_max_id, notificationMarker) > 0,
);
},
);
export const selectPendingNotificationGroupsCount = createSelector( export const selectPendingNotificationGroupsCount = createSelector(
[(s: RootState) => s.notificationGroups.pendingGroups], [(s: RootState) => s.notificationGroups.pendingGroups],
(pendingGroups) => (pendingGroups) =>