diff --git a/app/javascript/flavours/glitch/features/notifications/components/filtered_notifications_banner.tsx b/app/javascript/flavours/glitch/features/notifications/components/filtered_notifications_banner.tsx
index 8aaa486b19..f4413a8c17 100644
--- a/app/javascript/flavours/glitch/features/notifications/components/filtered_notifications_banner.tsx
+++ b/app/javascript/flavours/glitch/features/notifications/components/filtered_notifications_banner.tsx
@@ -1,18 +1,62 @@
-import { useEffect } from 'react';
+import { useCallback, useEffect } from 'react';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage, useIntl, defineMessages } from 'react-intl';
-import { Link } from 'react-router-dom';
+import { Link, useHistory } from 'react-router-dom';
import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react';
import { fetchNotificationPolicy } from 'flavours/glitch/actions/notification_policies';
import { Icon } from 'flavours/glitch/components/icon';
+import { selectSettingsNotificationsMinimizeFilteredBanner } from 'flavours/glitch/selectors/settings';
import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
-import { toCappedNumber } from 'flavours/glitch/utils/numbers';
+
+const messages = defineMessages({
+ filteredNotifications: {
+ id: 'notification_requests.title',
+ defaultMessage: 'Filtered notifications',
+ },
+});
+
+export const FilteredNotificationsIconButton: React.FC<{
+ className?: string;
+}> = ({ className }) => {
+ const intl = useIntl();
+ const history = useHistory();
+ const policy = useAppSelector((state) => state.notificationPolicy);
+ const minimizeSetting = useAppSelector(
+ selectSettingsNotificationsMinimizeFilteredBanner,
+ );
+
+ const handleClick = useCallback(() => {
+ history.push('/notifications/requests');
+ }, [history]);
+
+ if (policy === null || policy.summary.pending_notifications_count === 0) {
+ return null;
+ }
+
+ if (!minimizeSetting) {
+ return null;
+ }
+
+ return (
+
+ );
+};
export const FilteredNotificationsBanner: React.FC = () => {
const dispatch = useAppDispatch();
const policy = useAppSelector((state) => state.notificationPolicy);
+ const minimizeSetting = useAppSelector(
+ selectSettingsNotificationsMinimizeFilteredBanner,
+ );
useEffect(() => {
void dispatch(fetchNotificationPolicy());
@@ -30,6 +74,10 @@ export const FilteredNotificationsBanner: React.FC = () => {
return null;
}
+ if (minimizeSetting) {
+ return null;
+ }
+
return (
{
/>
-
-
- {toCappedNumber(policy.summary.pending_notifications_count)}
-
);
};
diff --git a/app/javascript/flavours/glitch/features/notifications/components/policy_controls.tsx b/app/javascript/flavours/glitch/features/notifications/components/policy_controls.tsx
new file mode 100644
index 0000000000..58eff3fbcf
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/notifications/components/policy_controls.tsx
@@ -0,0 +1,141 @@
+import { useCallback } from 'react';
+
+import { FormattedMessage } from 'react-intl';
+
+import { updateNotificationsPolicy } from 'flavours/glitch/actions/notification_policies';
+import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
+
+import { CheckboxWithLabel } from './checkbox_with_label';
+
+export const PolicyControls: React.FC = () => {
+ const dispatch = useAppDispatch();
+
+ const notificationPolicy = useAppSelector(
+ (state) => state.notificationPolicy,
+ );
+
+ const handleFilterNotFollowing = useCallback(
+ (checked: boolean) => {
+ void dispatch(
+ updateNotificationsPolicy({ filter_not_following: checked }),
+ );
+ },
+ [dispatch],
+ );
+
+ const handleFilterNotFollowers = useCallback(
+ (checked: boolean) => {
+ void dispatch(
+ updateNotificationsPolicy({ filter_not_followers: checked }),
+ );
+ },
+ [dispatch],
+ );
+
+ const handleFilterNewAccounts = useCallback(
+ (checked: boolean) => {
+ void dispatch(
+ updateNotificationsPolicy({ filter_new_accounts: checked }),
+ );
+ },
+ [dispatch],
+ );
+
+ const handleFilterPrivateMentions = useCallback(
+ (checked: boolean) => {
+ void dispatch(
+ updateNotificationsPolicy({ filter_private_mentions: checked }),
+ );
+ },
+ [dispatch],
+ );
+
+ if (!notificationPolicy) return null;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js b/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js
index 1212a88b38..3c4c4b30ca 100644
--- a/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js
+++ b/app/javascript/flavours/glitch/features/notifications/containers/column_settings_container.js
@@ -6,7 +6,6 @@ import { openModal } from 'flavours/glitch/actions/modal';
import { initializeNotifications } from 'flavours/glitch/actions/notifications_migration';
import { showAlert } from '../../../actions/alerts';
-import { updateNotificationsPolicy } from '../../../actions/notification_policies';
import { setFilter, requestBrowserPermission } from '../../../actions/notifications';
import { changeAlerts as changePushNotifications } from '../../../actions/push_notifications';
import { changeSetting } from '../../../actions/settings';
@@ -25,7 +24,6 @@ const mapStateToProps = state => ({
alertsEnabled: state.getIn(['settings', 'notifications', 'alerts']).includes(true),
browserSupport: state.getIn(['notifications', 'browserSupport']),
browserPermission: state.getIn(['notifications', 'browserPermission']),
- notificationPolicy: state.notificationPolicy,
});
const mapDispatchToProps = (dispatch) => ({
@@ -74,12 +72,6 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(requestBrowserPermission());
},
- onChangePolicy (param, checked) {
- dispatch(updateNotificationsPolicy({
- [param]: checked,
- }));
- },
-
});
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ColumnSettings));
diff --git a/app/javascript/flavours/glitch/features/notifications/index.jsx b/app/javascript/flavours/glitch/features/notifications/index.jsx
index 2d3d437756..b3b133411a 100644
--- a/app/javascript/flavours/glitch/features/notifications/index.jsx
+++ b/app/javascript/flavours/glitch/features/notifications/index.jsx
@@ -38,7 +38,10 @@ import { LoadGap } from '../../components/load_gap';
import ScrollableList from '../../components/scrollable_list';
import NotificationPurgeButtonsContainer from '../../containers/notification_purge_buttons_container';
-import { FilteredNotificationsBanner } from './components/filtered_notifications_banner';
+import {
+ FilteredNotificationsBanner,
+ FilteredNotificationsIconButton,
+} from './components/filtered_notifications_banner';
import NotificationsPermissionBanner from './components/notifications_permission_banner';
import ColumnSettingsContainer from './containers/column_settings_container';
import FilterBarContainer from './containers/filter_bar_container';
@@ -290,7 +293,9 @@ class Notifications extends PureComponent {
scrollContainer = ;
}
- const extraButtons = [];
+ const extraButtons = [
+ ,
+ ];
if (canMarkAsRead) {
extraButtons.push(
diff --git a/app/javascript/flavours/glitch/features/notifications/requests.jsx b/app/javascript/flavours/glitch/features/notifications/requests.jsx
index d7a07da152..3df8bc2616 100644
--- a/app/javascript/flavours/glitch/features/notifications/requests.jsx
+++ b/app/javascript/flavours/glitch/features/notifications/requests.jsx
@@ -9,16 +9,52 @@ import { useSelector, useDispatch } from 'react-redux';
import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react';
import { fetchNotificationRequests, expandNotificationRequests } from 'flavours/glitch/actions/notifications';
+import { changeSetting } from 'flavours/glitch/actions/settings';
import Column from 'flavours/glitch/components/column';
import ColumnHeader from 'flavours/glitch/components/column_header';
import ScrollableList from 'flavours/glitch/components/scrollable_list';
import { NotificationRequest } from './components/notification_request';
+import { PolicyControls } from './components/policy_controls';
+import SettingToggle from './components/setting_toggle';
const messages = defineMessages({
title: { id: 'notification_requests.title', defaultMessage: 'Filtered notifications' },
+ maximize: { id: 'notification_requests.maximize', defaultMessage: 'Maximize' }
});
+const ColumnSettings = () => {
+ const dispatch = useDispatch();
+ const settings = useSelector((state) => state.settings.get('notifications'));
+
+ const onChange = useCallback(
+ (key, checked) => {
+ dispatch(changeSetting(['notifications', ...key], checked));
+ },
+ [dispatch],
+ );
+
+ return (
+
+ );
+};
+
export const NotificationRequests = ({ multiColumn }) => {
const columnRef = useRef();
const intl = useIntl();
@@ -48,7 +84,9 @@ export const NotificationRequests = ({ multiColumn }) => {
onClick={handleHeaderClick}
multiColumn={multiColumn}
showBackButton
- />
+ >
+
+
);
- const extraButton = canMarkAsRead ? (
-
- ) : null;
+ const extraButton = (
+ <>
+
+ {canMarkAsRead && (
+
+ )}
+ >
+ );
return (
'dismissPermissionBanner',
])) as boolean;
+export const selectSettingsNotificationsMinimizeFilteredBanner = (
+ state: RootState,
+) =>
+ state.settings.getIn(['notifications', 'minimizeFilteredBanner']) as boolean;
+
/* eslint-enable @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */