about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/settings/preferences/filters_controller.rb9
-rw-r--r--app/controllers/settings/preferences_controller.rb3
-rw-r--r--app/lib/feed_manager.rb39
-rw-r--r--app/lib/user_settings_decorator.rb10
-rw-r--r--app/models/user.rb1
-rw-r--r--app/views/settings/preferences/filters/show.html.haml22
-rw-r--r--app/views/settings/preferences/other/show.html.haml5
7 files changed, 75 insertions, 14 deletions
diff --git a/app/controllers/settings/preferences/filters_controller.rb b/app/controllers/settings/preferences/filters_controller.rb
new file mode 100644
index 000000000..c58a698ef
--- /dev/null
+++ b/app/controllers/settings/preferences/filters_controller.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class Settings::Preferences::FiltersController < Settings::PreferencesController
+  private
+
+  def after_update_redirect_path
+    settings_preferences_filters_path
+  end
+end
diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb
index eb7d2ca07..089d94a31 100644
--- a/app/controllers/settings/preferences_controller.rb
+++ b/app/controllers/settings/preferences_controller.rb
@@ -11,6 +11,7 @@ class Settings::PreferencesController < Settings::BaseController
     user_settings.update(user_settings_params.to_h)
 
     if current_user.update(user_params)
+      Rails.cache.delete("filter_settings:#{current_user.account_id}")
       I18n.locale = current_user.locale
       redirect_to after_update_redirect_path, notice: I18n.t('generic.changes_saved_msg')
     else
@@ -73,6 +74,8 @@ class Settings::PreferencesController < Settings::BaseController
       :setting_boost_every,
       :setting_boost_jitter,
       :setting_boost_random,
+      :setting_filter_to_unknown,
+      :setting_filter_from_unknown,
       notification_emails: %i(follow follow_request reblog favourite mention digest report pending_account trending_tag),
       interactions: %i(must_be_follower must_be_following must_be_following_dm)
     )
diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb
index 0ec341e3f..88fa592a7 100644
--- a/app/lib/feed_manager.rb
+++ b/app/lib/feed_manager.rb
@@ -2,6 +2,7 @@
 
 require 'singleton'
 
+# rubocop:disable Metrics/ClassLength
 class FeedManager
   include Singleton
   include Redisable
@@ -23,7 +24,7 @@ class FeedManager
 
   def filter?(timeline_type, status, receiver_id)
     if [:home, :list].include?(timeline_type)
-      filter_from_home?(status, receiver_id, build_crutches(receiver_id, [status]))
+      filter_from_home?(status, receiver_id, build_crutches(receiver_id, [status]), filter_options_for(receiver_id))
     elsif timeline_type == :mentions
       filter_from_mentions?(status, receiver_id)
     elsif timeline_type == :direct
@@ -142,9 +143,10 @@ class FeedManager
 
     statuses = query.to_a
     crutches = build_crutches(into_account.id, statuses)
+    filter_options = filter_options_for(receiver_id)
 
     statuses.each do |status|
-      next if filter_from_home?(status, into_account.id, crutches)
+      next if filter_from_home?(status, into_account.id, crutches, filter_options)
 
       add_to_feed(:home, into_account.id, status, aggregate)
     end
@@ -242,9 +244,9 @@ class FeedManager
       (context == :home ? Mute.where(account_id: receiver_id, target_account_id: account_ids).any? : Mute.where(account_id: receiver_id, target_account_id: account_ids, hide_notifications: true).any?)
   end
 
-  def filter_from_home?(status, receiver_id, crutches)
+  def filter_from_home?(status, receiver_id, crutches, filter_options)
     return false if receiver_id == status.account_id
-    return true  unless status.published? && (status.conversation&.public? || crutches[:following][status.conversation&.account_id])
+    return true  unless status.published? && (status.conversation&.public? || status.conversation&.account_id == receiver_id || crutches[:following][status.conversation&.account_id])
     return true  if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?)
     return true  if phrase_filtered?(status, receiver_id, :home)
 
@@ -264,18 +266,25 @@ class FeedManager
 
     if status.reply? && !status.in_reply_to_account_id.nil?
       should_filter   = receiver_id != status.in_reply_to_account_id
+      should_filter &&= receiver_id != status.conversation&.account_id
       should_filter &&= status.account_id != status.in_reply_to_account_id
-      should_filter &&= !(crutches[:following][status.in_reply_to_account_id] && crutches[:following][status.conversation&.account_id])
+      should_filter &&= if filter_options[:to_unknown]
+                          !(crutches[:following][status.in_reply_to_account_id] && crutches[:following][status.conversation&.account_id])
+                        else
+                          !crutches[:following][status.in_reply_to_account_id]
+                        end
 
       return !!should_filter
     elsif status.reblog?
       should_filter   = status.reblog.reply?
       should_filter &&= status.reblog.account_id != status.reblog.in_reply_to_account_id
-      should_filter &&= !(crutches[:following][status.reblog.in_reply_to_account_id] && crutches[:following][status.reblog.conversation&.account_id])
-
-      should_filter ||= !crutches[:following][status.reblog.account_id] if status.reblog.account.silenced?
-      should_filter ||= !crutches[:following][status.reblog.conversation&.account_id] if status.reblog.conversation&.account&.silenced?
+      should_filter &&= if filter_options[:to_unknown]
+                          !(crutches[:following][status.reblog.in_reply_to_account_id] && crutches[:following][status.reblog.conversation&.account_id])
+                        else
+                          !crutches[:following][status.reblog.in_reply_to_account_id]
+                        end
 
