Change group notifications unread markers to only be cleared when focusing/navigating again (#31325)
This commit is contained in:
parent
af2aec1a82
commit
6f285bb2a6
3 changed files with 33 additions and 3 deletions
|
@ -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,
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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) =>
|
||||||
|
|
Loading…
Reference in a new issue