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/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 2bb58004e37fad..eba0643757e017 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
@@ -21,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!
@@ -33,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
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
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