pl-fe: Remove notification queue from reducer
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
dca8f15279
commit
74d0d4c60b
3 changed files with 45 additions and 101 deletions
|
@ -24,7 +24,6 @@ import type { AppDispatch, RootState } from 'pl-fe/store';
|
||||||
const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE' as const;
|
const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE' as const;
|
||||||
const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP' as const;
|
const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP' as const;
|
||||||
const NOTIFICATIONS_UPDATE_QUEUE = 'NOTIFICATIONS_UPDATE_QUEUE' as const;
|
const NOTIFICATIONS_UPDATE_QUEUE = 'NOTIFICATIONS_UPDATE_QUEUE' as const;
|
||||||
const NOTIFICATIONS_DEQUEUE = 'NOTIFICATIONS_DEQUEUE' as const;
|
|
||||||
|
|
||||||
const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST' as const;
|
const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST' as const;
|
||||||
const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS' as const;
|
const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS' as const;
|
||||||
|
@ -100,8 +99,6 @@ const updateNotificationsQueue = (notification: BaseNotification, intlMessages:
|
||||||
|
|
||||||
let filtered: boolean | null = false;
|
let filtered: boolean | null = false;
|
||||||
|
|
||||||
const isOnNotificationsPage = curPath === '/notifications';
|
|
||||||
|
|
||||||
if (notification.type === 'mention' || notification.type === 'status') {
|
if (notification.type === 'mention' || notification.type === 'status') {
|
||||||
const regex = regexFromFilters(filters);
|
const regex = regexFromFilters(filters);
|
||||||
const searchIndex = notification.status.spoiler_text + '\n' + unescapeHTML(notification.status.content);
|
const searchIndex = notification.status.spoiler_text + '\n' + unescapeHTML(notification.status.content);
|
||||||
|
@ -139,37 +136,7 @@ const updateNotificationsQueue = (notification: BaseNotification, intlMessages:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOnNotificationsPage) {
|
dispatch(updateNotifications(notification));
|
||||||
dispatch({
|
|
||||||
type: NOTIFICATIONS_UPDATE_QUEUE,
|
|
||||||
notification,
|
|
||||||
intlMessages,
|
|
||||||
intlLocale,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dispatch(updateNotifications(notification));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const dequeueNotifications = () =>
|
|
||||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
|
||||||
const queuedNotifications = getState().notifications.queuedNotifications;
|
|
||||||
const totalQueuedNotificationsCount = getState().notifications.totalQueuedNotificationsCount;
|
|
||||||
|
|
||||||
if (totalQueuedNotificationsCount === 0) {
|
|
||||||
return;
|
|
||||||
} else if (totalQueuedNotificationsCount > 0 && totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) {
|
|
||||||
queuedNotifications.forEach((block) => {
|
|
||||||
dispatch(updateNotifications(block.notification));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dispatch(expandNotifications());
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: NOTIFICATIONS_DEQUEUE,
|
|
||||||
});
|
|
||||||
dispatch(markReadNotifications());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const excludeTypesFromFilter = (filters: string[]) => NOTIFICATION_TYPES.filter(item => !filters.includes(item));
|
const excludeTypesFromFilter = (filters: string[]) => NOTIFICATION_TYPES.filter(item => !filters.includes(item));
|
||||||
|
@ -295,7 +262,6 @@ export {
|
||||||
NOTIFICATIONS_UPDATE,
|
NOTIFICATIONS_UPDATE,
|
||||||
NOTIFICATIONS_UPDATE_NOOP,
|
NOTIFICATIONS_UPDATE_NOOP,
|
||||||
NOTIFICATIONS_UPDATE_QUEUE,
|
NOTIFICATIONS_UPDATE_QUEUE,
|
||||||
NOTIFICATIONS_DEQUEUE,
|
|
||||||
NOTIFICATIONS_EXPAND_REQUEST,
|
NOTIFICATIONS_EXPAND_REQUEST,
|
||||||
NOTIFICATIONS_EXPAND_SUCCESS,
|
NOTIFICATIONS_EXPAND_SUCCESS,
|
||||||
NOTIFICATIONS_EXPAND_FAIL,
|
NOTIFICATIONS_EXPAND_FAIL,
|
||||||
|
@ -309,7 +275,6 @@ export {
|
||||||
type FilterType,
|
type FilterType,
|
||||||
updateNotifications,
|
updateNotifications,
|
||||||
updateNotificationsQueue,
|
updateNotificationsQueue,
|
||||||
dequeueNotifications,
|
|
||||||
expandNotifications,
|
expandNotifications,
|
||||||
expandNotificationsRequest,
|
expandNotificationsRequest,
|
||||||
expandNotificationsSuccess,
|
expandNotificationsSuccess,
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import React, { useCallback, useEffect, useRef } from 'react';
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
expandNotifications,
|
expandNotifications,
|
||||||
|
markReadNotifications,
|
||||||
scrollTopNotifications,
|
scrollTopNotifications,
|
||||||
dequeueNotifications,
|
|
||||||
} from 'pl-fe/actions/notifications';
|
} from 'pl-fe/actions/notifications';
|
||||||
import PullToRefresh from 'pl-fe/components/pull-to-refresh';
|
import PullToRefresh from 'pl-fe/components/pull-to-refresh';
|
||||||
import ScrollTopButton from 'pl-fe/components/scroll-top-button';
|
import ScrollTopButton from 'pl-fe/components/scroll-top-button';
|
||||||
|
@ -31,7 +31,27 @@ const messages = defineMessages({
|
||||||
|
|
||||||
const getNotifications = createSelector([
|
const getNotifications = createSelector([
|
||||||
(state: RootState) => state.notifications.items.toArray(),
|
(state: RootState) => state.notifications.items.toArray(),
|
||||||
], (notifications) => notifications.map(([_, notification]) => notification).filter(item => item !== null));
|
(_, topNotification?: string) => topNotification,
|
||||||
|
], (notifications, topNotificationId) => {
|
||||||
|
const allNotifications = notifications.map(([_, notification]) => notification).filter(item => item !== null);
|
||||||
|
|
||||||
|
if (topNotificationId) {
|
||||||
|
const queuedNotificationCount = allNotifications.findIndex((notification) =>
|
||||||
|
notification.most_recent_notification_id <= topNotificationId,
|
||||||
|
);
|
||||||
|
const displayedNotifications = allNotifications.slice(queuedNotificationCount);
|
||||||
|
|
||||||
|
return {
|
||||||
|
queuedNotificationCount,
|
||||||
|
displayedNotifications,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
queuedNotificationCount: 0,
|
||||||
|
displayedNotifications: allNotifications,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
const Notifications = () => {
|
const Notifications = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
@ -40,11 +60,11 @@ const Notifications = () => {
|
||||||
|
|
||||||
const showFilterBar = settings.notifications.quickFilter.show;
|
const showFilterBar = settings.notifications.quickFilter.show;
|
||||||
const activeFilter = settings.notifications.quickFilter.active;
|
const activeFilter = settings.notifications.quickFilter.active;
|
||||||
const notifications = useAppSelector(state => getNotifications(state));
|
const [topNotification, setTopNotification] = useState<string>();
|
||||||
|
const { queuedNotificationCount, displayedNotifications } = useAppSelector(state => getNotifications(state, topNotification));
|
||||||
const isLoading = useAppSelector(state => state.notifications.isLoading);
|
const isLoading = useAppSelector(state => state.notifications.isLoading);
|
||||||
// const isUnread = useAppSelector(state => state.notifications.unread > 0);
|
// const isUnread = useAppSelector(state => state.notifications.unread > 0);
|
||||||
const hasMore = useAppSelector(state => state.notifications.hasMore);
|
const hasMore = useAppSelector(state => state.notifications.hasMore);
|
||||||
const totalQueuedNotificationsCount = useAppSelector(state => state.notifications.totalQueuedNotificationsCount || 0);
|
|
||||||
|
|
||||||
const scrollableContentRef = useRef<Array<JSX.Element> | null>(null);
|
const scrollableContentRef = useRef<Array<JSX.Element> | null>(null);
|
||||||
|
|
||||||
|
@ -53,26 +73,26 @@ const Notifications = () => {
|
||||||
// };
|
// };
|
||||||
|
|
||||||
const handleLoadOlder = useCallback(debounce(() => {
|
const handleLoadOlder = useCallback(debounce(() => {
|
||||||
const minId = notifications.reduce<string | undefined>(
|
const minId = displayedNotifications.reduce<string | undefined>(
|
||||||
(minId, notification) => minId && notification.page_min_id && notification.page_min_id > minId
|
(minId, notification) => minId && notification.page_min_id && notification.page_min_id > minId
|
||||||
? minId
|
? minId
|
||||||
: notification.page_min_id,
|
: notification.page_min_id,
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
dispatch(expandNotifications({ maxId: minId }));
|
dispatch(expandNotifications({ maxId: minId }));
|
||||||
}, 300, { leading: true }), [notifications]);
|
}, 300, { leading: true }), [displayedNotifications]);
|
||||||
|
|
||||||
const handleScroll = useCallback(debounce((startIndex?: number) => {
|
const handleScroll = useCallback(debounce((startIndex?: number) => {
|
||||||
dispatch(scrollTopNotifications(startIndex === 0));
|
dispatch(scrollTopNotifications(startIndex === 0));
|
||||||
}, 100), []);
|
}, 100), []);
|
||||||
|
|
||||||
const handleMoveUp = (id: string) => {
|
const handleMoveUp = (id: string) => {
|
||||||
const elementIndex = notifications.findIndex(item => item !== null && item.group_key === id) - 1;
|
const elementIndex = displayedNotifications.findIndex(item => item !== null && item.group_key === id) - 1;
|
||||||
_selectChild(elementIndex);
|
_selectChild(elementIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMoveDown = (id: string) => {
|
const handleMoveDown = (id: string) => {
|
||||||
const elementIndex = notifications.findIndex(item => item !== null && item.group_key === id) + 1;
|
const elementIndex = displayedNotifications.findIndex(item => item !== null && item.group_key === id) + 1;
|
||||||
_selectChild(elementIndex);
|
_selectChild(elementIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,7 +104,8 @@ const Notifications = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDequeueNotifications = useCallback(() => {
|
const handleDequeueNotifications = useCallback(() => {
|
||||||
dispatch(dequeueNotifications());
|
setTopNotification(undefined);
|
||||||
|
dispatch(markReadNotifications());
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleRefresh = useCallback(() => dispatch(expandNotifications()), []);
|
const handleRefresh = useCallback(() => dispatch(expandNotifications()), []);
|
||||||
|
@ -100,6 +121,11 @@ const Notifications = () => {
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (topNotification || displayedNotifications.length === 0) return;
|
||||||
|
setTopNotification(displayedNotifications[0].most_recent_notification_id);
|
||||||
|
}, [displayedNotifications.length]);
|
||||||
|
|
||||||
const emptyMessage = activeFilter === 'all'
|
const emptyMessage = activeFilter === 'all'
|
||||||
? <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. Interact with others to start the conversation." />
|
? <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. Interact with others to start the conversation." />
|
||||||
: <FormattedMessage id='empty_column.notifications_filtered' defaultMessage="You don't have any notifications of this type yet." />;
|
: <FormattedMessage id='empty_column.notifications_filtered' defaultMessage="You don't have any notifications of this type yet." />;
|
||||||
|
@ -112,8 +138,8 @@ const Notifications = () => {
|
||||||
|
|
||||||
if (isLoading && scrollableContentRef.current) {
|
if (isLoading && scrollableContentRef.current) {
|
||||||
scrollableContent = scrollableContentRef.current;
|
scrollableContent = scrollableContentRef.current;
|
||||||
} else if (notifications.length > 0 || hasMore) {
|
} else if (displayedNotifications.length > 0 || hasMore) {
|
||||||
scrollableContent = notifications.map((item) => (
|
scrollableContent = displayedNotifications.map((item) => (
|
||||||
<Notification
|
<Notification
|
||||||
key={item.group_key}
|
key={item.group_key}
|
||||||
notification={item}
|
notification={item}
|
||||||
|
@ -130,7 +156,7 @@ const Notifications = () => {
|
||||||
const scrollContainer = (
|
const scrollContainer = (
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
showLoading={isLoading && notifications.length === 0}
|
showLoading={isLoading && displayedNotifications.length === 0}
|
||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
placeholderComponent={PlaceholderNotification}
|
placeholderComponent={PlaceholderNotification}
|
||||||
|
@ -138,7 +164,7 @@ const Notifications = () => {
|
||||||
onLoadMore={handleLoadOlder}
|
onLoadMore={handleLoadOlder}
|
||||||
onScroll={handleScroll}
|
onScroll={handleScroll}
|
||||||
listClassName={clsx('divide-y divide-solid divide-gray-200 black:divide-gray-800 dark:divide-primary-800', {
|
listClassName={clsx('divide-y divide-solid divide-gray-200 black:divide-gray-800 dark:divide-primary-800', {
|
||||||
'animate-pulse': notifications.length === 0,
|
'animate-pulse': displayedNotifications.length === 0,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{scrollableContent!}
|
{scrollableContent!}
|
||||||
|
@ -152,7 +178,7 @@ const Notifications = () => {
|
||||||
<Portal>
|
<Portal>
|
||||||
<ScrollTopButton
|
<ScrollTopButton
|
||||||
onClick={handleDequeueNotifications}
|
onClick={handleDequeueNotifications}
|
||||||
count={totalQueuedNotificationsCount}
|
count={queuedNotificationCount}
|
||||||
message={messages.queue}
|
message={messages.queue}
|
||||||
/>
|
/>
|
||||||
</Portal>
|
</Portal>
|
||||||
|
|
|
@ -20,41 +20,29 @@ import {
|
||||||
NOTIFICATIONS_FILTER_SET,
|
NOTIFICATIONS_FILTER_SET,
|
||||||
NOTIFICATIONS_CLEAR,
|
NOTIFICATIONS_CLEAR,
|
||||||
NOTIFICATIONS_SCROLL_TOP,
|
NOTIFICATIONS_SCROLL_TOP,
|
||||||
NOTIFICATIONS_UPDATE_QUEUE,
|
|
||||||
NOTIFICATIONS_DEQUEUE,
|
|
||||||
NOTIFICATIONS_MARK_READ_REQUEST,
|
NOTIFICATIONS_MARK_READ_REQUEST,
|
||||||
MAX_QUEUED_NOTIFICATIONS,
|
|
||||||
} from '../actions/notifications';
|
} from '../actions/notifications';
|
||||||
import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines';
|
import { TIMELINE_DELETE, type TimelineAction } from '../actions/timelines';
|
||||||
|
|
||||||
import type { Notification as BaseNotification, Markers, NotificationGroup, PaginatedResponse, Relationship } from 'pl-api';
|
import type { Notification as BaseNotification, Markers, NotificationGroup, PaginatedResponse, Relationship } from 'pl-api';
|
||||||
import type { AnyAction } from 'redux';
|
import type { AnyAction } from 'redux';
|
||||||
|
|
||||||
const QueuedNotificationRecord = ImmutableRecord({
|
|
||||||
notification: {} as any as BaseNotification,
|
|
||||||
intlMessages: {} as Record<string, string>,
|
|
||||||
intlLocale: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const ReducerRecord = ImmutableRecord({
|
const ReducerRecord = ImmutableRecord({
|
||||||
items: ImmutableOrderedMap<string, NotificationGroup>(),
|
items: ImmutableOrderedMap<string, NotificationGroup>(),
|
||||||
hasMore: true,
|
hasMore: true,
|
||||||
top: false,
|
top: false,
|
||||||
unread: 0,
|
unread: 0,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
queuedNotifications: ImmutableOrderedMap<string, QueuedNotification>(), //max = MAX_QUEUED_NOTIFICATIONS
|
|
||||||
totalQueuedNotificationsCount: 0, //used for queuedItems overflow for MAX_QUEUED_NOTIFICATIONS+
|
|
||||||
lastRead: -1 as string | -1,
|
lastRead: -1 as string | -1,
|
||||||
});
|
});
|
||||||
|
|
||||||
type State = ReturnType<typeof ReducerRecord>;
|
type State = ReturnType<typeof ReducerRecord>;
|
||||||
type QueuedNotification = ReturnType<typeof QueuedNotificationRecord>;
|
|
||||||
|
|
||||||
const parseId = (id: string | number) => parseInt(id as string, 10);
|
const parseId = (id: string | number) => parseInt(id as string, 10);
|
||||||
|
|
||||||
// For sorting the notifications
|
// For sorting the notifications
|
||||||
const comparator = (a: Pick<NotificationGroup, 'group_key'>, b: Pick<NotificationGroup, 'group_key'>) => {
|
const comparator = (a: Pick<NotificationGroup, 'most_recent_notification_id'>, b: Pick<NotificationGroup, 'most_recent_notification_id'>) => {
|
||||||
const parse = (m: Pick<NotificationGroup, 'group_key'>) => parseId(m.group_key);
|
const parse = (m: Pick<NotificationGroup, 'most_recent_notification_id'>) => parseId(m.most_recent_notification_id);
|
||||||
if (parse(a) < parse(b)) return 1;
|
if (parse(a) < parse(b)) return 1;
|
||||||
if (parse(a) > parse(b)) return -1;
|
if (parse(a) > parse(b)) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -75,13 +63,7 @@ const importNotification = (state: State, notification: NotificationGroup) => {
|
||||||
|
|
||||||
if (!top) state = state.update('unread', unread => unread + 1);
|
if (!top) state = state.update('unread', unread => unread + 1);
|
||||||
|
|
||||||
return state.update('items', map => {
|
return state.update('items', map => map.set(notification.group_key, notification).sort(comparator));
|
||||||
if (top && map.size > 40) {
|
|
||||||
map = map.take(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
return map.set(notification.group_key, notification).sort(comparator);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const expandNormalizedNotifications = (state: State, notifications: NotificationGroup[], next: (() => Promise<PaginatedResponse<BaseNotification>>) | null) => {
|
const expandNormalizedNotifications = (state: State, notifications: NotificationGroup[], next: (() => Promise<PaginatedResponse<BaseNotification>>) | null) => {
|
||||||
|
@ -112,28 +94,6 @@ const deleteByStatus = (state: State, statusId: string) =>
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
state.update('items', map => map.filterNot(item => item !== null && item.status === statusId));
|
state.update('items', map => map.filterNot(item => item !== null && item.status === statusId));
|
||||||
|
|
||||||
const updateNotificationsQueue = (state: State, notification: BaseNotification, intlMessages: Record<string, string>, intlLocale: string) => {
|
|
||||||
const queuedNotifications = state.queuedNotifications;
|
|
||||||
const listedNotifications = state.items;
|
|
||||||
const totalQueuedNotificationsCount = state.totalQueuedNotificationsCount;
|
|
||||||
|
|
||||||
const alreadyExists = queuedNotifications.has(notification.group_key) || listedNotifications.has(notification.group_key);
|
|
||||||
if (alreadyExists) return state;
|
|
||||||
|
|
||||||
const newQueuedNotifications = queuedNotifications;
|
|
||||||
|
|
||||||
return state.withMutations(mutable => {
|
|
||||||
if (totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) {
|
|
||||||
mutable.set('queuedNotifications', newQueuedNotifications.set(notification.group_key, QueuedNotificationRecord({
|
|
||||||
notification,
|
|
||||||
intlMessages,
|
|
||||||
intlLocale,
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
mutable.set('totalQueuedNotificationsCount', totalQueuedNotificationsCount + 1);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const importMarker = (state: State, marker: Markers) => {
|
const importMarker = (state: State, marker: Markers) => {
|
||||||
const lastReadId = marker.notifications.last_read_id || -1 as string | -1;
|
const lastReadId = marker.notifications.last_read_id || -1 as string | -1;
|
||||||
|
|
||||||
|
@ -163,13 +123,6 @@ const notifications = (state: State = ReducerRecord(), action: AccountsAction |
|
||||||
return updateTop(state, action.top);
|
return updateTop(state, action.top);
|
||||||
case NOTIFICATIONS_UPDATE:
|
case NOTIFICATIONS_UPDATE:
|
||||||
return importNotification(state, action.notification);
|
return importNotification(state, action.notification);
|
||||||
case NOTIFICATIONS_UPDATE_QUEUE:
|
|
||||||
return updateNotificationsQueue(state, action.notification, action.intlMessages, action.intlLocale);
|
|
||||||
case NOTIFICATIONS_DEQUEUE:
|
|
||||||
return state.withMutations(mutable => {
|
|
||||||
mutable.delete('queuedNotifications');
|
|
||||||
mutable.set('totalQueuedNotificationsCount', 0);
|
|
||||||
});
|
|
||||||
case NOTIFICATIONS_EXPAND_SUCCESS:
|
case NOTIFICATIONS_EXPAND_SUCCESS:
|
||||||
return expandNormalizedNotifications(state, action.notifications, action.next);
|
return expandNormalizedNotifications(state, action.notifications, action.next);
|
||||||
case ACCOUNT_BLOCK_SUCCESS:
|
case ACCOUNT_BLOCK_SUCCESS:
|
||||||
|
|
Loading…
Reference in a new issue