From 9e92bf54e5f08123e605808c971fb9976cbad9e6 Mon Sep 17 00:00:00 2001 From: sneakers-the-rat Date: Sun, 28 Jul 2024 20:22:58 -0700 Subject: [PATCH 1/3] add mute fields to notification policy in an ugly hack of duplicating fields but hopefully in a way that stays compatible with upstream masto --- .../api/v1/notifications/policies_controller.rb | 6 +++++- app/models/notification_policy.rb | 4 ++++ ...240729030729_add_mute_to_notification_policies.rb | 12 ++++++++++++ db/schema.rb | 6 +++++- 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20240729030729_add_mute_to_notification_policies.rb diff --git a/app/controllers/api/v1/notifications/policies_controller.rb b/app/controllers/api/v1/notifications/policies_controller.rb index 1ec336f9a594dc..065cc2edaec791 100644 --- a/app/controllers/api/v1/notifications/policies_controller.rb +++ b/app/controllers/api/v1/notifications/policies_controller.rb @@ -31,7 +31,11 @@ def resource_params :filter_not_following, :filter_not_followers, :filter_new_accounts, - :filter_private_mentions + :filter_private_mentions, + :mute_not_following, + :mute_not_followers, + :mute_new_accounts, + :mute_private_mentions ) end end diff --git a/app/models/notification_policy.rb b/app/models/notification_policy.rb index 2bb58004e37fad..e47194e982bccc 100644 --- a/app/models/notification_policy.rb +++ b/app/models/notification_policy.rb @@ -12,6 +12,10 @@ # filter_private_mentions :boolean default(TRUE), not null # created_at :datetime not null # updated_at :datetime not null +# mute_not_following :boolean default(FALSE), not null +# mute_not_followers :boolean default(FALSE), not null +# mute_new_accounts :boolean default(FALSE), not null +# mute_private_mentions :boolean default(FALSE), not null # class NotificationPolicy < ApplicationRecord diff --git a/db/migrate/20240729030729_add_mute_to_notification_policies.rb b/db/migrate/20240729030729_add_mute_to_notification_policies.rb new file mode 100644 index 00000000000000..e6d062bc86a9bd --- /dev/null +++ b/db/migrate/20240729030729_add_mute_to_notification_policies.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class AddMuteToNotificationPolicies < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + + def change + add_column :notification_policies, :mute_not_following, :boolean, default: false, null: false + add_column :notification_policies, :mute_not_followers, :boolean, default: false, null: false + add_column :notification_policies, :mute_new_accounts, :boolean, default: false, null: false + add_column :notification_policies, :mute_private_mentions, :boolean, default: false, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 8c67b8469c5d05..a4cff2d82f3b83 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_07_24_181224) do +ActiveRecord::Schema[7.1].define(version: 2024_07_29_030729) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -698,6 +698,10 @@ t.boolean "filter_private_mentions", default: true, null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.boolean "mute_not_following", default: false, null: false + t.boolean "mute_not_followers", default: false, null: false + t.boolean "mute_new_accounts", default: false, null: false + t.boolean "mute_private_mentions", default: false, null: false t.index ["account_id"], name: "index_notification_policies_on_account_id", unique: true end From b0c9d247aadef1eecaef9ce67b59338f0eca9038 Mon Sep 17 00:00:00 2001 From: sneakers-the-rat Date: Sun, 28 Jul 2024 23:33:25 -0700 Subject: [PATCH 2/3] working frontend with toggles, backend with exclusivity checking. implementing mutes still unfinished --- .../glitch/api_types/notification_policies.ts | 4 + .../components/column_settings.jsx | 84 ++++++++++++++----- .../components/pill_bar_toggle.jsx | 37 ++++++++ .../flavours/glitch/styles/forms.scss | 5 ++ app/models/notification_policy.rb | 28 +++++++ .../rest/notification_policy_serializer.rb | 4 + 6 files changed, 141 insertions(+), 21 deletions(-) create mode 100644 app/javascript/flavours/glitch/features/notifications/components/pill_bar_toggle.jsx diff --git a/app/javascript/flavours/glitch/api_types/notification_policies.ts b/app/javascript/flavours/glitch/api_types/notification_policies.ts index 0f4a2d132e0e0e..889242472e7de1 100644 --- a/app/javascript/flavours/glitch/api_types/notification_policies.ts +++ b/app/javascript/flavours/glitch/api_types/notification_policies.ts @@ -5,6 +5,10 @@ export interface NotificationPolicyJSON { filter_not_followers: boolean; filter_new_accounts: boolean; filter_private_mentions: boolean; + mute_not_following: boolean; + mute_not_followers: boolean; + mute_new_accounts: boolean; + mute_private_mentions: boolean; summary: { pending_requests_count: number; pending_notifications_count: number; diff --git a/app/javascript/flavours/glitch/features/notifications/components/column_settings.jsx b/app/javascript/flavours/glitch/features/notifications/components/column_settings.jsx index 3423517227da0f..65b1f13fc0b9dd 100644 --- a/app/javascript/flavours/glitch/features/notifications/components/column_settings.jsx +++ b/app/javascript/flavours/glitch/features/notifications/components/column_settings.jsx @@ -8,10 +8,10 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { identityContextPropShape, withIdentity } from 'flavours/glitch/identity_context'; import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_REPORTS } from 'flavours/glitch/permissions'; -import { CheckboxWithLabel } from './checkbox_with_label'; import ClearColumnButton from './clear_column_button'; import GrantPermissionButton from './grant_permission_button'; import PillBarButton from './pill_bar_button'; +import PillBarToggle from './pill_bar_toggle'; import SettingToggle from './setting_toggle'; class ColumnSettings extends PureComponent { @@ -49,6 +49,22 @@ class ColumnSettings extends PureComponent { this.props.onChangePolicy('filter_private_mentions', checked); }; + handleMuteNotFollowing = checked => { + this.props.onChangePolicy('mute_not_following', checked); + }; + + handleMuteNotFollowers = checked => { + this.props.onChangePolicy('mute_not_followers', checked); + }; + + handleMuteNewAccounts = checked => { + this.props.onChangePolicy('mute_new_accounts', checked); + }; + + handleMutePrivateMentions = checked => { + this.props.onChangePolicy('mute_private_mentions', checked); + }; + render () { const { settings, pushSettings, onChange, onClear, alertsEnabled, browserSupport, browserPermission, onRequestNotificationPermission, notificationPolicy } = this.props; @@ -59,6 +75,8 @@ class ColumnSettings extends PureComponent { const alertStr = ; const showStr = ; const soundStr = ; + const filterStr = ; + const muteStr = ; const showPushSettings = pushSettings.get('browserSupport') && pushSettings.get('isSubscribed'); const pushStr = showPushSettings && ; @@ -85,31 +103,55 @@ class ColumnSettings extends PureComponent {

