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