Redesign: Add follow requests indicator to notifications page (#40683)

This commit is contained in:
diondiondion
2026-09-25 12:00:03 +00:00
committed by GitHub
parent e7365313f9
commit 6511e595ec
5 changed files with 97 additions and 13 deletions

View File

@@ -2,6 +2,8 @@ import { useCallback, useEffect } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import type { Map as ImmutableMap } from 'immutable';
import {
PenNibIcon,
HouseIcon,
@@ -14,6 +16,7 @@ import {
} from '@phosphor-icons/react';
import FediIcon from '@/images/icons/icon_fediverse.svg?react';
import { fetchFollowRequests } from '@/mastodon/actions/accounts';
import { fetchLists } from '@/mastodon/actions/lists';
import { closeNavigation } from '@/mastodon/actions/navigation';
import { fetchFollowedHashtags } from '@/mastodon/actions/tags_typed';
@@ -78,13 +81,39 @@ function useFollowedHashtags() {
return { followedHashtags: tags };
}
export function useFollowRequestsCount({
fetch = true,
}: { fetch?: boolean } = {}) {
const followRequestsCount = useAppSelector(
(state) =>
(
state.user_lists.getIn(['follow_requests', 'items']) as
| ImmutableMap<string, unknown>
| undefined
)?.size ?? 0,
);
const dispatch = useAppDispatch();
useEffect(() => {
if (fetch) {
dispatch(fetchFollowRequests());
}
}, [dispatch, fetch]);
return followRequestsCount;
}
export function useNotificationsCount() {
const unreadNotificationsCount = useAppSelector(
selectUnreadNotificationGroupsCount,
);
const followRequestsCount = useFollowRequestsCount();
const { unreadAnnouncementCount } = useHasAnnouncements();
return unreadNotificationsCount + unreadAnnouncementCount;
return (
unreadNotificationsCount + followRequestsCount + unreadAnnouncementCount
);
}
const isFediverseFeedsLinkActive = (

View File

@@ -0,0 +1,46 @@
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import { UserPlusIcon } from '@phosphor-icons/react';
import { Icon } from 'mastodon/components/icon';
import { useFollowRequestsCount } from '../../navigation_panel/redesign';
/**
* This banner is only shown to users whose notification policy filters
* or blocks notifications from accounts that are not following them,
* so that they have a way of finding out about pending requests.
*/
export const FollowRequestsBanner: React.FC = () => {
const followRequestsCount = useFollowRequestsCount({ fetch: false });
if (followRequestsCount === 0) {
return null;
}
return (
<Link className='filtered-notifications-banner' to='/follow_requests'>
<div className='notification-group__icon'>
<Icon icon={UserPlusIcon} id='filtered-notifications' />
</div>
<div className='filtered-notifications-banner__text'>
<strong>
<FormattedMessage
id='column.follow_requests'
defaultMessage='Follow requests'
/>
</strong>
<span>
<FormattedMessage
id='follow_requests.pending_requests'
defaultMessage='From {count, plural, =0 {no one} one {one person} other {# people}} you may know'
values={{ count: followRequestsCount }}
/>
</span>
</div>
</Link>
);
};

View File

@@ -61,6 +61,7 @@ import {
import NotificationsPermissionBanner from '../notifications/components/notifications_permission_banner';
import ColumnSettingsContainer from '../notifications/containers/column_settings_container';
import { FollowRequestsBanner } from './components/follow_requests_banner';
import { NotificationGroup } from './components/notification_group';
import { FilterBar } from './filter_bar';
@@ -229,6 +230,7 @@ export const Notifications: React.FC<{
{needsNotificationPermission && <NotificationsPermissionBanner />}
{shouldShowAnnouncements && <Announcements />}
<FilteredNotificationsBanner />
<FollowRequestsBanner />
</>
);

View File

@@ -840,6 +840,7 @@
"firehose.remote": "Other servers",
"follow_request.authorize": "Authorize",
"follow_request.reject": "Reject",
"follow_requests.pending_requests": "From {count, plural, =0 {no one} one {one person} other {# people}} you may know",
"follow_requests.unlocked_explanation": "Even though your account is not locked, the {domain} staff thought you might want to review follow requests from these accounts manually.",
"follow_suggestions.curated_suggestion": "Staff pick",
"follow_suggestions.dismiss": "Don't show again",

View File

@@ -5,6 +5,8 @@ import type { NotificationGroup } from 'mastodon/models/notification_group';
import type { NotificationGap } from 'mastodon/reducers/notification_groups';
import type { RootState } from 'mastodon/store';
import { isRedesignEnabled } from '../utils/environment';
import {
selectSettingsNotificationsExcludedTypes,
selectSettingsNotificationsQuickFilterActive,
@@ -63,19 +65,23 @@ export const selectUnreadNotificationGroupsCount = createSelector(
selectPendingNotificationGroups,
],
(notificationMarker, groups, pendingGroups) => {
function filterRelevantNotifications(
group: NotificationGap | NotificationGroup,
) {
if (isRedesignEnabled() && group.type === 'follow_request') {
// Pending follow requests are counted separately in the redesign
return false;
}
return (
group.type !== 'gap' &&
group.page_max_id &&
compareId(group.page_max_id, notificationMarker) > 0
);
}
return (
groups.filter(
(group) =>
group.type !== 'gap' &&
group.page_max_id &&
compareId(group.page_max_id, notificationMarker) > 0,
).length +
pendingGroups.filter(
(group) =>
group.type !== 'gap' &&
group.page_max_id &&
compareId(group.page_max_id, notificationMarker) > 0,
).length
groups.filter(filterRelevantNotifications).length +
pendingGroups.filter(filterRelevantNotifications).length
);
},
);