Add notifications store trimming

Claire 2024-06-27 14:47:37 +02:00
parent 7109805713
commit 1609fcb44b
3 changed files with 26 additions and 4 deletions

View File

@ -113,6 +113,10 @@ export const processNewNotificationForGroups = createAppAsyncThunk(
export const loadPending = createAction('notificationGroups/loadPending'); export const loadPending = createAction('notificationGroups/loadPending');
export const updateScrollPosition = createAction<{ top: boolean }>(
'notificationGroups/updateScrollPosition',
);
export const setNotificationsFilter = createAppAsyncThunk( export const setNotificationsFilter = createAppAsyncThunk(
'notifications/filter/set', 'notifications/filter/set',
({ filterType }: { filterType: string }, { dispatch }) => { ({ filterType }: { filterType: string }, { dispatch }) => {

View File

@ -13,6 +13,7 @@ import NotificationsIcon from '@/material-icons/400-24px/notifications-fill.svg?
import { import {
fetchNotifications, fetchNotifications,
fetchNotificationsGap, fetchNotificationsGap,
updateScrollPosition,
loadPending, loadPending,
} from 'mastodon/actions/notification_groups'; } from 'mastodon/actions/notification_groups';
import { compareId } from 'mastodon/compare_id'; import { compareId } from 'mastodon/compare_id';
@ -37,7 +38,6 @@ import type { RootState } from 'mastodon/store';
import { addColumn, removeColumn, moveColumn } from '../../actions/columns'; import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
import { submitMarkers } from '../../actions/markers'; import { submitMarkers } from '../../actions/markers';
import { import {
scrollTopNotifications,
// mountNotifications, // mountNotifications,
// unmountNotifications, // unmountNotifications,
markNotificationsAsRead, markNotificationsAsRead,
@ -146,7 +146,7 @@ export const Notifications: React.FC<{
return () => { return () => {
// dispatch(unmountNotifications()); // dispatch(unmountNotifications());
// dispatch(scrollTopNotifications(false)); // dispatch(updateScrollPosition({ top: false }));
}; };
}, [dispatch]); }, [dispatch]);
@ -171,11 +171,11 @@ export const Notifications: React.FC<{
}, [dispatch]); }, [dispatch]);
const handleScrollToTop = useDebouncedCallback(() => { const handleScrollToTop = useDebouncedCallback(() => {
dispatch(scrollTopNotifications(true)); dispatch(updateScrollPosition({ top: true }));
}, 100); }, 100);
const handleScroll = useDebouncedCallback(() => { const handleScroll = useDebouncedCallback(() => {
dispatch(scrollTopNotifications(false)); dispatch(updateScrollPosition({ top: false }));
}, 100); }, 100);
useEffect(() => { useEffect(() => {

View File

@ -13,6 +13,7 @@ import {
fetchNotificationsGap, fetchNotificationsGap,
processNewNotificationForGroups, processNewNotificationForGroups,
loadPending, loadPending,
updateScrollPosition,
} from 'mastodon/actions/notification_groups'; } from 'mastodon/actions/notification_groups';
import { import {
disconnectTimeline, disconnectTimeline,
@ -28,6 +29,8 @@ import {
} from 'mastodon/models/notification_group'; } from 'mastodon/models/notification_group';
import type { NotificationGroup } from 'mastodon/models/notification_group'; import type { NotificationGroup } from 'mastodon/models/notification_group';
const NOTIFICATIONS_TRIM_LIMIT = 50;
export interface NotificationGap { export interface NotificationGap {
type: 'gap'; type: 'gap';
maxId?: string; maxId?: string;
@ -37,12 +40,14 @@ export interface NotificationGap {
interface NotificationGroupsState { interface NotificationGroupsState {
groups: (NotificationGroup | NotificationGap)[]; groups: (NotificationGroup | NotificationGap)[];
pendingGroups: (NotificationGroup | NotificationGap)[]; pendingGroups: (NotificationGroup | NotificationGap)[];
scrolledToTop: boolean;
isLoading: boolean; isLoading: boolean;
} }
const initialState: NotificationGroupsState = { const initialState: NotificationGroupsState = {
groups: [], groups: [],
pendingGroups: [], // holds pending groups in slow mode pendingGroups: [], // holds pending groups in slow mode
scrolledToTop: false,
isLoading: false, isLoading: false,
}; };
@ -220,6 +225,13 @@ function processNewNotification(
} }
} }
function trimNotifications(state: NotificationGroupsState) {
// TODO: is there more to it?
if (state.scrolledToTop) {
state.groups.splice(NOTIFICATIONS_TRIM_LIMIT);
}
}
export const notificationsGroupsReducer = export const notificationsGroupsReducer =
createReducer<NotificationGroupsState>(initialState, (builder) => { createReducer<NotificationGroupsState>(initialState, (builder) => {
builder builder
@ -315,6 +327,7 @@ export const notificationsGroupsReducer =
usePendingItems ? state.pendingGroups : state.groups, usePendingItems ? state.pendingGroups : state.groups,
notification, notification,
); );
trimNotifications(state);
}) })
.addCase(disconnectTimeline, (state, action) => { .addCase(disconnectTimeline, (state, action) => {
if (action.payload.timeline === 'home') { if (action.payload.timeline === 'home') {
@ -368,12 +381,17 @@ export const notificationsGroupsReducer =
} }
} }
} }
trimNotifications(state);
}); });
// Then build the consolidated list and clear pending groups // Then build the consolidated list and clear pending groups
state.groups = state.pendingGroups.concat(state.groups); state.groups = state.pendingGroups.concat(state.groups);
state.pendingGroups = []; state.pendingGroups = [];
}) })
.addCase(updateScrollPosition, (state, action) => {
state.scrolledToTop = action.payload.top;
trimNotifications(state);
})
.addMatcher( .addMatcher(
isAnyOf(authorizeFollowRequestSuccess, rejectFollowRequestSuccess), isAnyOf(authorizeFollowRequestSuccess, rejectFollowRequestSuccess),
(state, action) => { (state, action) => {