Notifications: handle view while fetching categories

## Issue
"No notifications" briefly appear when your previous filter is not "All".

## Change
When splitting up the category-fetch, the render logic was not updated accordingly.
This commit is contained in:
infinite-persistence 2022-01-03 12:54:02 +08:00 committed by Thomas Zarebczan
parent 449398b88f
commit fad3f6ed78

View file

@ -43,14 +43,18 @@ export default function NotificationsPage(props: Props) {
activeChannel, activeChannel,
doCommentReactList, doCommentReactList,
} = props; } = props;
const initialFetchDone = useFetched(fetching);
const [name, setName] = usePersistedState('notifications--rule', NOTIFICATIONS.NOTIFICATION_NAME_ALL); const [name, setName] = usePersistedState('notifications--rule', NOTIFICATIONS.NOTIFICATION_NAME_ALL);
const isFiltered = name !== NOTIFICATIONS.NOTIFICATION_NAME_ALL; const isFiltered = name !== NOTIFICATIONS.NOTIFICATION_NAME_ALL;
const list = isFiltered ? notificationsFiltered : notifications; const list = isFiltered ? notificationsFiltered : notifications;
const fetchedOnce = useFetched(fetching);
const categoriesReady = notificationCategories;
const notificationsReady = !isFiltered || fetchedOnce;
const ready = categoriesReady && notificationsReady;
// Fetch reacts // Fetch reacts
React.useEffect(() => { React.useEffect(() => {
if ((!fetching || initialFetchDone) && activeChannel) { if (ready && !fetching && activeChannel) {
let idsForReactionFetch = []; let idsForReactionFetch = [];
list.map((notification) => { list.map((notification) => {
const { notification_rule, notification_parameters } = notification; const { notification_rule, notification_parameters } = notification;
@ -73,8 +77,9 @@ export default function NotificationsPage(props: Props) {
doCommentReactList(idsForReactionFetch); doCommentReactList(idsForReactionFetch);
} }
} }
}, [doCommentReactList, list, activeChannel, fetching, initialFetchDone]); }, [ready, doCommentReactList, list, activeChannel, fetching]);
// Mark all as seen
React.useEffect(() => { React.useEffect(() => {
if (unseenCount > 0) { if (unseenCount > 0) {
doSeeAllNotifications(); doSeeAllNotifications();
@ -82,59 +87,70 @@ export default function NotificationsPage(props: Props) {
}, [unseenCount, doSeeAllNotifications]); }, [unseenCount, doSeeAllNotifications]);
const stringifiedNotificationCategories = notificationCategories ? JSON.stringify(notificationCategories) : ''; const stringifiedNotificationCategories = notificationCategories ? JSON.stringify(notificationCategories) : '';
// Fetch filtered notifications
React.useEffect(() => { React.useEffect(() => {
if (stringifiedNotificationCategories) { if (stringifiedNotificationCategories) {
const arrayNotificationCategories = JSON.parse(stringifiedNotificationCategories); const arrayNotificationCategories = JSON.parse(stringifiedNotificationCategories);
if (name !== NOTIFICATIONS.NOTIFICATION_NAME_ALL) { if (name !== NOTIFICATIONS.NOTIFICATION_NAME_ALL) {
// Fetch filtered list when:
// (1) 'name' changed
// (2) new "all" notifications received (e.g. from websocket).
try { try {
const matchingCategory = arrayNotificationCategories.find((category) => category.name === name); const matchingCategory = arrayNotificationCategories.find((category) => category.name === name);
if (matchingCategory) { if (matchingCategory) {
doNotificationList(matchingCategory.types); doNotificationList(matchingCategory.types);
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e); // eslint-disable-line no-console
} }
} }
} }
}, [name, notifications, stringifiedNotificationCategories]); }, [name, notifications, stringifiedNotificationCategories, doNotificationList]);
React.useEffect(() => { React.useEffect(() => {
if (!notificationCategories) { if (!notificationCategories) {
doNotificationCategories(); doNotificationCategories();
} }
}, []); }, []); // eslint-disable-line react-hooks/exhaustive-deps
const notificationListElement = ( return (
<> <Page className="notification-page">
<BrowserNotificationBanner /> <BrowserNotificationBanner />
<div className="claim-list__header"> {ready && (
<h1 className="card__title">{__('Notifications')}</h1> <div className="claim-list__header">
<div className="claim-list__alt-controls--wrap"> <h1 className="card__title">{__('Notifications')}</h1>
{fetching && <Spinner type="small" />} <div className="claim-list__alt-controls--wrap">
{fetching && <Spinner type="small" delayed />}
{unreadCount > 0 && ( {unreadCount > 0 && (
<Button icon={ICONS.EYE} onClick={doReadNotifications} button="secondary" label={__('Mark all as read')} /> <Button
)} icon={ICONS.EYE}
{notificationCategories && ( onClick={doReadNotifications}
<FormField type="select" name="filter" value={name} onChange={(e) => setName(e.target.value)}> button="secondary"
{notificationCategories.map((category) => { label={__('Mark all as read')}
return ( />
<option key={category.name} value={category.name}> )}
{__(category.name)}
</option> {notificationCategories && (
); <FormField type="select" name="filter" value={name} onChange={(e) => setName(e.target.value)}>
})} {notificationCategories.map((category) => {
</FormField> return (
)} <option key={category.name} value={category.name}>
{__(category.name)}
</option>
);
})}
</FormField>
)}
</div>
</div> </div>
</div> )}
{list && list.length > 0 && !(isFiltered && fetching) ? ( {!ready ? (
<div className="main--empty">
<Spinner />
</div>
) : list && list.length > 0 && !(isFiltered && fetching) ? (
<div className="card"> <div className="card">
<div className="notification_list"> <div className="notification_list">
{list.map((notification) => { {list.map((notification) => {
@ -161,20 +177,6 @@ export default function NotificationsPage(props: Props) {
)} )}
</div> </div>
)} )}
</>
);
return (
<Page className="notification-page">
{initialFetchDone ? (
notificationListElement
) : fetching ? (
<div className="main--empty">
<Spinner delayed />
</div>
) : (
notificationListElement
)}
</Page> </Page>
); );
} }