Add preference to hide following/followers lists (#7532)

* Add preference to hide following/followers lists

- Public pages
- ActivityPub collections (does not return pages but does give total)
- REST API (unless it's your own) (does not federate)

Fix #6901

* Add preference

* Add delegation

* Fix issue

* Fix issue
This commit is contained in:
Eugen Rochko 2018-05-18 02:26:51 +02:00 committed by GitHub
parent 919eef3098
commit 1e02dc8715
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 58 additions and 9 deletions

View file

@ -19,6 +19,8 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
end end
def load_accounts def load_accounts
return [] if @account.user_hides_network? && current_account.id != @account.id
default_accounts.merge(paginated_follows).to_a default_accounts.merge(paginated_follows).to_a
end end

View file

@ -19,6 +19,8 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
end end
def load_accounts def load_accounts
return [] if @account.user_hides_network? && current_account.id != @account.id
default_accounts.merge(paginated_follows).to_a default_accounts.merge(paginated_follows).to_a
end end

View file

@ -6,11 +6,15 @@ class FollowerAccountsController < ApplicationController
def index def index
respond_to do |format| respond_to do |format|
format.html do format.html do
next if @account.user_hides_network?
follows follows
@relationships = AccountRelationshipsPresenter.new(follows.map(&:account_id), current_user.account_id) if user_signed_in? @relationships = AccountRelationshipsPresenter.new(follows.map(&:account_id), current_user.account_id) if user_signed_in?
end end
format.json do format.json do
raise Mastodon::NotPermittedError if params[:page].present? && @account.user_hides_network?
render json: collection_presenter, render json: collection_presenter,
serializer: ActivityPub::CollectionSerializer, serializer: ActivityPub::CollectionSerializer,
adapter: ActivityPub::Adapter, adapter: ActivityPub::Adapter,

View file

@ -6,11 +6,15 @@ class FollowingAccountsController < ApplicationController
def index def index
respond_to do |format| respond_to do |format|
format.html do format.html do
next if @account.user_hides_network?
follows follows
@relationships = AccountRelationshipsPresenter.new(follows.map(&:target_account_id), current_user.account_id) if user_signed_in? @relationships = AccountRelationshipsPresenter.new(follows.map(&:target_account_id), current_user.account_id) if user_signed_in?
end end
format.json do format.json do
raise Mastodon::NotPermittedError if params[:page].present? && @account.user_hides_network?
render json: collection_presenter, render json: collection_presenter,
serializer: ActivityPub::CollectionSerializer, serializer: ActivityPub::CollectionSerializer,
adapter: ActivityPub::Adapter, adapter: ActivityPub::Adapter,

View file

@ -44,6 +44,7 @@ class Settings::PreferencesController < ApplicationController
:setting_system_font_ui, :setting_system_font_ui,
:setting_noindex, :setting_noindex,
:setting_theme, :setting_theme,
:setting_hide_network,
notification_emails: %i(follow follow_request reblog favourite mention digest), notification_emails: %i(follow follow_request reblog favourite mention digest),
interactions: %i(must_be_follower must_be_following) interactions: %i(must_be_follower must_be_following)
) )

View file

@ -322,6 +322,15 @@
z-index: 2; z-index: 2;
position: relative; position: relative;
&.empty img {
position: absolute;
opacity: 0.2;
height: 200px;
left: 0;
bottom: 0;
pointer-events: none;
}
@media screen and (max-width: 740px) { @media screen and (max-width: 740px) {
border-radius: 0; border-radius: 0;
box-shadow: none; box-shadow: none;
@ -438,8 +447,8 @@
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
text-align: center; text-align: center;
padding: 60px 0; padding: 130px 0;
padding-top: 55px; padding-top: 125px;
margin: 0 auto; margin: 0 auto;
cursor: default; cursor: default;
} }

View file

