mirror of https://github.com/mastodon/mastodon.git
Handle unread notifications
parent
a4ba310adf
commit
c14e537ef0
|
@ -19,6 +19,7 @@ import { Icon } from 'mastodon/components/icon';
|
|||
import { NotSignedInIndicator } from 'mastodon/components/not_signed_in_indicator';
|
||||
import { useIdentity } from 'mastodon/identity_context';
|
||||
import type { NotificationGap } from 'mastodon/reducers/notifications_groups';
|
||||
import { selectUnreadNotificationsGroupsCount } from 'mastodon/selectors/notifications';
|
||||
import {
|
||||
selectNeedsNotificationPermission,
|
||||
selectSettingsNotificationsExcludedTypes,
|
||||
|
@ -35,8 +36,8 @@ import {
|
|||
expandNotifications,
|
||||
scrollTopNotifications,
|
||||
loadPending,
|
||||
mountNotifications,
|
||||
unmountNotifications,
|
||||
// mountNotifications,
|
||||
// unmountNotifications,
|
||||
markNotificationsAsRead,
|
||||
} from '../../actions/notifications';
|
||||
import Column from '../../components/column';
|
||||
|
@ -81,52 +82,35 @@ const getNotifications = createSelector(
|
|||
);
|
||||
|
||||
// const mapStateToProps = (state) => ({
|
||||
// isUnread:
|
||||
// state.getIn(['notifications', 'unread']) > 0 ||
|
||||
// state.getIn(['notifications', 'pendingItems']).size > 0,
|
||||
// numPending: state.getIn(['notifications', 'pendingItems'], ImmutableList())
|
||||
// .size,
|
||||
// canMarkAsRead:
|
||||
// state.getIn(['settings', 'notifications', 'showUnread']) &&
|
||||
// state.getIn(['notifications', 'readMarkerId']) !== '0' &&
|
||||
// getNotifications(state).some(
|
||||
// (item) =>
|
||||
// item !== null &&
|
||||
// compareId(
|
||||
// item.get('id'),
|
||||
// state.getIn(['notifications', 'readMarkerId']),
|
||||
// ) > 0,
|
||||
// ),
|
||||
// });
|
||||
|
||||
export const Notifications: React.FC<{
|
||||
columnId?: string;
|
||||
isUnread?: boolean;
|
||||
multiColumn?: boolean;
|
||||
numPending: number;
|
||||
}> = ({ isUnread, columnId, multiColumn, numPending }) => {
|
||||
}> = ({ columnId, multiColumn, numPending }) => {
|
||||
const intl = useIntl();
|
||||
const notifications = useAppSelector(getNotifications);
|
||||
const dispatch = useAppDispatch();
|
||||
const isLoading = useAppSelector((s) => s.notificationsGroups.isLoading);
|
||||
const hasMore = useAppSelector((s) => s.notificationsGroups.hasMore);
|
||||
const readMarkerId = useAppSelector(
|
||||
(s) => s.notificationsGroups.readMarkerId,
|
||||
);
|
||||
|
||||
const lastReadId = useAppSelector((s) =>
|
||||
selectSettingsNotificationsShowUnread(s)
|
||||
? s.notificationsGroups.readMarkerId
|
||||
: '0',
|
||||
selectSettingsNotificationsShowUnread(s) ? s.markers.notifications : '0',
|
||||
);
|
||||
const canMarkAsRead = useAppSelector(
|
||||
(s) =>
|
||||
selectSettingsNotificationsShowUnread(s) &&
|
||||
s.notificationsGroups.readMarkerId !== '0' &&
|
||||
notifications.some(
|
||||
(item) =>
|
||||
item.type !== 'gap' && compareId(item.group_key, readMarkerId) > 0,
|
||||
),
|
||||
|
||||
const unreadNotificationsCount = useAppSelector(
|
||||
selectUnreadNotificationsGroupsCount,
|
||||
);
|
||||
|
||||
const isUnread = unreadNotificationsCount > 0;
|
||||
|
||||
const canMarkAsRead =
|
||||
useAppSelector(selectSettingsNotificationsShowUnread) &&
|
||||
unreadNotificationsCount > 0;
|
||||
|
||||
const needsNotificationPermission = useAppSelector(
|
||||
selectNeedsNotificationPermission,
|
||||
);
|
||||
|
@ -157,14 +141,14 @@ export const Notifications: React.FC<{
|
|||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(mountNotifications());
|
||||
// dispatch(mountNotifications());
|
||||
|
||||
// FIXME: remove once this becomes the main implementation
|
||||
void dispatch(fetchNotifications());
|
||||
|
||||
return () => {
|
||||
dispatch(unmountNotifications());
|
||||
dispatch(scrollTopNotifications(false));
|
||||
// dispatch(unmountNotifications());
|
||||
// dispatch(scrollTopNotifications(false));
|
||||
};
|
||||
}, [dispatch]);
|
||||
|
||||
|
@ -282,7 +266,9 @@ export const Notifications: React.FC<{
|
|||
onMoveUp={handleMoveUp}
|
||||
onMoveDown={handleMoveDown}
|
||||
unread={
|
||||
lastReadId !== '0' && compareId(item.group_key, lastReadId) > 0
|
||||
lastReadId !== '0' &&
|
||||
!!item.page_max_id &&
|
||||
compareId(item.page_max_id, lastReadId) > 0
|
||||
}
|
||||
/>
|
||||
),
|
||||
|
|
|
@ -34,6 +34,7 @@ import { NavigationPortal } from 'mastodon/components/navigation_portal';
|
|||
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
|
||||
import { timelinePreview, trendsEnabled } from 'mastodon/initial_state';
|
||||
import { transientSingleColumn } from 'mastodon/is_mobile';
|
||||
import { selectUnreadNotificationsGroupsCount } from 'mastodon/selectors/notifications';
|
||||
|
||||
import ColumnLink from './column_link';
|
||||
import DisabledAccountBanner from './disabled_account_banner';
|
||||
|
@ -62,14 +63,27 @@ const NotificationsLink = () => {
|
|||
const count = useSelector(state => state.getIn(['notifications', 'unread']));
|
||||
const intl = useIntl();
|
||||
|
||||
const newCount = useSelector(selectUnreadNotificationsGroupsCount);
|
||||
|
||||
return (
|
||||
<ColumnLink
|
||||
transparent
|
||||
to='/notifications'
|
||||
icon={<IconWithBadge id='bell' icon={NotificationsIcon} count={count} className='column-link__icon' />}
|
||||
activeIcon={<IconWithBadge id='bell' icon={NotificationsActiveIcon} count={count} className='column-link__icon' />}
|
||||
text={intl.formatMessage(messages.notifications)}
|
||||
/>
|
||||
<>
|
||||
<ColumnLink
|
||||
key='notifications'
|
||||
transparent
|
||||
to='/notifications'
|
||||
icon={<IconWithBadge id='bell' icon={NotificationsIcon} count={count} className='column-link__icon' />}
|
||||
activeIcon={<IconWithBadge id='bell' icon={NotificationsActiveIcon} count={count} className='column-link__icon' />}
|
||||
text={intl.formatMessage(messages.notifications)}
|
||||
/>
|
||||
<ColumnLink
|
||||
key='notifications-v2'
|
||||
transparent
|
||||
to='/notifications_v2'
|
||||
icon={<IconWithBadge id='bell' icon={NotificationsIcon} count={newCount} className='column-link__icon' />}
|
||||
activeIcon={<IconWithBadge id='bell' icon={NotificationsActiveIcon} count={newCount} className='column-link__icon' />}
|
||||
text={"New Notifications"}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -31,18 +31,14 @@ export interface NotificationGap {
|
|||
|
||||
interface NotificationGroupsState {
|
||||
groups: (NotificationGroup | NotificationGap)[];
|
||||
unread: number;
|
||||
isLoading: boolean;
|
||||
hasMore: boolean;
|
||||
readMarkerId: string;
|
||||
}
|
||||
|
||||
const initialState: NotificationGroupsState = {
|
||||
groups: [],
|
||||
unread: 0,
|
||||
isLoading: false,
|
||||
hasMore: false,
|
||||
readMarkerId: '0',
|
||||
};
|
||||
|
||||
function removeNotificationsForAccounts(
|
||||
|
@ -172,7 +168,6 @@ export const notificationsGroupsReducer =
|
|||
})
|
||||
.addCase(clearNotifications.pending, (state) => {
|
||||
state.groups = [];
|
||||
state.unread = 0;
|
||||
state.hasMore = false;
|
||||
})
|
||||
.addCase(blockAccountSuccess, (state, action) => {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import { createSelector } from '@reduxjs/toolkit';
|
||||
|
||||
import { compareId } from 'mastodon/compare_id';
|
||||
import type { RootState } from 'mastodon/store';
|
||||
|
||||
export const selectUnreadNotificationsGroupsCount = createSelector(
|
||||
[
|
||||
(s: RootState) => s.markers.notifications,
|
||||
(s: RootState) => s.notificationsGroups.groups,
|
||||
],
|
||||
(notificationMarker, groups) => {
|
||||
return groups.filter(
|
||||
(group) =>
|
||||
group.type !== 'gap' &&
|
||||
group.page_max_id &&
|
||||
compareId(group.page_max_id, notificationMarker) > 0,
|
||||
).length;
|
||||
},
|
||||
);
|
Loading…
Reference in New Issue