+      should_filter ||= !crutches[:following][status.reblog.account_id] if filter_options[:from_account] || status.reblog.account.silenced?
       should_filter ||= crutches[:hiding_reblogs][status.account_id]
       should_filter ||= crutches[:blocked_by][status.reblog.account_id]
       should_filter ||= crutches[:domain_blocking][status.reblog.account.domain]
@@ -423,6 +432,17 @@ class FeedManager
     redis.zrem(timeline_key, status.id)
   end
 
+  def filter_options_for(receiver_id)
+    Rails.cache.fetch("filter_settings:#{receiver_id}", expires_in: 1.month) do
+      return {} if (settings = User.find_by(account_id: receiver_id)&.settings).blank?
+
+      {
+        to_unknown: settings.filter_to_unknown,
+        from_unknown: settings.filter_from_unknown,
+      }
+    end
+  end
+
   def build_crutches(receiver_id, statuses)
     crutches = {}
 
@@ -450,3 +470,4 @@ class FeedManager
     crutches
   end
 end
+# rubocop:enable Metrics/ClassLength
diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb
index 28f40dc73..7b67a5a58 100644
--- a/app/lib/user_settings_decorator.rb
+++ b/app/lib/user_settings_decorator.rb
@@ -60,6 +60,8 @@ class UserSettingsDecorator
     user.settings['boost_every']         = boost_every_preference if change?('setting_boost_every')
     user.settings['boost_jitter']        = boost_jitter_preference if change?('setting_boost_jitter')
     user.settings['boost_random']        = boost_random_preference if change?('setting_boost_random')
+    user.settings['filter_to_unknown']   = filter_to_unknown_preference if change?('setting_filter_to_unknown')
+    user.settings['filter_from_unknown'] = filter_from_unknown_preference if change?('setting_filter_from_unknown')
   end
 
   def merged_notification_emails
@@ -226,6 +228,14 @@ class UserSettingsDecorator
     boolean_cast_setting 'setting_boost_random'
   end
 
+  def filter_to_unknown_preference
+    boolean_cast_setting 'setting_filter_to_unknown'
+  end
+
+  def filter_from_unknown_preference
+    boolean_cast_setting 'setting_filter_from_unknown'
+  end
+
   def boolean_cast_setting(key)
     ActiveModel::Type::Boolean.new.cast(settings[key])
   end
diff --git a/app/models/user.rb b/app/models/user.rb
index 8e10d6e9d..9d1af7db6 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -119,6 +119,7 @@ class User < ApplicationRecord
            :style_wide_media,
            :publish_in, :unpublish_in, :unpublish_delete, :boost_every, :boost_jitter,
            :boost_random,
+           :filter_to_unknown, :filter_from_unknown,
            to: :settings, prefix: :setting, allow_nil: false
 
   attr_reader :invite_code, :sign_in_token_attempt
diff --git a/app/views/settings/preferences/filters/show.html.haml b/app/views/settings/preferences/filters/show.html.haml
new file mode 100644
index 000000000..f91010724
--- /dev/null
+++ b/app/views/settings/preferences/filters/show.html.haml
@@ -0,0 +1,22 @@
+- content_for :page_title do
+  = t('settings.preferences')
+
+- content_for :heading_actions do
+  = button_tag t('generic.save_changes'), class: 'button', form: 'edit_preferences'
+
+= simple_form_for current_user, url: settings_preferences_filters_path, html: { method: :put, id: 'edit_preferences' } do |f|
+  = render 'shared/error_messages', object: current_user
+
+  %h4= t 'preferences.filtering'
+
+  .fields-group
+    = f.input :setting_filter_to_unknown, as: :boolean, wrapper: :with_label
+    = f.input :setting_filter_from_unknown, as: :boolean, wrapper: :with_label
+
+  %h4= t 'preferences.public_timelines'
+
+  .fields-group
+    = f.input :chosen_languages, collection: filterable_languages.sort, wrapper: :with_block_label, include_blank: false, label_method: lambda { |locale| human_locale(locale) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
+
+  .actions
+    = f.button :button, t('generic.save_changes'), type: :submit
diff --git a/app/views/settings/preferences/other/show.html.haml b/app/views/settings/preferences/other/show.html.haml
index efe8cd0db..87a03a515 100644
--- a/app/views/settings/preferences/other/show.html.haml
+++ b/app/views/settings/preferences/other/show.html.haml
@@ -41,10 +41,5 @@
   .fields-group
     = f.input :setting_default_content_type, collection: ['text/plain', 'text/markdown', 'text/html'], wrapper: :with_label, include_blank: false, label_method: lambda { |item| safe_join([t("simple_form.labels.defaults.setting_default_content_type_#{item.split('/')[1]}"), content_tag(:span, t("simple_form.hints.defaults.setting_default_content_type_#{item.split('/')[1]}"), class: 'hint')]) }, required: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
 
-  %h4= t 'preferences.public_timelines'
-
-  .fields-group
-    = f.input :chosen_languages, collection: filterable_languages.sort, wrapper: :with_block_label, include_blank: false, label_method: lambda { |locale| human_locale(locale) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
-
   .actions
     = f.button :button, t('generic.save_changes'), type: :submit