@ -4,7 +4,7 @@
font-size: 12px; font-size: 12px;
color: $darker-text-color; color: $darker-text-color;
.domain { .footer__domain {
font-weight: 500; font-weight: 500;
a { a {

View file

@ -28,6 +28,7 @@ class UserSettingsDecorator
user.settings['system_font_ui'] = system_font_ui_preference if change?('setting_system_font_ui') user.settings['system_font_ui'] = system_font_ui_preference if change?('setting_system_font_ui')
user.settings['noindex'] = noindex_preference if change?('setting_noindex') user.settings['noindex'] = noindex_preference if change?('setting_noindex')
user.settings['theme'] = theme_preference if change?('setting_theme') user.settings['theme'] = theme_preference if change?('setting_theme')
user.settings['hide_network'] = hide_network_preference if change?('setting_hide_network')
end end
def merged_notification_emails def merged_notification_emails
@ -78,6 +79,10 @@ class UserSettingsDecorator
boolean_cast_setting 'setting_noindex' boolean_cast_setting 'setting_noindex'
end end
def hide_network_preference
boolean_cast_setting 'setting_hide_network'
end
def theme_preference def theme_preference
settings['setting_theme'] settings['setting_theme']
end end

View file

@ -136,6 +136,7 @@ class Account < ApplicationRecord
:moderator?, :moderator?,
:staff?, :staff?,
:locale, :locale,
:hides_network?,
to: :user, to: :user,
prefix: true, prefix: true,
allow_nil: true allow_nil: true

View file

@ -86,7 +86,7 @@ class User < ApplicationRecord
has_many :session_activations, dependent: :destroy has_many :session_activations, dependent: :destroy
delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :delete_modal, delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :delete_modal,
:reduce_motion, :system_font_ui, :noindex, :theme, :display_sensitive_media, :reduce_motion, :system_font_ui, :noindex, :theme, :display_sensitive_media, :hide_network,
to: :settings, prefix: :setting, allow_nil: false to: :settings, prefix: :setting, allow_nil: false
attr_accessor :invite_code attr_accessor :invite_code
@ -219,6 +219,10 @@ class User < ApplicationRecord
settings.notification_emails['digest'] settings.notification_emails['digest']
end end
def hides_network?
@hides_network ||= settings.hide_network
end
def token_for_app(a) def token_for_app(a)
return nil if a.nil? || a.owner != self return nil if a.nil? || a.owner != self
Doorkeeper::AccessToken Doorkeeper::AccessToken

View file

@ -1,5 +1,6 @@
.accounts-grid .accounts-grid{ class: accounts.empty? ? 'empty' : '' }
- if accounts.empty? - if accounts.empty?
= image_tag asset_pack_path('elephant_ui_greeting.svg'), alt: '', role: 'presentational'
= render partial: 'accounts/nothing_here' = render partial: 'accounts/nothing_here'
- else - else
= render partial: 'accounts/grid_card', collection: accounts, as: :account, cached: !user_signed_in? = render partial: 'accounts/grid_card', collection: accounts, as: :account, cached: !user_signed_in?

View file

@ -0,0 +1,3 @@
.accounts-grid.empty
= image_tag asset_pack_path('elephant_ui_greeting.svg'), alt: '', role: 'presentational'
%p.nothing-here= t('accounts.network_hidden')

View file

@ -7,4 +7,7 @@
= render 'accounts/header', account: @account = render 'accounts/header', account: @account
= render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:account) - if @account.user_hides_network?
= render 'accounts/follow_grid_hidden'
- else
= render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:account)

View file

@ -7,4 +7,7 @@
= render 'accounts/header', account: @account = render 'accounts/header', account: @account
= render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:target_account) - if @account.user_hides_network?
= render 'accounts/follow_grid_hidden'
- else
= render 'accounts/follow_grid', follows: @follows, accounts: @follows.map(&:target_account)

View file

@ -8,9 +8,9 @@
%span.single-user-login %span.single-user-login
= link_to t('auth.login'), new_user_session_path = link_to t('auth.login'), new_user_session_path
&mdash; &mdash;
%span.domain= link_to site_hostname, about_path %span.footer__domain= link_to site_hostname, about_path
- else - else
%span.domain= link_to site_hostname, root_path %span.footer__domain= link_to site_hostname, root_path
%span.powered-by %span.powered-by
!= t('generic.powered_by', link: link_to('Mastodon', 'https://joinmastodon.org')) != t('generic.powered_by', link: link_to('Mastodon', 'https://joinmastodon.org'))

View file

@ -26,6 +26,9 @@
.fields-group .fields-group
= f.input :setting_noindex, as: :boolean, wrapper: :with_label = f.input :setting_noindex, as: :boolean, wrapper: :with_label
.fields-group
= f.input :setting_hide_network, as: :boolean, wrapper: :with_label
%h4= t 'preferences.web' %h4= t 'preferences.web'
.fields-group .fields-group

View file

@ -40,6 +40,7 @@ en:
following: Following following: Following
media: Media media: Media
moved_html: "%{name} has moved to %{new_profile_link}:" moved_html: "%{name} has moved to %{new_profile_link}:"
network_hidden: This information is not available
nothing_here: There is nothing here! nothing_here: There is nothing here!
people_followed_by: People whom %{name} follows people_followed_by: People whom %{name} follows
people_who_follow: People who follow %{name} people_who_follow: People who follow %{name}

View file

@ -15,6 +15,7 @@ en:
note: note:
one: <span class="note-counter">1</span> character left one: <span class="note-counter">1</span> character left
other: <span class="note-counter">%{count}</span> characters left other: <span class="note-counter">%{count}</span> characters left
setting_hide_network: Who you follow and who follows you will not be shown on your profile
setting_noindex: Affects your public profile and status pages setting_noindex: Affects your public profile and status pages
setting_theme: Affects how Mastodon looks when you're logged in from any device. setting_theme: Affects how Mastodon looks when you're logged in from any device.
imports: imports:
@ -54,6 +55,7 @@ en:
setting_default_sensitive: Always mark media as sensitive setting_default_sensitive: Always mark media as sensitive
setting_delete_modal: Show confirmation dialog before deleting a toot setting_delete_modal: Show confirmation dialog before deleting a toot
setting_display_sensitive_media: Always show media marked as sensitive setting_display_sensitive_media: Always show media marked as sensitive
setting_hide_network: Hide your network
setting_noindex: Opt-out of search engine indexing setting_noindex: Opt-out of search engine indexing
setting_reduce_motion: Reduce motion in animations setting_reduce_motion: Reduce motion in animations
setting_system_font_ui: Use system's default font setting_system_font_ui: Use system's default font

View file

@ -20,6 +20,7 @@ defaults: &defaults
timeline_preview: true timeline_preview: true
show_staff_badge: true show_staff_badge: true
default_sensitive: false default_sensitive: false
hide_network: false
unfollow_modal: false unfollow_modal: false
boost_modal: false boost_modal: false
delete_modal: true delete_modal: true