diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2022-02-23 16:45:22 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-23 16:45:22 +0100 |
commit | 7b816eb5aeeed61fa1e3a7c95cbb5bb7978f7fa5 (patch) | |
tree | 5888b4ec8bbb68d88c527ec8dada549f4a6c9b77 /app | |
parent | 3e12abc1fe9b32f69eaf2a8d1edf8bad9622eb4a (diff) |
Add notifications for new sign-ups (#16953)
Diffstat (limited to 'app')
9 files changed, 69 insertions, 65 deletions
diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb index db2512e5f..5167928e9 100644 --- a/app/controllers/api/web/push_subscriptions_controller.rb +++ b/app/controllers/api/web/push_subscriptions_controller.rb @@ -17,17 +17,7 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController data = { policy: 'all', - - alerts: { - follow: alerts_enabled, - follow_request: alerts_enabled, - favourite: alerts_enabled, - reblog: alerts_enabled, - mention: alerts_enabled, - poll: alerts_enabled, - status: alerts_enabled, - update: alerts_enabled, - }, + alerts: Notification::TYPES.index_with { alerts_enabled }, } data.deep_merge!(data_params) if params[:data] @@ -62,15 +52,6 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController end def data_params - @data_params ||= params.require(:data).permit(:policy, alerts: [ - :follow, - :follow_request, - :favourite, - :reblog, - :mention, - :poll, - :status, - :update, - ]) + @data_params ||= params.require(:data).permit(:policy, alerts: Notification::TYPES) end end diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js index 9370811e0..00e8d74d7 100644 --- a/app/javascript/mastodon/actions/notifications.js +++ b/app/javascript/mastodon/actions/notifications.js @@ -45,7 +45,7 @@ defineMessages({ }); const fetchRelatedRelationships = (dispatch, notifications) => { - const accountIds = notifications.filter(item => item.type === 'follow').map(item => item.account.id); + const accountIds = notifications.filter(item => ['follow', 'follow_request', 'admin.sign_up'].indexOf(item.type) !== -1).map(item => item.account.id); if (accountIds.length > 0) { dispatch(fetchRelationships(accountIds)); @@ -132,6 +132,7 @@ const excludeTypesFromFilter = filter => { 'poll', 'status', 'update', + 'admin.sign_up', ]); return allTypes.filterNot(item => item === filter).toJS(); diff --git a/app/javascript/mastodon/features/notifications/components/column_settings.js b/app/javascript/mastodon/features/notifications/components/column_settings.js index ada8b6e4a..84db04430 100644 --- a/app/javascript/mastodon/features/notifications/components/column_settings.js +++ b/app/javascript/mastodon/features/notifications/components/column_settings.js @@ -5,6 +5,7 @@ import { FormattedMessage } from 'react-intl'; import ClearColumnButton from './clear_column_button'; import GrantPermissionButton from './grant_permission_button'; import SettingToggle from './setting_toggle'; +import { isStaff } from 'mastodon/initial_state'; export default class ColumnSettings extends React.PureComponent { @@ -155,7 +156,7 @@ export default class ColumnSettings extends React.PureComponent { </div> <div role='group' aria-labelledby='notifications-update'> - <span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.update' defaultMessage='Edits:' /></span> + <span id='notifications-update' className='column-settings__section'><FormattedMessage id='notifications.column_settings.update' defaultMessage='Edits:' /></span> <div className='column-settings__row'> <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'update']} onChange={onChange} label={alertStr} /> @@ -164,6 +165,19 @@ export default class ColumnSettings extends React.PureComponent { <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'update']} onChange={onChange} label={soundStr} /> </div> </div> + + {isStaff && ( + <div role='group' aria-labelledby='notifications-admin-sign-up'> + <span id='notifications-status' className='column-settings__section'><FormattedMessage id='notifications.column_settings.admin.sign_up' defaultMessage='New sign-ups:' /></span> + + <div className='column-settings__row'> + <SettingToggle disabled={browserPermission === 'denied'} prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'admin.sign_up']} onChange={onChange} label={alertStr} /> + {showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'admin.sign_up']} onChange={this.onPushChange} label={pushStr} />} + <SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'admin.sign_up']} onChange={onChange} label={showStr} /> + <SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'admin.sign_up']} onChange={onChange} label={soundStr} /> + </div> + </div> + )} </div> ); } diff --git a/app/javascript/mastodon/features/notifications/components/notification.js b/app/javascript/mastodon/features/notifications/components/notification.js index cd471852b..9198e9c9d 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.js +++ b/app/javascript/mastodon/features/notifications/components/notification.js @@ -20,6 +20,7 @@ const messages = defineMessages({ reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your status' }, status: { id: 'notification.status', defaultMessage: '{name} just posted' }, update: { id: 'notification.update', defaultMessage: '{name} edited a post' }, + adminSignUp: { id: 'notification.admin.sign_up', defaultMessage: '{name} signed up' }, }); const notificationForScreenReader = (intl, message, timestamp) => { @@ -344,6 +345,28 @@ class Notification extends ImmutablePureComponent { ); } + renderAdminSignUp (notification, account, link) { + const { intl, unread } = this.props; + + return ( + <HotKeys handlers={this.getHandlers()}> + <div className={classNames('notification notification-admin-sign-up focusable', { unread })} tabIndex='0' aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.adminSignUp, { name: account.get('acct') }), notification.get('created_at'))}> + <div className='notification__message'> + <div className='notification__favourite-icon-wrapper'> + <Icon id='user-plus' fixedWidth /> + </div> + + <span title={notification.get('created_at')}> + <FormattedMessage id='notification.admin.sign_up' defaultMessage='{name} signed up' values={{ name: link }} /> + </span> + </div> + + <AccountContainer id={account.get('id')} hidden={this.props.hidden} /> + </div> + </HotKeys> + ); + } + render () { const { notification } = this.props; const account = notification.get('account'); @@ -367,6 +390,8 @@ class Notification extends ImmutablePureComponent { return this.renderUpdate(notification, link); case 'poll': return this.renderPoll(notification, account); + case 'admin.sign_up': + return this.renderAdminSignUp(notification, account, link); } return null; diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js index 5146abe98..39639f3dc 100644 --- a/app/javascript/mastodon/reducers/settings.js +++ b/app/javascript/mastodon/reducers/settings.js @@ -37,6 +37,7 @@ const initialState = ImmutableMap({ poll: false, status: false, update: false, + 'admin.sign_up': false, }), quickFilter: ImmutableMap({ @@ -57,6 +58,7 @@ const initialState = ImmutableMap({ poll: true, status: true, update: true, + 'admin.sign_up': true, }), sounds: ImmutableMap({ @@ -68,6 +70,7 @@ const initialState = ImmutableMap({ poll: true, status: true, update: true, + 'admin.sign_up': true, }), }), diff --git a/app/javascript/mastodon/service_worker/web_push_locales.js b/app/javascript/mastodon/service_worker/web_push_locales.js index 807a1bcb9..7d713cd37 100644 --- a/app/javascript/mastodon/service_worker/web_push_locales.js +++ b/app/javascript/mastodon/service_worker/web_push_locales.js @@ -22,6 +22,7 @@ filenames.forEach(filename => { 'notification.poll': full['notification.poll'] || '', 'notification.status': full['notification.status'] || '', 'notification.update': full['notification.update'] || '', + 'notification.admin.sign_up': full['notification.admin.sign_up'] || '', 'status.show_more': full['status.show_more'] || '', 'status.reblog': full['status.reblog'] || '', diff --git a/app/models/notification.rb b/app/models/notification.rb index c14eb8a7e..9bf296386 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -36,6 +36,7 @@ class Notification < ApplicationRecord favourite poll update + admin.sign_up ).freeze TARGET_STATUS_INCLUDES_BY_TYPE = { @@ -63,13 +64,10 @@ class Notification < ApplicationRecord scope :without_suspended, -> { joins(:from_account).merge(Account.without_suspended) } scope :browserable, ->(exclude_types = [], account_id = nil) { - types = TYPES - exclude_types.map(&:to_sym) - - if account_id.nil? - where(type: types) - else - where(type: types, from_account_id: account_id) - end + scope = all + scope = where(from_account_id: account_id) if account_id.present? + scope = scope.where(type: TYPES - exclude_types.map(&:to_sym)) unless exclude_types.empty? + scope } def type @@ -142,6 +140,8 @@ class Notification < ApplicationRecord self.from_account_id = activity&.account_id when 'Mention' self.from_account_id = activity&.status&.account_id + when 'Account' + self.from_account_id = activity&.id end end end diff --git a/app/services/bootstrap_timeline_service.rb b/app/services/bootstrap_timeline_service.rb index e1a1b98c3..70e7cc570 100644 --- a/app/services/bootstrap_timeline_service.rb +++ b/app/services/bootstrap_timeline_service.rb @@ -5,6 +5,7 @@ class BootstrapTimelineService < BaseService @source_account = source_account autofollow_inviter! + notify_staff! end private @@ -14,4 +15,10 @@ class BootstrapTimelineService < BaseService FollowService.new.call(@source_account, @source_account.user.invite.user.account) end + + def notify_staff! + User.staff.includes(:account).find_each do |user| + NotifyService.new.call(user.account, :'admin.new_user', @source_account) + end + end end diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index ab80a7e4b..b1f9fd755 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -22,34 +22,6 @@ class NotifyService < BaseService FeedManager.instance.filter?(:mentions, @notification.mention.status, @recipient) end - def blocked_status? - false - end - - def blocked_favourite? - false - end - - def blocked_follow? - false - end - - def blocked_reblog? - false - end - - def blocked_follow_request? - false - end - - def blocked_poll? - false - end - - def blocked_update? - false - end - def following_sender? return @following_sender if defined?(@following_sender) @following_sender = @recipient.following?(@notification.from_account) || @recipient.requested?(@notification.from_account) @@ -149,15 +121,15 @@ class NotifyService < BaseService return blocked if message? && from_staff? - blocked ||= domain_blocking? # Skip for domain blocked accounts - blocked ||= @recipient.blocking?(@notification.from_account) # Skip for blocked accounts + blocked ||= domain_blocking? + blocked ||= @recipient.blocking?(@notification.from_account) blocked ||= @recipient.muting_notifications?(@notification.from_account) - blocked ||= hellbanned? # Hellban - blocked ||= optional_non_follower? # Options - blocked ||= optional_non_following? # Options - blocked ||= optional_non_following_and_direct? # Options + blocked ||= hellbanned? + blocked ||= optional_non_follower? + blocked ||= optional_non_following? + blocked ||= optional_non_following_and_direct? blocked ||= conversation_muted? - blocked ||= send("blocked_#{@notification.type}?") # Type-dependent filters + blocked ||= blocked_mention? if @notification.type == :mention blocked end |