From cfeb3beb4e1c3a05392546e6e4584de537049989 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 7 Jul 2018 19:31:19 +0200 Subject: [PATCH] Fix filters not affecting notifications in web UI (#7977) * Hook up filtering to statuses in notifications column * Filter notifications for sound, desktop notifications --- .../mastodon/actions/notifications.js | 17 ++++++++++++++--- .../notifications/components/notification.js | 1 + app/javascript/mastodon/selectors/index.js | 6 ++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js index 3f95f6667..ad6430b82 100644 --- a/app/javascript/mastodon/actions/notifications.js +++ b/app/javascript/mastodon/actions/notifications.js @@ -9,6 +9,7 @@ import { } from './importer'; import { defineMessages } from 'react-intl'; import { unescapeHTML } from '../utils/html'; +import { getFilters, regexFromFilters } from '../selectors'; export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE'; export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP'; @@ -38,6 +39,16 @@ export function updateNotifications(notification, intlMessages, intlLocale) { const showInColumn = getState().getIn(['settings', 'notifications', 'shows', notification.type], true); const showAlert = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true); const playSound = getState().getIn(['settings', 'notifications', 'sounds', notification.type], true); + const filters = getFilters(getState(), { contextType: 'notifications' }); + + let filtered = false; + + if (notification.type === 'mention') { + const regex = regexFromFilters(filters); + const searchIndex = notification.status.spoiler_text + '\n' + unescapeHTML(notification.status.content); + + filtered = regex && regex.test(searchIndex); + } if (showInColumn) { dispatch(importFetchedAccount(notification.account)); @@ -49,11 +60,11 @@ export function updateNotifications(notification, intlMessages, intlLocale) { dispatch({ type: NOTIFICATIONS_UPDATE, notification, - meta: playSound ? { sound: 'boop' } : undefined, + meta: (playSound && !filtered) ? { sound: 'boop' } : undefined, }); fetchRelatedRelationships(dispatch, [notification]); - } else if (playSound) { + } else if (playSound && !filtered) { dispatch({ type: NOTIFICATIONS_UPDATE_NOOP, meta: { sound: 'boop' }, @@ -61,7 +72,7 @@ export function updateNotifications(notification, intlMessages, intlLocale) { } // Desktop notifications - if (typeof window.Notification !== 'undefined' && showAlert) { + if (typeof window.Notification !== 'undefined' && showAlert && !filtered) { const title = new IntlMessageFormat(intlMessages[`notification.${notification.type}`], intlLocale).format({ name: notification.account.display_name.length > 0 ? notification.account.display_name : notification.account.username }); const body = (notification.status && notification.status.spoiler_text.length > 0) ? notification.status.spoiler_text : unescapeHTML(notification.status ? notification.status.content : ''); diff --git a/app/javascript/mastodon/features/notifications/components/notification.js b/app/javascript/mastodon/features/notifications/components/notification.js index 6db62b330..f58224a8b 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.js +++ b/app/javascript/mastodon/features/notifications/components/notification.js @@ -91,6 +91,7 @@ export default class Notification extends ImmutablePureComponent { hidden={this.props.hidden} onMoveDown={this.handleMoveDown} onMoveUp={this.handleMoveUp} + contextType='notifications' /> ); } diff --git a/app/javascript/mastodon/selectors/index.js b/app/javascript/mastodon/selectors/index.js index ba9777eba..7aa7569a0 100644 --- a/app/javascript/mastodon/selectors/index.js +++ b/app/javascript/mastodon/selectors/index.js @@ -35,10 +35,12 @@ const toServerSideType = columnType => { } }; +export const getFilters = (state, { contextType }) => state.get('filters', ImmutableList()).filter(filter => contextType && filter.get('context').includes(toServerSideType(contextType)) && (filter.get('expires_at') === null || Date.parse(filter.get('expires_at')) > (new Date()))); + const escapeRegExp = string => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string -const regexFromFilters = filters => { +export const regexFromFilters = filters => { if (filters.size === 0) { return null; } @@ -53,7 +55,7 @@ export const makeGetStatus = () => { (state, { id }) => state.getIn(['statuses', state.getIn(['statuses', id, 'reblog'])]), (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]), (state, { id }) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]), - (state, { contextType }) => state.get('filters', ImmutableList()).filter(filter => contextType && filter.get('context').includes(toServerSideType(contextType)) && (filter.get('expires_at') === null || Date.parse(filter.get('expires_at')) > (new Date()))), + getFilters, ], (statusBase, statusReblog, accountBase, accountReblog, filters) => {