From: Thibaut Girka Date: Thu, 10 Oct 2019 15:26:08 +0000 (+0200) Subject: Merge branch 'master' into glitch-soc/merge-upstream X-Git-Url: https://git.xn--scling-oua.cat.family/?a=commitdiff_plain;h=61631f475163c5640a78ff66f0ac6c053cda2f84;p=mastodon.git Merge branch 'master' into glitch-soc/merge-upstream Conflicts: - README.md - app/javascript/styles/mastodon/components.scss conflicts caused by image URLs being different - app/models/status.rb as_home_timeline removed, kept glitch-soc-only as_direct_timeline - app/views/statuses/_simple_status.html.haml - config/locales/en.yml some strings were changed upstream - spec/models/status_spec.rb as_home_timeline removed, kept glitch-soc-only as_direct_timeline --- 61631f475163c5640a78ff66f0ac6c053cda2f84 diff --cc app/lib/feed_manager.rb index 4587664b8,d8b486b60..d109d991c --- a/app/lib/feed_manager.rb +++ b/app/lib/feed_manager.rb @@@ -19,11 -19,9 +19,11 @@@ class FeedManage def filter?(timeline_type, status, receiver_id) if timeline_type == :home - filter_from_home?(status, receiver_id) + filter_from_home?(status, receiver_id, build_crutches(receiver_id, [status])) elsif timeline_type == :mentions filter_from_mentions?(status, receiver_id) + elsif timeline_type == :direct + filter_from_direct?(status, receiver_id) else false end @@@ -45,11 -45,12 +47,13 @@@ def push_to_list(list, status) if status.reply? && status.in_reply_to_account_id != status.account_id should_filter = status.in_reply_to_account_id != list.account_id - should_filter &&= !ListAccount.where(list_id: list.id, account_id: status.in_reply_to_account_id).exists? + should_filter &&= !list.show_all_replies? + should_filter &&= !(list.show_list_replies? && ListAccount.where(list_id: list.id, account_id: status.in_reply_to_account_id).exists?) return false if should_filter end + return false unless add_to_feed(:list, list.id, status, list.account.user&.aggregates_reblogs?) + trim(:list, list.id) PushUpdateWorker.perform_async(list.account_id, status.id, "timeline:list:#{list.id}") if push_update_required?("timeline:list:#{list.id}") true diff --cc app/models/form/admin_settings.rb index f1ee38325,70e9c21f1..3398af169 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@@ -32,10 -28,9 +32,11 @@@ class Form::AdminSetting thumbnail hero mascot + show_reblogs_in_public_timelines + show_replies_in_public_timelines spam_check_enabled trends + trendable_by_default show_domain_blocks show_domain_blocks_rationale noindex @@@ -50,12 -45,9 +51,13 @@@ show_known_fediverse_at_about_page preview_sensitive_media profile_directory + hide_followers_count + enable_keybase + show_reblogs_in_public_timelines + show_replies_in_public_timelines spam_check_enabled trends + trendable_by_default noindex ).freeze diff --cc app/models/status.rb index 7ac0fb5bd,0c01a5389..c189d19bf --- a/app/models/status.rb +++ b/app/models/status.rb @@@ -291,54 -282,8 +291,50 @@@ class Status < ApplicationRecor where(language: nil).or where(language: account.chosen_languages) end - def as_home_timeline(account) - where(account: [account] + account.following).where(visibility: [:public, :unlisted, :private]) - end - + def as_direct_timeline(account, limit = 20, max_id = nil, since_id = nil, cache_ids = false) + # direct timeline is mix of direct message from_me and to_me. + # 2 queries are executed with pagination. + # constant expression using arel_table is required for partial index + + # _from_me part does not require any timeline filters + query_from_me = where(account_id: account.id) + .where(Status.arel_table[:visibility].eq(3)) + .limit(limit) + .order('statuses.id DESC') + + # _to_me part requires mute and block filter. + # FIXME: may we check mutes.hide_notifications? + query_to_me = Status + .joins(:mentions) + .merge(Mention.where(account_id: account.id)) + .where(Status.arel_table[:visibility].eq(3)) + .limit(limit) + .order('mentions.status_id DESC') + .not_excluded_by_account(account) + + if max_id.present? + query_from_me = query_from_me.where('statuses.id < ?', max_id) + query_to_me = query_to_me.where('mentions.status_id < ?', max_id) + end + + if since_id.present? + query_from_me = query_from_me.where('statuses.id > ?', since_id) + query_to_me = query_to_me.where('mentions.status_id > ?', since_id) + end + + if cache_ids + # returns array of cache_ids object that have id and updated_at + (query_from_me.cache_ids.to_a + query_to_me.cache_ids.to_a).uniq(&:id).sort_by(&:id).reverse.take(limit) + else + # returns ActiveRecord.Relation + items = (query_from_me.select(:id).to_a + query_to_me.select(:id).to_a).uniq(&:id).sort_by(&:id).reverse.take(limit) + Status.where(id: items.map(&:id)) + end + end + def as_public_timeline(account = nil, local_only = false) - query = timeline_scope(local_only).without_replies + query = timeline_scope(local_only) + query = query.without_replies unless Setting.show_replies_in_public_timelines apply_timeline_filters(query, account, local_only) end diff --cc app/views/statuses/_simple_status.html.haml index fe1591bf9,a68fe1022..a0e77ac6d --- a/app/views/statuses/_simple_status.html.haml +++ b/app/views/statuses/_simple_status.html.haml @@@ -24,7 -24,7 +24,7 @@@ %p{ :style => ('margin-bottom: 0' unless current_account&.user&.setting_expand_spoilers) }< %span.p-summary> #{Formatter.instance.format_spoiler(status, autoplay: autoplay)}  %button.status__content__spoiler-link= t('statuses.show_more') - .e-content{ lang: status.language, style: "display: #{!current_account&.user&.setting_expand_spoilers && status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }< - .e-content{ style: "display: #{!current_account&.user&.setting_expand_spoilers && status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" } ++ .e-content{ style: "display: #{!current_account&.user&.setting_expand_spoilers && status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }< = Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) - if status.preloadable_poll = react_component :poll, disabled: true, poll: ActiveModelSerializers::SerializableResource.new(status.preloadable_poll, serializer: REST::PollSerializer, scope: current_user, scope_name: :current_user).as_json do diff --cc config/locales/en.yml index 2665d0b28,1ffc99eb3..6f742fdf6 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@@ -486,14 -478,8 +485,14 @@@ en open: Anyone can sign up title: Registrations mode show_known_fediverse_at_about_page: - desc_html: When toggled, it will show toots from all the known fediverse on preview. Otherwise it will only show local toots. - title: Show known fediverse on timeline preview + desc_html: When disabled, restricts the public timeline linked from the landing page to showing only local content + title: Include federated content on unauthenticated public timeline page + show_reblogs_in_public_timelines: + desc_html: Show public boosts of public toots in local and public timelines. + title: Show boosts in public timelines + show_replies_in_public_timelines: + desc_html: In addition to public self-replies (threads), show public replies in local and public timelines. + title: Show replies in public timelines show_staff_badge: desc_html: Show a staff badge on a user page title: Show staff badge diff --cc spec/models/status_spec.rb index 8e90b92d0,51a10cd17..02f533287 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@@ -333,99 -296,6 +333,56 @@@ RSpec.describe Status, type: :model d end end - describe '.as_home_timeline' do - let(:account) { Fabricate(:account) } - let(:followed) { Fabricate(:account) } - let(:not_followed) { Fabricate(:account) } - - before do - Fabricate(:follow, account: account, target_account: followed) - - @self_status = Fabricate(:status, account: account, visibility: :public) - @self_direct_status = Fabricate(:status, account: account, visibility: :direct) - @followed_status = Fabricate(:status, account: followed, visibility: :public) - @followed_direct_status = Fabricate(:status, account: followed, visibility: :direct) - @not_followed_status = Fabricate(:status, account: not_followed, visibility: :public) - - @results = Status.as_home_timeline(account) - end - - it 'includes statuses from self' do - expect(@results).to include(@self_status) - end - - it 'does not include direct statuses from self' do - expect(@results).to_not include(@self_direct_status) - end - - it 'includes statuses from followed' do - expect(@results).to include(@followed_status) - end - - it 'does not include direct statuses mentioning recipient from followed' do - Fabricate(:mention, account: account, status: @followed_direct_status) - expect(@results).to_not include(@followed_direct_status) - end - - it 'does not include direct statuses not mentioning recipient from followed' do - expect(@results).not_to include(@followed_direct_status) - end - - it 'does not include statuses from non-followed' do - expect(@results).not_to include(@not_followed_status) - end - end - + describe '.as_direct_timeline' do + let(:account) { Fabricate(:account) } + let(:followed) { Fabricate(:account) } + let(:not_followed) { Fabricate(:account) } + + before do + Fabricate(:follow, account: account, target_account: followed) + + @self_public_status = Fabricate(:status, account: account, visibility: :public) + @self_direct_status = Fabricate(:status, account: account, visibility: :direct) + @followed_public_status = Fabricate(:status, account: followed, visibility: :public) + @followed_direct_status = Fabricate(:status, account: followed, visibility: :direct) + @not_followed_direct_status = Fabricate(:status, account: not_followed, visibility: :direct) + + @results = Status.as_direct_timeline(account) + end + + it 'does not include public statuses from self' do + expect(@results).to_not include(@self_public_status) + end + + it 'includes direct statuses from self' do + expect(@results).to include(@self_direct_status) + end + + it 'does not include public statuses from followed' do + expect(@results).to_not include(@followed_public_status) + end + + it 'does not include direct statuses not mentioning recipient from followed' do + expect(@results).to_not include(@followed_direct_status) + end + + it 'does not include direct statuses not mentioning recipient from non-followed' do + expect(@results).to_not include(@not_followed_direct_status) + end + + it 'includes direct statuses mentioning recipient from followed' do + Fabricate(:mention, account: account, status: @followed_direct_status) + results2 = Status.as_direct_timeline(account) + expect(results2).to include(@followed_direct_status) + end + + it 'includes direct statuses mentioning recipient from non-followed' do + Fabricate(:mention, account: account, status: @not_followed_direct_status) + results2 = Status.as_direct_timeline(account) + expect(results2).to include(@not_followed_direct_status) + end + end + describe '.as_public_timeline' do it 'only includes statuses with public visibility' do public_status = Fabricate(:status, visibility: :public)