- - - - - - - - - - - - - - - - - - - +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+

- +
diff --git a/app/javascript/flavours/glitch/features/notifications/components/pill_bar_toggle.jsx b/app/javascript/flavours/glitch/features/notifications/components/pill_bar_toggle.jsx new file mode 100644 index 00000000000000..51e21849785ff8 --- /dev/null +++ b/app/javascript/flavours/glitch/features/notifications/components/pill_bar_toggle.jsx @@ -0,0 +1,37 @@ +import PropTypes from 'prop-types'; +import { PureComponent } from 'react'; + +import classNames from 'classnames'; + +export default class PillBarToggle extends PureComponent { + + static propTypes = { + id: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired, + label: PropTypes.node.isRequired, + onChange: PropTypes.func.isRequired, + disabled: PropTypes.bool, + }; + + onChange = () => { + this.props.onChange(!this.props.active); + }; + + render () { + const { id, active, label, disabled } = this.props; + const prop_id = ['setting-pillbar-button', id].filter(Boolean).join('-'); + + return ( + + ); + } +} diff --git a/app/javascript/flavours/glitch/styles/forms.scss b/app/javascript/flavours/glitch/styles/forms.scss index 4877170275f470..9fc4627e3782eb 100644 --- a/app/javascript/flavours/glitch/styles/forms.scss +++ b/app/javascript/flavours/glitch/styles/forms.scss @@ -1327,6 +1327,11 @@ code { margin: 0 4px; margin-top: -2px; } + + // Extra bottom margin when used as a label over a pillbar button group + &.pillbar { + margin-bottom: 0.5em; + } } &__toggle { diff --git a/app/models/notification_policy.rb b/app/models/notification_policy.rb index e47194e982bccc..eba0643757e017 100644 --- a/app/models/notification_policy.rb +++ b/app/models/notification_policy.rb @@ -25,6 +25,8 @@ class NotificationPolicy < ApplicationRecord attr_reader :pending_requests_count, :pending_notifications_count + before_update :ensure_filter_mute_exclusivity + MAX_MEANINGFUL_COUNT = 100 def summarize! @@ -37,4 +39,30 @@ def summarize! def pending_notification_requests @pending_notification_requests ||= notification_requests.limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint')) end + + def ensure_filter_mute_exclusivity + if filter_not_following_changed? && filter_not_following? + self.mute_not_following = false + elsif mute_not_following_changed? && mute_not_following? + self.filter_not_following = false + end + + if filter_not_followers_changed? && filter_not_followers? + self.mute_not_followers = false + elsif mute_not_followers_changed? && mute_not_followers? + self.filter_not_followers = false + end + + if filter_new_accounts_changed? && filter_new_accounts? + self.mute_new_accounts = false + elsif mute_new_accounts_changed? && mute_new_accounts? + self.filter_new_accounts = false + end + + if filter_private_mentions_changed? && filter_private_mentions? + self.mute_private_mentions = false + elsif mute_private_mentions_changed? && mute_private_mentions? + self.filter_private_mentions = false + end + end end diff --git a/app/serializers/rest/notification_policy_serializer.rb b/app/serializers/rest/notification_policy_serializer.rb index 8bf85250fa590c..961654f5711eb4 100644 --- a/app/serializers/rest/notification_policy_serializer.rb +++ b/app/serializers/rest/notification_policy_serializer.rb @@ -7,6 +7,10 @@ class REST::NotificationPolicySerializer < ActiveModel::Serializer :filter_not_followers, :filter_new_accounts, :filter_private_mentions, + :mute_not_following, + :mute_not_followers, + :mute_new_accounts, + :mute_private_mentions, :summary def summary From 2b1927ac355fdfdf85d6cb57aba97324b31fb6c1 Mon Sep 17 00:00:00 2001 From: sneakers-the-rat Date: Mon, 29 Jul 2024 00:11:34 -0700 Subject: [PATCH 3/3] working backend, no notifications created --- app/services/notify_service.rb | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/app/services/notify_service.rb b/app/services/notify_service.rb index 23f92c816b86c0..4c22fd36438b25 100644 --- a/app/services/notify_service.rb +++ b/app/services/notify_service.rb @@ -34,7 +34,7 @@ def dismiss? blocked ||= @recipient.muting_notifications?(@sender) blocked ||= conversation_muted? blocked ||= blocked_mention? if message? - blocked + blocked || FilterCondition.new(@notification).dismiss? end private @@ -99,6 +99,16 @@ def filter? filtered_by_private_mentions_policy? end + def dismiss? + return false unless Notification::PROPERTIES[@notification.type][:filterable] + return false if override_for_sender? + + muted_by_not_following_policy? || + muted_by_not_followers_policy? || + muted_by_new_accounts_policy? || + muted_by_private_mentions_policy? + end + private def filtered_by_not_following_policy? @@ -117,6 +127,22 @@ def filtered_by_private_mentions_policy? @policy.filter_private_mentions? && not_following? && private_mention_not_in_response? end + def muted_by_not_following_policy? + @policy.mute_not_following? && not_following? + end + + def muted_by_not_followers_policy? + @policy.mute_not_followers? && not_follower? + end + + def muted_by_new_accounts_policy? + @policy.mute_new_accounts? && new_account? + end + + def muted_by_private_mentions_policy? + @policy.mute_private_mentions? && not_following? && private_mention_not_in_response? + end + def not_following? !@recipient.following?(@sender) end