From 8ffc48ebfac7adc1de9579516fbd4fe2d263ec07 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 11 Feb 2022 22:20:19 +0100 Subject: [PATCH 1/7] Add notifications when a reblogged status has been updated (#17404) * Add notifications when a reblogged status has been updated * Change wording to say "edit" instead of "update" and add missing controls * Replace previous update notifications with the most up-to-date one --- .../api/web/push_subscriptions_controller.rb | 12 ++++++- .../mastodon/actions/notifications.js | 13 +++++-- .../components/column_settings.js | 11 ++++++ .../notifications/components/notification.js | 35 +++++++++++++++++++ app/javascript/mastodon/reducers/settings.js | 3 ++ .../service_worker/web_push_locales.js | 2 ++ .../service_worker/web_push_notifications.js | 2 +- app/models/notification.rb | 6 ++-- app/models/status.rb | 1 + .../rest/notification_serializer.rb | 2 +- app/services/fan_out_on_write_service.rb | 9 +++++ app/services/notify_service.rb | 4 +++ app/workers/local_notification_worker.rb | 9 ++++- config/locales/en.yml | 2 ++ 14 files changed, 103 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb index bed57fc54c..db2512e5f5 100644 --- a/app/controllers/api/web/push_subscriptions_controller.rb +++ b/app/controllers/api/web/push_subscriptions_controller.rb @@ -26,6 +26,7 @@ class Api::Web::PushSubscriptionsController < Api::Web::BaseController mention: alerts_enabled, poll: alerts_enabled, status: alerts_enabled, + update: alerts_enabled, }, } @@ -61,6 +62,15 @@ 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]) + @data_params ||= params.require(:data).permit(:policy, alerts: [ + :follow, + :follow_request, + :favourite, + :reblog, + :mention, + :poll, + :status, + :update, + ]) end end diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js index 663cf21e34..9370811e0c 100644 --- a/app/javascript/mastodon/actions/notifications.js +++ b/app/javascript/mastodon/actions/notifications.js @@ -34,7 +34,6 @@ export const NOTIFICATIONS_LOAD_PENDING = 'NOTIFICATIONS_LOAD_PENDING'; export const NOTIFICATIONS_MOUNT = 'NOTIFICATIONS_MOUNT'; export const NOTIFICATIONS_UNMOUNT = 'NOTIFICATIONS_UNMOUNT'; - export const NOTIFICATIONS_MARK_AS_READ = 'NOTIFICATIONS_MARK_AS_READ'; export const NOTIFICATIONS_SET_BROWSER_SUPPORT = 'NOTIFICATIONS_SET_BROWSER_SUPPORT'; @@ -124,7 +123,17 @@ export function updateNotifications(notification, intlMessages, intlLocale) { const excludeTypesFromSettings = state => state.getIn(['settings', 'notifications', 'shows']).filter(enabled => !enabled).keySeq().toJS(); const excludeTypesFromFilter = filter => { - const allTypes = ImmutableList(['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll']); + const allTypes = ImmutableList([ + 'follow', + 'follow_request', + 'favourite', + 'reblog', + 'mention', + 'poll', + 'status', + 'update', + ]); + 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 005f5afda9..ada8b6e4a8 100644 --- a/app/javascript/mastodon/features/notifications/components/column_settings.js +++ b/app/javascript/mastodon/features/notifications/components/column_settings.js @@ -153,6 +153,17 @@ export default class ColumnSettings extends React.PureComponent { + +
+ + +
+ + {showPushSettings && } + + +
+
); } diff --git a/app/javascript/mastodon/features/notifications/components/notification.js b/app/javascript/mastodon/features/notifications/components/notification.js index f9f8a87f2d..cd471852b5 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.js +++ b/app/javascript/mastodon/features/notifications/components/notification.js @@ -19,6 +19,7 @@ const messages = defineMessages({ poll: { id: 'notification.poll', defaultMessage: 'A poll you have voted in has ended' }, 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' }, }); const notificationForScreenReader = (intl, message, timestamp) => { @@ -273,6 +274,38 @@ class Notification extends ImmutablePureComponent { ); } + renderUpdate (notification, link) { + const { intl, unread } = this.props; + + return ( + +
+
+
+ +
+ + + + +
+ +
+
+ ); + } + renderPoll (notification, account) { const { intl, unread } = this.props; const ownPoll = me === account.get('id'); @@ -330,6 +363,8 @@ class Notification extends ImmutablePureComponent { return this.renderReblog(notification, link); case 'status': return this.renderStatus(notification, link); + case 'update': + return this.renderUpdate(notification, link); case 'poll': return this.renderPoll(notification, account); } diff --git a/app/javascript/mastodon/reducers/settings.js b/app/javascript/mastodon/reducers/settings.js index 2a89919e1f..5146abe98a 100644 --- a/app/javascript/mastodon/reducers/settings.js +++ b/app/javascript/mastodon/reducers/settings.js @@ -36,6 +36,7 @@ const initialState = ImmutableMap({ mention: false, poll: false, status: false, + update: false, }), quickFilter: ImmutableMap({ @@ -55,6 +56,7 @@ const initialState = ImmutableMap({ mention: true, poll: true, status: true, + update: true, }), sounds: ImmutableMap({ @@ -65,6 +67,7 @@ const initialState = ImmutableMap({ mention: true, poll: true, status: true, + update: true, }), }), diff --git a/app/javascript/mastodon/service_worker/web_push_locales.js b/app/javascript/mastodon/service_worker/web_push_locales.js index 1265f3cfaf..807a1bcb94 100644 --- a/app/javascript/mastodon/service_worker/web_push_locales.js +++ b/app/javascript/mastodon/service_worker/web_push_locales.js @@ -20,6 +20,8 @@ filenames.forEach(filename => { 'notification.mention': full['notification.mention'] || '', 'notification.reblog': full['notification.reblog'] || '', 'notification.poll': full['notification.poll'] || '', + 'notification.status': full['notification.status'] || '', + 'notification.update': full['notification.update'] || '', 'status.show_more': full['status.show_more'] || '', 'status.reblog': full['status.reblog'] || '', diff --git a/app/javascript/mastodon/service_worker/web_push_notifications.js b/app/javascript/mastodon/service_worker/web_push_notifications.js index 926c5c4d7a..48a2be7e70 100644 --- a/app/javascript/mastodon/service_worker/web_push_notifications.js +++ b/app/javascript/mastodon/service_worker/web_push_notifications.js @@ -102,7 +102,7 @@ const handlePush = (event) => { options.image = undefined; options.actions = [actionExpand(preferred_locale)]; - } else if (notification.type === 'mention') { + } else if (['mention', 'status'].includes(notification.type)) { options.actions = [actionReblog(preferred_locale), actionFavourite(preferred_locale)]; } diff --git a/app/models/notification.rb b/app/models/notification.rb index 3bf9dd483e..c14eb8a7eb 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -35,6 +35,7 @@ class Notification < ApplicationRecord follow_request favourite poll + update ).freeze TARGET_STATUS_INCLUDES_BY_TYPE = { @@ -43,6 +44,7 @@ class Notification < ApplicationRecord mention: [mention: :status], favourite: [favourite: :status], poll: [poll: :status], + update: :status, }.freeze belongs_to :account, optional: true @@ -76,7 +78,7 @@ class Notification < ApplicationRecord def target_status case type - when :status + when :status, :update status when :reblog status&.reblog @@ -110,7 +112,7 @@ class Notification < ApplicationRecord cached_status = cached_statuses_by_id[notification.target_status.id] case notification.type - when :status + when :status, :update notification.status = cached_status when :reblog notification.status.reblog = cached_status diff --git a/app/models/status.rb b/app/models/status.rb index 4fabf24ef2..2e3df98a1f 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -62,6 +62,7 @@ class Status < ApplicationRecord has_many :favourites, inverse_of: :status, dependent: :destroy has_many :bookmarks, inverse_of: :status, dependent: :destroy has_many :reblogs, foreign_key: 'reblog_of_id', class_name: 'Status', inverse_of: :reblog, dependent: :destroy + has_many :reblogged_by_accounts, through: :reblogs, class_name: 'Account', source: :account has_many :replies, foreign_key: 'in_reply_to_id', class_name: 'Status', inverse_of: :thread has_many :mentions, dependent: :destroy, inverse_of: :status has_many :active_mentions, -> { active }, class_name: 'Mention', inverse_of: :status diff --git a/app/serializers/rest/notification_serializer.rb b/app/serializers/rest/notification_serializer.rb index 27b031fcc7..69b81f6deb 100644 --- a/app/serializers/rest/notification_serializer.rb +++ b/app/serializers/rest/notification_serializer.rb @@ -11,6 +11,6 @@ class REST::NotificationSerializer < ActiveModel::Serializer end def status_type? - [:favourite, :reblog, :status, :mention, :poll].include?(object.type) + [:favourite, :reblog, :status, :mention, :poll, :update].include?(object.type) end end diff --git a/app/services/fan_out_on_write_service.rb b/app/services/fan_out_on_write_service.rb index 4f847e2939..2bab91116a 100644 --- a/app/services/fan_out_on_write_service.rb +++ b/app/services/fan_out_on_write_service.rb @@ -34,6 +34,7 @@ class FanOutOnWriteService < BaseService def fan_out_to_local_recipients! deliver_to_self! notify_mentioned_accounts! + notify_about_update! if update? case @status.visibility.to_sym when :public, :unlisted, :private @@ -64,6 +65,14 @@ class FanOutOnWriteService < BaseService end end + def notify_about_update! + @status.reblogged_by_accounts.merge(Account.local).select(:id).reorder(nil).find_in_batches do |accounts| + LocalNotificationWorker.push_bulk(accounts) do |account| + [account.id, @status.id, 'Status', 'update'] + end + end + end + def deliver_to_all_followers! @account.followers_for_local_distribution.select(:id).reorder(nil).find_in_batches do |followers| FeedInsertWorker.push_bulk(followers) do |follower| diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 0f3516d28f..039e007f50 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -46,6 +46,10 @@ class NotifyService < BaseService 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) diff --git a/app/workers/local_notification_worker.rb b/app/workers/local_notification_worker.rb index a22e2834de..749a54b73b 100644 --- a/app/workers/local_notification_worker.rb +++ b/app/workers/local_notification_worker.rb @@ -12,7 +12,14 @@ class LocalNotificationWorker activity = activity_class_name.constantize.find(activity_id) end - return if Notification.where(account: receiver, activity: activity).any? + # For most notification types, only one notification should exist, and the older one is + # preferred. For updates, such as when a status is edited, the new notification + # should replace the previous ones. + if type == 'update' + Notification.where(account: receiver, activity: activity, type: 'update').in_batches.delete_all + elsif Notification.where(account: receiver, activity: activity, type: type).any? + return + end NotifyService.new.call(receiver, type || activity_class_name.underscore, activity) rescue ActiveRecord::RecordNotFound diff --git a/config/locales/en.yml b/config/locales/en.yml index 0a9f66827c..1809f123ed 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1148,6 +1148,8 @@ en: title: New boost status: subject: "%{name} just posted" + update: + subject: "%{name} edited a post" notifications: email_events: Events for e-mail notifications email_events_hint: 'Select events that you want to receive notifications for:' From 63c1a70f35b2db57a0238a8af8aadd46d7731891 Mon Sep 17 00:00:00 2001 From: Jeong Arm Date: Sat, 12 Feb 2022 06:23:19 +0900 Subject: [PATCH 2/7] Enable domain purge button on suspended domains too (#17209) * Enable domain purge button on suspended domains too * Change unless to if --- app/views/admin/instances/show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/instances/show.html.haml b/app/views/admin/instances/show.html.haml index e520bca0cc..4db8fd15cb 100644 --- a/app/views/admin/instances/show.html.haml +++ b/app/views/admin/instances/show.html.haml @@ -84,5 +84,5 @@ = link_to t('admin.instances.delivery.stop'), stop_delivery_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post }, class: 'button' - else = link_to t('admin.instances.delivery.restart'), restart_delivery_admin_instance_path(@instance), data: { confirm: t('admin.accounts.are_you_sure'), method: :post }, class: 'button' - - unless @instance.delivery_failure_tracker.available? && @instance.accounts_count > 0 + - if !@instance.delivery_failure_tracker.available? || @instance.accounts_count.zero? || @instance.domain_block&.suspend? = link_to t('admin.instances.purge'), admin_instance_path(@instance), data: { confirm: t('admin.instances.confirm_purge'), method: :delete }, class: 'button' From 3849c7e038ab503868d9bc9fab03e4e0f9646585 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Feb 2022 23:16:52 +0100 Subject: [PATCH 3/7] Bump puma from 5.6.1 to 5.6.2 (#17526) Bumps [puma](https://github.com/puma/puma) from 5.6.1 to 5.6.2. - [Release notes](https://github.com/puma/puma/releases) - [Changelog](https://github.com/puma/puma/blob/master/History.md) - [Commits](https://github.com/puma/puma/compare/v5.6.1...v5.6.2) --- updated-dependencies: - dependency-name: puma dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index df3862e803..95c75448aa 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -434,7 +434,7 @@ GEM pry-rails (0.3.9) pry (>= 0.10.4) public_suffix (4.0.6) - puma (5.6.1) + puma (5.6.2) nio4r (~> 2.0) pundit (2.1.1) activesupport (>= 3.0.0) From f53e4c250e5a659431c138a6040bd59124c9a75e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sat, 12 Feb 2022 01:08:23 +0100 Subject: [PATCH 4/7] Fix layout of the report page on smaller screens in admin UI (#17523) Fix #17491 --- app/javascript/styles/mastodon/admin.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/javascript/styles/mastodon/admin.scss b/app/javascript/styles/mastodon/admin.scss index 21669ddedb..546de16400 100644 --- a/app/javascript/styles/mastodon/admin.scss +++ b/app/javascript/styles/mastodon/admin.scss @@ -1187,6 +1187,10 @@ a.sparkline { } } } + + @media screen and (max-width: 930px) { + grid-template-columns: minmax(0, 1fr); + } } .account-card { From c24ff1efe135e04dcdad9ab53469c1573614ed0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Feb 2022 01:09:31 +0100 Subject: [PATCH 5/7] Bump follow-redirects from 1.14.7 to 1.14.8 (#17527) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8. - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8) --- updated-dependencies: - dependency-name: follow-redirects dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 08e78d9fdf..94509ae7fd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4989,9 +4989,9 @@ flush-write-stream@^1.0.0: readable-stream "^2.3.6" follow-redirects@^1.0.0, follow-redirects@^1.14.7: - version "1.14.7" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" - integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== + version "1.14.8" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" + integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== font-awesome@^4.7.0: version "4.7.0" From e5e6857bd7a716d24421a72d2a7260983f81d4b5 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 11 Feb 2022 22:20:19 +0100 Subject: [PATCH 6/7] [Glitch] Add notifications when a reblogged status has been updated Port front-end changes from 8ffc48ebfac7adc1de9579516fbd4fe2d263ec07 to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/actions/notifications.js | 13 +++++++++-- .../glitch/components/status_prepend.js | 11 ++++++++++ .../components/column_settings.js | 11 ++++++++++ .../notifications/components/notification.js | 22 +++++++++++++++++++ .../flavours/glitch/reducers/settings.js | 3 +++ 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/app/javascript/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js index 4b00ea632a..40430102cf 100644 --- a/app/javascript/flavours/glitch/actions/notifications.js +++ b/app/javascript/flavours/glitch/actions/notifications.js @@ -47,7 +47,6 @@ export const NOTIFICATIONS_UNMOUNT = 'NOTIFICATIONS_UNMOUNT'; export const NOTIFICATIONS_SET_VISIBILITY = 'NOTIFICATIONS_SET_VISIBILITY'; - export const NOTIFICATIONS_MARK_AS_READ = 'NOTIFICATIONS_MARK_AS_READ'; export const NOTIFICATIONS_SET_BROWSER_SUPPORT = 'NOTIFICATIONS_SET_BROWSER_SUPPORT'; @@ -136,7 +135,17 @@ const excludeTypesFromSettings = state => state.getIn(['settings', 'notification const excludeTypesFromFilter = filter => { - const allTypes = ImmutableList(['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll']); + const allTypes = ImmutableList([ + 'follow', + 'follow_request', + 'favourite', + 'reblog', + 'mention', + 'poll', + 'status', + 'update', + ]); + return allTypes.filterNot(item => item === filter).toJS(); }; diff --git a/app/javascript/flavours/glitch/components/status_prepend.js b/app/javascript/flavours/glitch/components/status_prepend.js index 5a00f232e0..1661ca8f5f 100644 --- a/app/javascript/flavours/glitch/components/status_prepend.js +++ b/app/javascript/flavours/glitch/components/status_prepend.js @@ -88,6 +88,14 @@ export default class StatusPrepend extends React.PureComponent { /> ); } + case 'update': + return ( + + ); } return null; } @@ -115,6 +123,9 @@ export default class StatusPrepend extends React.PureComponent { case 'status': iconId = 'bell'; break; + case 'update': + iconId = 'pencil'; + break; }; return !type ? null : ( diff --git a/app/javascript/flavours/glitch/features/notifications/components/column_settings.js b/app/javascript/flavours/glitch/features/notifications/components/column_settings.js index 95250c6edc..569ba4db08 100644 --- a/app/javascript/flavours/glitch/features/notifications/components/column_settings.js +++ b/app/javascript/flavours/glitch/features/notifications/components/column_settings.js @@ -154,6 +154,17 @@ export default class ColumnSettings extends React.PureComponent { + +
+ + +
+ + {showPushSettings && } + + +
+
); } diff --git a/app/javascript/flavours/glitch/features/notifications/components/notification.js b/app/javascript/flavours/glitch/features/notifications/components/notification.js index e1d9fbd0af..1cf2058982 100644 --- a/app/javascript/flavours/glitch/features/notifications/components/notification.js +++ b/app/javascript/flavours/glitch/features/notifications/components/notification.js @@ -171,6 +171,28 @@ export default class Notification extends ImmutablePureComponent { unread={this.props.unread} /> ); + case 'update': + return ( +