mirror of https://github.com/mastodon/mastodon
Convert notifications policies frontend code to Typescript (#29868)
parent
50db95b9a1
commit
d558dfd77d
@ -0,0 +1,16 @@
|
|||||||
|
import {
|
||||||
|
apiGetNotificationPolicy,
|
||||||
|
apiUpdateNotificationsPolicy,
|
||||||
|
} from 'mastodon/api/notification_policies';
|
||||||
|
import type { NotificationPolicy } from 'mastodon/models/notification_policy';
|
||||||
|
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
|
||||||
|
|
||||||
|
export const fetchNotificationPolicy = createDataLoadingThunk(
|
||||||
|
'notificationPolicy/fetch',
|
||||||
|
() => apiGetNotificationPolicy(),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const updateNotificationsPolicy = createDataLoadingThunk(
|
||||||
|
'notificationPolicy/update',
|
||||||
|
(policy: Partial<NotificationPolicy>) => apiUpdateNotificationsPolicy(policy),
|
||||||
|
);
|
@ -0,0 +1,10 @@
|
|||||||
|
import { apiRequest } from 'mastodon/api';
|
||||||
|
import type { NotificationPolicyJSON } from 'mastodon/api_types/notification_policies';
|
||||||
|
|
||||||
|
export const apiGetNotificationPolicy = () =>
|
||||||
|
apiRequest<NotificationPolicyJSON>('GET', '/v1/notifications/policy');
|
||||||
|
|
||||||
|
export const apiUpdateNotificationsPolicy = (
|
||||||
|
policy: Partial<NotificationPolicyJSON>,
|
||||||
|
) =>
|
||||||
|
apiRequest<NotificationPolicyJSON>('PUT', '/v1/notifications/policy', policy);
|
@ -0,0 +1,12 @@
|
|||||||
|
// See app/serializers/rest/notification_policy_serializer.rb
|
||||||
|
|
||||||
|
export interface NotificationPolicyJSON {
|
||||||
|
filter_not_following: boolean;
|
||||||
|
filter_not_followers: boolean;
|
||||||
|
filter_new_accounts: boolean;
|
||||||
|
filter_private_mentions: boolean;
|
||||||
|
summary: {
|
||||||
|
pending_requests_count: number;
|
||||||
|
pending_notifications_count: number;
|
||||||
|
};
|
||||||
|
}
|
@ -1,49 +0,0 @@
|
|||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react';
|
|
||||||
import { fetchNotificationPolicy } from 'mastodon/actions/notifications';
|
|
||||||
import { Icon } from 'mastodon/components/icon';
|
|
||||||
import { toCappedNumber } from 'mastodon/utils/numbers';
|
|
||||||
|
|
||||||
export const FilteredNotificationsBanner = () => {
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
const policy = useSelector(state => state.get('notificationPolicy'));
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
dispatch(fetchNotificationPolicy());
|
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
dispatch(fetchNotificationPolicy());
|
|
||||||
}, 120000);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearInterval(interval);
|
|
||||||
};
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
if (policy === null || policy.getIn(['summary', 'pending_notifications_count']) === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link className='filtered-notifications-banner' to='/notifications/requests'>
|
|
||||||
<Icon icon={InventoryIcon} />
|
|
||||||
|
|
||||||
<div className='filtered-notifications-banner__text'>
|
|
||||||
<strong><FormattedMessage id='filtered_notifications_banner.title' defaultMessage='Filtered notifications' /></strong>
|
|
||||||
<span><FormattedMessage id='filtered_notifications_banner.pending_requests' defaultMessage='Notifications from {count, plural, =0 {no one} one {one person} other {# people}} you may know' values={{ count: policy.getIn(['summary', 'pending_requests_count']) }} /></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='filtered-notifications-banner__badge'>
|
|
||||||
<div className='filtered-notifications-banner__badge__badge'>{toCappedNumber(policy.getIn(['summary', 'pending_notifications_count']))}</div>
|
|
||||||
<FormattedMessage id='filtered_notifications_banner.mentions' defaultMessage='{count, plural, one {mention} other {mentions}}' values={{ count: policy.getIn(['summary', 'pending_notifications_count']) }} />
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
};
|
|
@ -0,0 +1,68 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react';
|
||||||
|
import { fetchNotificationPolicy } from 'mastodon/actions/notification_policies';
|
||||||
|
import { Icon } from 'mastodon/components/icon';
|
||||||
|
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||||
|
import { toCappedNumber } from 'mastodon/utils/numbers';
|
||||||
|
|
||||||
|
export const FilteredNotificationsBanner: React.FC = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const policy = useAppSelector((state) => state.notificationPolicy);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
void dispatch(fetchNotificationPolicy());
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
void dispatch(fetchNotificationPolicy());
|
||||||
|
}, 120000);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(interval);
|
||||||
|
};
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
if (policy === null || policy.summary.pending_notifications_count === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
className='filtered-notifications-banner'
|
||||||
|
to='/notifications/requests'
|
||||||
|
>
|
||||||
|
<Icon icon={InventoryIcon} id='filtered-notifications' />
|
||||||
|
|
||||||
|
<div className='filtered-notifications-banner__text'>
|
||||||
|
<strong>
|
||||||
|
<FormattedMessage
|
||||||
|
id='filtered_notifications_banner.title'
|
||||||
|
defaultMessage='Filtered notifications'
|
||||||
|
/>
|
||||||
|
</strong>
|
||||||
|
<span>
|
||||||
|
<FormattedMessage
|
||||||
|
id='filtered_notifications_banner.pending_requests'
|
||||||
|
defaultMessage='Notifications from {count, plural, =0 {no one} one {one person} other {# people}} you may know'
|
||||||
|
values={{ count: policy.summary.pending_requests_count }}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='filtered-notifications-banner__badge'>
|
||||||
|
<div className='filtered-notifications-banner__badge__badge'>
|
||||||
|
{toCappedNumber(policy.summary.pending_notifications_count)}
|
||||||
|
</div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='filtered_notifications_banner.mentions'
|
||||||
|
defaultMessage='{count, plural, one {mention} other {mentions}}'
|
||||||
|
values={{ count: policy.summary.pending_notifications_count }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,3 @@
|
|||||||
|
import type { NotificationPolicyJSON } from 'mastodon/api_types/notification_policies';
|
||||||
|
|
||||||
|
export type NotificationPolicy = NotificationPolicyJSON; // No changes from the API type
|
@ -1,12 +0,0 @@
|
|||||||
import { fromJS } from 'immutable';
|
|
||||||
|
|
||||||
import { NOTIFICATION_POLICY_FETCH_SUCCESS } from 'mastodon/actions/notifications';
|
|
||||||
|
|
||||||
export const notificationPolicyReducer = (state = null, action) => {
|
|
||||||
switch(action.type) {
|
|
||||||
case NOTIFICATION_POLICY_FETCH_SUCCESS:
|
|
||||||
return fromJS(action.policy);
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
};
|
|
@ -0,0 +1,18 @@
|
|||||||
|
import { createReducer, isAnyOf } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
|
import {
|
||||||
|
fetchNotificationPolicy,
|
||||||
|
updateNotificationsPolicy,
|
||||||
|
} from 'mastodon/actions/notification_policies';
|
||||||
|
import type { NotificationPolicy } from 'mastodon/models/notification_policy';
|
||||||
|
|
||||||
|
export const notificationPolicyReducer =
|
||||||
|
createReducer<NotificationPolicy | null>(null, (builder) => {
|
||||||
|
builder.addMatcher(
|
||||||
|
isAnyOf(
|
||||||
|
fetchNotificationPolicy.fulfilled,
|
||||||
|
updateNotificationsPolicy.fulfilled,
|
||||||
|
),
|
||||||
|
(_state, action) => action.payload,
|
||||||
|
);
|
||||||
|
});
|
Loading…
Reference in New Issue