Add the ability to make status reference notifications followee-only
This commit is contained in:
parent
91910d7d2d
commit
ccafeaf32f
11 changed files with 116 additions and 4 deletions
|
@ -96,7 +96,7 @@ class Settings::PreferencesController < Settings::BaseController
|
||||||
:setting_default_search_searchability,
|
:setting_default_search_searchability,
|
||||||
:setting_show_reload_button,
|
:setting_show_reload_button,
|
||||||
notification_emails: %i(follow follow_request reblog favourite emoji_reaction status_reference mention digest report pending_account trending_tag),
|
notification_emails: %i(follow follow_request reblog favourite emoji_reaction status_reference mention digest report pending_account trending_tag),
|
||||||
interactions: %i(must_be_follower must_be_following must_be_following_dm must_be_dm_to_send_email)
|
interactions: %i(must_be_follower must_be_following must_be_following_dm must_be_dm_to_send_email must_be_following_reference)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ const initialState = ImmutableMap({
|
||||||
poll: true,
|
poll: true,
|
||||||
status: true,
|
status: true,
|
||||||
emoji_reaction: true,
|
emoji_reaction: true,
|
||||||
status_reference: false,
|
status_reference: true,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
sounds: ImmutableMap({
|
sounds: ImmutableMap({
|
||||||
|
@ -87,7 +87,7 @@ const initialState = ImmutableMap({
|
||||||
poll: true,
|
poll: true,
|
||||||
status: true,
|
status: true,
|
||||||
emoji_reaction: true,
|
emoji_reaction: true,
|
||||||
status_reference: false,
|
status_reference: true,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ class StatusPolicy < ApplicationPolicy
|
||||||
def subscribe?
|
def subscribe?
|
||||||
return false unless show?
|
return false unless show?
|
||||||
|
|
||||||
!unlisted? || owned? || following_author? || mention_exists?
|
public? || owned? || following_author? || mention_exists?
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -69,6 +69,10 @@ class StatusPolicy < ApplicationPolicy
|
||||||
author.id == current_account&.id
|
author.id == current_account&.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def public?
|
||||||
|
record.public_visibility?
|
||||||
|
end
|
||||||
|
|
||||||
def unlisted?
|
def unlisted?
|
||||||
record.unlisted_visibility?
|
record.unlisted_visibility?
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,6 +67,10 @@ class NotifyService < BaseService
|
||||||
@recipient.user.settings.interactions['must_be_following'] && !following_sender?
|
@recipient.user.settings.interactions['must_be_following'] && !following_sender?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def optional_non_following_and_reference?
|
||||||
|
status_reference? && @recipient.user.settings.interactions['must_be_following_reference'] && !following_sender?
|
||||||
|
end
|
||||||
|
|
||||||
def optional_non_direct_message?
|
def optional_non_direct_message?
|
||||||
message? && @recipient.user.settings.interactions['must_be_dm_to_send_email'] && !@notification.target_status.direct_visibility?
|
message? && @recipient.user.settings.interactions['must_be_dm_to_send_email'] && !@notification.target_status.direct_visibility?
|
||||||
end
|
end
|
||||||
|
@ -75,6 +79,10 @@ class NotifyService < BaseService
|
||||||
@notification.type == :mention
|
@notification.type == :mention
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def status_reference?
|
||||||
|
@notification.type == :status_reference
|
||||||
|
end
|
||||||
|
|
||||||
def direct_message?
|
def direct_message?
|
||||||
message? && @notification.target_status.direct_visibility?
|
message? && @notification.target_status.direct_visibility?
|
||||||
end
|
end
|
||||||
|
@ -162,6 +170,7 @@ class NotifyService < BaseService
|
||||||
blocked ||= hellbanned? # Hellban
|
blocked ||= hellbanned? # Hellban
|
||||||
blocked ||= optional_non_follower? # Options
|
blocked ||= optional_non_follower? # Options
|
||||||
blocked ||= optional_non_following? # Options
|
blocked ||= optional_non_following? # Options
|
||||||
|
blocked ||= optional_non_following_and_reference? # Options
|
||||||
blocked ||= optional_non_following_and_direct? # Options
|
blocked ||= optional_non_following_and_direct? # Options
|
||||||
blocked ||= conversation_muted?
|
blocked ||= conversation_muted?
|
||||||
blocked ||= send("blocked_#{@notification.type}?") # Type-dependent filters
|
blocked ||= send("blocked_#{@notification.type}?") # Type-dependent filters
|
||||||
|
|
|
@ -38,3 +38,4 @@
|
||||||
= ff.input :must_be_following, as: :boolean, wrapper: :with_label
|
= ff.input :must_be_following, as: :boolean, wrapper: :with_label
|
||||||
= ff.input :must_be_following_dm, as: :boolean, wrapper: :with_label
|
= ff.input :must_be_following_dm, as: :boolean, wrapper: :with_label
|
||||||
= ff.input :must_be_dm_to_send_email, as: :boolean, wrapper: :with_label, fedibird_features: true
|
= ff.input :must_be_dm_to_send_email, as: :boolean, wrapper: :with_label, fedibird_features: true
|
||||||
|
= ff.input :must_be_following_reference, as: :boolean, wrapper: :with_label, fedibird_features: true
|
||||||
|
|
|
@ -307,6 +307,7 @@ en:
|
||||||
must_be_follower: Block notifications from non-followers
|
must_be_follower: Block notifications from non-followers
|
||||||
must_be_following: Block notifications from people you don't follow
|
must_be_following: Block notifications from people you don't follow
|
||||||
must_be_following_dm: Block direct messages from people you don't follow
|
must_be_following_dm: Block direct messages from people you don't follow
|
||||||
|
must_be_following_reference: Block reference notifications from people you don't follow
|
||||||
invite:
|
invite:
|
||||||
comment: Comment
|
comment: Comment
|
||||||
invite_request:
|
invite_request:
|
||||||
|
|
|
@ -311,6 +311,7 @@ ja:
|
||||||
must_be_follower: フォロワー以外からの通知をブロック
|
must_be_follower: フォロワー以外からの通知をブロック
|
||||||
must_be_following: フォローしていないユーザーからの通知をブロック
|
must_be_following: フォローしていないユーザーからの通知をブロック
|
||||||
must_be_following_dm: フォローしていないユーザーからのダイレクトメッセージをブロック
|
must_be_following_dm: フォローしていないユーザーからのダイレクトメッセージをブロック
|
||||||
|
must_be_following_reference: フォローしていないユーザーからの参照通知をブロック
|
||||||
invite:
|
invite:
|
||||||
comment: コメント
|
comment: コメント
|
||||||
invite_request:
|
invite_request:
|
||||||
|
|
|
@ -82,6 +82,7 @@ defaults: &defaults
|
||||||
must_be_follower: false
|
must_be_follower: false
|
||||||
must_be_following: false
|
must_be_following: false
|
||||||
must_be_following_dm: false
|
must_be_following_dm: false
|
||||||
|
must_be_following_reference: true
|
||||||
reserved_usernames:
|
reserved_usernames:
|
||||||
- admin
|
- admin
|
||||||
- support
|
- support
|
||||||
|
|
4
spec/fabricators/status_reference_fabricator.rb
Normal file
4
spec/fabricators/status_reference_fabricator.rb
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Fabricator(:status_reference) do
|
||||||
|
status_id nil
|
||||||
|
target_status_id nil
|
||||||
|
end
|
|
@ -25,6 +25,37 @@ RSpec.describe StatusPolicy, type: :model do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
permissions :subscribe? do
|
||||||
|
it 'grants access when public and account is viewer' do
|
||||||
|
viewer = Fabricate(:account)
|
||||||
|
status.visibility = :public
|
||||||
|
|
||||||
|
expect(subject).to permit(viewer, status)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'grants access when direct and viewer is mentioned' do
|
||||||
|
status.visibility = :unlisted
|
||||||
|
status.mentions = [Fabricate(:mention, account: alice)]
|
||||||
|
|
||||||
|
expect(subject).to permit(alice, status)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'grants access when unlisted and account is following viewer' do
|
||||||
|
follow = Fabricate(:follow)
|
||||||
|
status.visibility = :unlisted
|
||||||
|
status.account = follow.target_account
|
||||||
|
|
||||||
|
expect(subject).to permit(follow.account, status)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'denies access when unlisted and account is not mentioned or following viewer' do
|
||||||
|
viewer = Fabricate(:account)
|
||||||
|
status.visibility = :unlisted
|
||||||
|
|
||||||
|
expect(subject).to_not permit(viewer, status)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
permissions :show? do
|
permissions :show? do
|
||||||
it 'grants access when direct and account is viewer' do
|
it 'grants access when direct and account is viewer' do
|
||||||
status.visibility = :direct
|
status.visibility = :direct
|
||||||
|
|
|
@ -126,6 +126,66 @@ RSpec.describe NotifyService, type: :service do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'status references' do
|
||||||
|
let(:target_status) { Fabricate(:status, account: recipient, visibility: :public) }
|
||||||
|
let(:activity) { Fabricate(:status_reference, status: status, target_status: target_status) }
|
||||||
|
let(:type) { :status_reference }
|
||||||
|
|
||||||
|
before do
|
||||||
|
user.settings.interactions = user.settings.interactions.merge('must_be_following_reference' => enabled)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'if must_be_following_reference is true' do
|
||||||
|
let(:enabled) { true }
|
||||||
|
|
||||||
|
describe 'with public' do
|
||||||
|
let(:status) { Fabricate(:status, account: sender, visibility: :public) }
|
||||||
|
|
||||||
|
it 'does notify' do
|
||||||
|
is_expected.to_not change(Notification, :count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'with unlisted' do
|
||||||
|
let(:status) { Fabricate(:status, account: sender, visibility: :unlisted) }
|
||||||
|
|
||||||
|
it 'does notify when sender is followed' do
|
||||||
|
recipient.follow!(sender)
|
||||||
|
is_expected.to change(Notification, :count)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not notify when sender is not followed' do
|
||||||
|
is_expected.to_not change(Notification, :count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'if must_be_following_reference is false' do
|
||||||
|
let(:enabled) { false }
|
||||||
|
|
||||||
|
describe 'with public' do
|
||||||
|
let(:status) { Fabricate(:status, account: sender, visibility: :public) }
|
||||||
|
|
||||||
|
it 'does notify' do
|
||||||
|
is_expected.to change(Notification, :count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'with unlisted' do
|
||||||
|
let(:status) { Fabricate(:status, account: sender, visibility: :unlisted) }
|
||||||
|
|
||||||
|
it 'does notify when sender is followed' do
|
||||||
|
recipient.follow!(sender)
|
||||||
|
is_expected.to change(Notification, :count)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not notify when sender is not followed' do
|
||||||
|
is_expected.to_not change(Notification, :count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context do
|
context do
|
||||||
let(:asshole) { Fabricate(:account, username: 'asshole') }
|
let(:asshole) { Fabricate(:account, username: 'asshole') }
|
||||||
let(:reply_to) { Fabricate(:status, account: asshole) }
|
let(:reply_to) { Fabricate(:status, account: asshole) }
|
||||||
|
|
Loading…
Reference in a new issue