From: Thibaut Girka Date: Fri, 19 Jul 2019 16:26:49 +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=249991c498a37b25ef4d35f5d0898ff05d4dd1de;p=mastodon.git Merge branch 'master' into glitch-soc/merge-upstream Conflicts: - Gemfile.lock - app/controllers/accounts_controller.rb - app/controllers/admin/dashboard_controller.rb - app/controllers/follower_accounts_controller.rb - app/controllers/following_accounts_controller.rb - app/controllers/remote_follow_controller.rb - app/controllers/stream_entries_controller.rb - app/controllers/tags_controller.rb - app/javascript/packs/public.js - app/lib/sanitize_config.rb - app/models/account.rb - app/models/form/admin_settings.rb - app/models/media_attachment.rb - app/models/stream_entry.rb - app/models/user.rb - app/serializers/initial_state_serializer.rb - app/services/batched_remove_status_service.rb - app/services/post_status_service.rb - app/services/process_mentions_service.rb - app/services/reblog_service.rb - app/services/remove_status_service.rb - app/views/admin/settings/edit.html.haml - config/locales/simple_form.pl.yml - config/settings.yml - docker-compose.yml --- 249991c498a37b25ef4d35f5d0898ff05d4dd1de diff --cc app/controllers/about_controller.rb index 5850bd56d,33bac9bbc..a6e33a5d9 --- a/app/controllers/about_controller.rb +++ b/app/controllers/about_controller.rb @@@ -1,16 -1,19 +1,20 @@@ # frozen_string_literal: true class AboutController < ApplicationController + before_action :set_pack layout 'public' - before_action :set_instance_presenter, only: [:show, :more, :terms] + before_action :set_body_classes, only: :show + before_action :set_instance_presenter + before_action :set_expires_in - def show - @hide_navbar = true - end + skip_before_action :check_user_permissions, only: [:more, :terms] - def more; end + def show; end + + def more + flash.now[:notice] = I18n.t('about.instance_actor_flash') if params[:instance_actor] + end def terms; end diff --cc app/controllers/accounts_controller.rb index 051b6ecbd,fc913c2ec..ff684e31e --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@@ -10,10 -12,8 +12,9 @@@ class AccountsController < ApplicationC def show respond_to do |format| format.html do + use_pack 'public' - mark_cacheable! unless user_signed_in? + expires_in 0, public: true unless user_signed_in? - @body_classes = 'with-modals' @pinned_statuses = [] @endorsed_accounts = @account.endorsed_accounts.to_a.sample(4) diff --cc app/controllers/admin/dashboard_controller.rb index aedfeb70e,e74e4755f..faa2df1b5 --- a/app/controllers/admin/dashboard_controller.rb +++ b/app/controllers/admin/dashboard_controller.rb @@@ -30,7 -30,7 +30,8 @@@ module Admi @trending_hashtags = TrendingTags.get(7) @profile_directory = Setting.profile_directory @timeline_preview = Setting.timeline_preview + @keybase_integration = Setting.enable_keybase + @spam_check_enabled = Setting.spam_check_enabled end private diff --cc app/controllers/follower_accounts_controller.rb index fab9c8462,6e873de5b..e2ba9bf00 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@@ -8,8 -10,7 +10,8 @@@ class FollowerAccountsController < Appl def index respond_to do |format| format.html do + use_pack 'public' - mark_cacheable! unless user_signed_in? + expires_in 0, public: true unless user_signed_in? next if @account.user_hides_network? @@@ -41,11 -46,11 +47,11 @@@ end def collection_presenter + options = { type: :ordered } + options[:size] = @account.followers_count unless Setting.hide_followers_count || @account.user&.setting_hide_followers_count - if params[:page].present? + if page_requested? ActivityPub::CollectionPresenter.new( id: account_followers_url(@account, page: params.fetch(:page, 1)), - type: :ordered, - size: @account.followers_count, items: follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.account) }, part_of: account_followers_url(@account), next: page_url(follows.next_page), diff --cc app/controllers/following_accounts_controller.rb index 272116040,07d62f7dd..49f1f3218 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@@ -8,8 -10,7 +10,8 @@@ class FollowingAccountsController < App def index respond_to do |format| format.html do + use_pack 'public' - mark_cacheable! unless user_signed_in? + expires_in 0, public: true unless user_signed_in? next if @account.user_hides_network? diff --cc app/controllers/remote_follow_controller.rb index 17bc1940a,0fb71d335..46dd444a4 --- a/app/controllers/remote_follow_controller.rb +++ b/app/controllers/remote_follow_controller.rb @@@ -1,11 -1,10 +1,11 @@@ # frozen_string_literal: true class RemoteFollowController < ApplicationController + include AccountOwnedConcern + layout 'modal' - before_action :set_account + before_action :set_pack - before_action :gone, if: :suspended_account? before_action :set_body_classes def new @@@ -33,18 -32,6 +33,10 @@@ { acct: session[:remote_follow] } end + def set_pack + use_pack 'modal' + end + - def set_account - @account = Account.find_local!(params[:account_username]) - end - - def suspended_account? - @account.suspended? - end - def set_body_classes @body_classes = 'modal-layout' @hide_header = true diff --cc app/controllers/statuses_controller.rb index 66ba260aa,22e7519f9..0190a3c54 --- a/app/controllers/statuses_controller.rb +++ b/app/controllers/statuses_controller.rb @@@ -27,16 -25,9 +25,11 @@@ class StatusesController < ApplicationC def show respond_to do |format| format.html do + use_pack 'public' + expires_in 10.seconds, public: true if current_account.nil? - - @body_classes = 'with-modals' - set_ancestors set_descendants - - render 'stream_entries/show' end format.json do diff --cc app/controllers/tags_controller.rb index 5cb048c1a,d08e5a61a..b4e6dbc92 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@@ -9,11 -13,10 +13,11 @@@ class TagsController < ApplicationContr before_action :set_instance_presenter def show - @tag = Tag.find_normalized!(params[:id]) - respond_to do |format| format.html do + use_pack 'about' + expires_in 0, public: true + @initial_state_json = ActiveModelSerializers::SerializableResource.new( InitialStatePresenter.new(settings: {}, token: current_session&.token), serializer: InitialStateSerializer diff --cc app/javascript/core/public.js index 33b7a207d,000000000..0f4222139 mode 100644,000000..100644 --- a/app/javascript/core/public.js +++ b/app/javascript/core/public.js @@@ -1,66 -1,0 +1,66 @@@ +// This file will be loaded on public pages, regardless of theme. + +import createHistory from 'history/createBrowserHistory'; +import ready from '../mastodon/ready'; + +const { delegate } = require('rails-ujs'); +const { length } = require('stringz'); + +delegate(document, '.webapp-btn', 'click', ({ target, button }) => { + if (button !== 0) { + return true; + } + window.location.href = target.href; + return false; +}); + +delegate(document, '.status__content__spoiler-link', 'click', function() { + const contentEl = this.parentNode.parentNode.querySelector('.e-content'); + + if (contentEl.style.display === 'block') { + contentEl.style.display = 'none'; + this.parentNode.style.marginBottom = 0; + } else { + contentEl.style.display = 'block'; + this.parentNode.style.marginBottom = null; + } + + return false; +}); + +delegate(document, '.modal-button', 'click', e => { + e.preventDefault(); + + let href; + + if (e.target.nodeName !== 'A') { + href = e.target.parentNode.href; + } else { + href = e.target.href; + } + + window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes'); +}); + +const getProfileAvatarAnimationHandler = (swapTo) => { + //animate avatar gifs on the profile page when moused over + return ({ target }) => { + const swapSrc = target.getAttribute(swapTo); + //only change the img source if autoplay is off and the image src is actually different - if(target.getAttribute('data-autoplay') === 'false' && target.src !== swapSrc) { ++ if(target.getAttribute('data-autoplay') !== 'true' && target.src !== swapSrc) { + target.src = swapSrc; + } + }; +}; + +delegate(document, 'img#profile_page_avatar', 'mouseover', getProfileAvatarAnimationHandler('data-original')); + +delegate(document, 'img#profile_page_avatar', 'mouseout', getProfileAvatarAnimationHandler('data-static')); + +delegate(document, '#account_header', 'change', ({ target }) => { + const header = document.querySelector('.card .card__img img'); + const [file] = target.files || []; + const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc; + + header.src = url; +}); diff --cc app/javascript/packs/public.js index 69e6ba0ec,0c60d828e..69441d315 --- a/app/javascript/packs/public.js +++ b/app/javascript/packs/public.js @@@ -91,15 -108,127 +91,7 @@@ function main() if (parallaxComponents.length > 0 ) { new Rellax('.parallax', { speed: -1 }); } - - if (document.body.classList.contains('with-modals')) { - const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth; - const scrollbarWidthStyle = document.createElement('style'); - scrollbarWidthStyle.id = 'scrollbar-width'; - document.head.appendChild(scrollbarWidthStyle); - scrollbarWidthStyle.sheet.insertRule(`body.with-modals--active { margin-right: ${scrollbarWidth}px; }`, 0); - } }); - - delegate(document, '.webapp-btn', 'click', ({ target, button }) => { - if (button !== 0) { - return true; - } - window.location.href = target.href; - return false; - }); - - delegate(document, '.status__content__spoiler-link', 'click', function() { - const contentEl = this.parentNode.parentNode.querySelector('.e-content'); - - if (contentEl.style.display === 'block') { - contentEl.style.display = 'none'; - this.parentNode.style.marginBottom = 0; - } else { - contentEl.style.display = 'block'; - this.parentNode.style.marginBottom = null; - } - - return false; - }); - - delegate(document, '.modal-button', 'click', e => { - e.preventDefault(); - - let href; - - if (e.target.nodeName !== 'A') { - href = e.target.parentNode.href; - } else { - href = e.target.href; - } - - window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes'); - }); - - delegate(document, '#account_display_name', 'input', ({ target }) => { - const name = document.querySelector('.card .display-name strong'); - if (name) { - if (target.value) { - name.innerHTML = emojify(escapeTextContentForBrowser(target.value)); - } else { - name.textContent = document.querySelector('#default_account_display_name').textContent; - } - } - }); - - delegate(document, '#account_avatar', 'change', ({ target }) => { - const avatar = document.querySelector('.card .avatar img'); - const [file] = target.files || []; - const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc; - - avatar.src = url; - }); - - const getProfileAvatarAnimationHandler = (swapTo) => { - //animate avatar gifs on the profile page when moused over - return ({ target }) => { - const swapSrc = target.getAttribute(swapTo); - //only change the img source if autoplay is off and the image src is actually different - if(target.getAttribute('data-autoplay') !== 'true' && target.src !== swapSrc) { - target.src = swapSrc; - } - }; - }; - - delegate(document, 'img#profile_page_avatar', 'mouseover', getProfileAvatarAnimationHandler('data-original')); - - delegate(document, 'img#profile_page_avatar', 'mouseout', getProfileAvatarAnimationHandler('data-static')); - - delegate(document, '#account_header', 'change', ({ target }) => { - const header = document.querySelector('.card .card__img img'); - const [file] = target.files || []; - const url = file ? URL.createObjectURL(file) : header.dataset.originalSrc; - - header.src = url; - }); - - delegate(document, '#account_locked', 'change', ({ target }) => { - const lock = document.querySelector('.card .display-name i'); - - if (target.checked) { - lock.style.display = 'inline'; - } else { - lock.style.display = 'none'; - } - }); - - delegate(document, '.input-copy input', 'click', ({ target }) => { - target.focus(); - target.select(); - target.setSelectionRange(0, target.value.length); - }); - - delegate(document, '.input-copy button', 'click', ({ target }) => { - const input = target.parentNode.querySelector('.input-copy__wrapper input'); - - const oldReadOnly = input.readonly; - - input.readonly = false; - input.focus(); - input.select(); - input.setSelectionRange(0, input.value.length); - - try { - if (document.execCommand('copy')) { - input.blur(); - target.parentNode.classList.add('copied'); - - setTimeout(() => { - target.parentNode.classList.remove('copied'); - }, 700); - } - } catch (err) { - console.error(err); - } - - input.readonly = oldReadOnly; - }); } loadPolyfills().then(main).catch(error => { diff --cc app/models/account.rb index 3d7b0dda3,ccd116d6e..3370fbc5e --- a/app/models/account.rb +++ b/app/models/account.rb @@@ -62,10 -63,11 +63,15 @@@ class Account < ApplicationRecor include AccountCounters include DomainNormalizable + MAX_DISPLAY_NAME_LENGTH = (ENV['MAX_DISPLAY_NAME_CHARS'] || 30).to_i + MAX_NOTE_LENGTH = (ENV['MAX_BIO_CHARS'] || 500).to_i + MAX_FIELDS = (ENV['MAX_PROFILE_FIELDS'] || 4).to_i + + TRUST_LEVELS = { + untrusted: 0, + trusted: 1, + }.freeze + enum protocol: [:ostatus, :activitypub] validates :username, presence: true @@@ -75,12 -77,12 +81,12 @@@ validates :username, format: { with: /\A#{USERNAME_RE}\z/i }, if: -> { !local? && will_save_change_to_username? } # Local user validations - validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? } + validates :username, format: { with: /\A[a-z0-9_]+\z/i }, length: { maximum: 30 }, if: -> { local? && will_save_change_to_username? && actor_type != 'Application' } validates_with UniqueUsernameValidator, if: -> { local? && will_save_change_to_username? } validates_with UnreservedUsernameValidator, if: -> { local? && will_save_change_to_username? } - validates :display_name, length: { maximum: 30 }, if: -> { local? && will_save_change_to_display_name? } - validates :note, note_length: { maximum: 500 }, if: -> { local? && will_save_change_to_note? } - validates :fields, length: { maximum: 4 }, if: -> { local? && will_save_change_to_fields? } + validates :display_name, length: { maximum: MAX_DISPLAY_NAME_LENGTH }, if: -> { local? && will_save_change_to_display_name? } + validates :note, note_length: { maximum: MAX_NOTE_LENGTH }, if: -> { local? && will_save_change_to_note? } + validates :fields, length: { maximum: MAX_FIELDS }, if: -> { local? && will_save_change_to_fields? } scope :remote, -> { where.not(domain: nil) } scope :local, -> { where(domain: nil) } diff --cc app/models/concerns/account_associations.rb index ecccaf35e,0921e3252..2877b9c25 --- a/app/models/concerns/account_associations.rb +++ b/app/models/concerns/account_associations.rb @@@ -11,10 -11,8 +11,9 @@@ module AccountAssociation has_many :identity_proofs, class_name: 'AccountIdentityProof', dependent: :destroy, inverse_of: :account # Timelines - has_many :stream_entries, inverse_of: :account, dependent: :destroy has_many :statuses, inverse_of: :account, dependent: :destroy has_many :favourites, inverse_of: :account, dependent: :destroy + has_many :bookmarks, inverse_of: :account, dependent: :destroy has_many :mentions, inverse_of: :account, dependent: :destroy has_many :notifications, inverse_of: :account, dependent: :destroy has_many :conversations, class_name: 'AccountConversation', dependent: :destroy, inverse_of: :account diff --cc app/models/form/admin_settings.rb index 0e9bfb265,2c03c88a8..ecaed44f6 --- a/app/models/form/admin_settings.rb +++ b/app/models/form/admin_settings.rb @@@ -32,8 -28,7 +32,9 @@@ class Form::AdminSetting thumbnail hero mascot + show_reblogs_in_public_timelines + show_replies_in_public_timelines + spam_check_enabled ).freeze BOOLEAN_KEYS = %i( @@@ -45,10 -40,7 +46,11 @@@ 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 ).freeze UPLOAD_KEYS = %i( diff --cc app/models/user.rb index bb903a45c,31c99630c..72fc92195 --- a/app/models/user.rb +++ b/app/models/user.rb @@@ -103,10 -103,10 +103,10 @@@ class User < ApplicationRecor has_many :session_activations, dependent: :destroy - delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :delete_modal, - :reduce_motion, :system_font_ui, :noindex, :theme, :display_media, :hide_network, + delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :favourite_modal, :delete_modal, + :reduce_motion, :system_font_ui, :noindex, :flavour, :skin, :display_media, :hide_network, :hide_followers_count, :expand_spoilers, :default_language, :aggregate_reblogs, :show_application, - :advanced_layout, :default_content_type, :use_blurhash, :use_pending_items, to: :settings, prefix: :setting, allow_nil: false - :advanced_layout, :use_blurhash, :use_pending_items, to: :settings, prefix: :setting, allow_nil: false ++ :advanced_layout, :default_content_type, :use_blurhash, :use_pending_items, :use_pending_items, to: :settings, prefix: :setting, allow_nil: false attr_reader :invite_code attr_writer :external diff --cc app/services/batched_remove_status_service.rb index 2fe009c91,27dc460a6..bbee47cb7 --- a/app/services/batched_remove_status_service.rb +++ b/app/services/batched_remove_status_service.rb @@@ -46,12 -40,7 +40,8 @@@ class BatchedRemoveStatusService < Base # Cannot be batched statuses.each do |status| unpush_from_public_timelines(status) + unpush_from_direct_timelines(status) if status.direct_visibility? - batch_salmon_slaps(status) if status.local? end - - Pubsubhubbub::RawDistributionWorker.push_bulk(@stream_entry_batches) { |batch| batch } - NotificationWorker.push_bulk(@salmon_batches) { |batch| batch } end private @@@ -102,30 -85,4 +86,14 @@@ end end end + + def unpush_from_direct_timelines(status) + payload = @json_payloads[status.id] + redis.pipelined do + @mentions[status.id].each do |mention| + FeedManager.instance.unpush_from_direct(mention.account, status) if mention.account.local? + end + FeedManager.instance.unpush_from_direct(status.account, status) if status.account.local? + end + end - - def batch_salmon_slaps(status) - return if @mentions[status.id].empty? - - recipients = @mentions[status.id].map(&:account).reject(&:local?).select(&:ostatus?).uniq(&:domain).map(&:id) - - recipients.each do |recipient_id| - @salmon_batches << [build_xml(status.stream_entry), status.account_id, recipient_id] - end - end - - def build_xml(stream_entry) - return @activity_xml[stream_entry.id] if @activity_xml.key?(stream_entry.id) - - @activity_xml[stream_entry.id] = stream_entry_to_xml(stream_entry) - end end diff --cc app/services/post_status_service.rb index 6d7c44913,34ec6d504..b36471339 --- a/app/services/post_status_service.rb +++ b/app/services/post_status_service.rb @@@ -91,12 -88,7 +91,7 @@@ class PostStatusService < BaseServic def postprocess_status! LinkCrawlWorker.perform_async(@status.id) unless @status.spoiler_text? DistributionWorker.perform_async(@status.id) - - unless @status.local_only? - Pubsubhubbub::DistributionWorker.perform_async(@status.stream_entry.id) - ActivityPub::DistributionWorker.perform_async(@status.id) - end - - ActivityPub::DistributionWorker.perform_async(@status.id) ++ ActivityPub::DistributionWorker.perform_async(@status.id) unless @status.local_only? PollExpirationNotifyWorker.perform_at(@status.poll.expires_at, @status.poll.id) if @status.poll end diff --cc app/services/process_mentions_service.rb index 1804e0c93,90dca9740..a374206eb --- a/app/services/process_mentions_service.rb +++ b/app/services/process_mentions_service.rb @@@ -49,9 -48,7 +48,7 @@@ class ProcessMentionsService < BaseServ if mentioned_account.local? LocalNotificationWorker.perform_async(mentioned_account.id, mention.id, mention.class.name) - elsif mentioned_account.ostatus? && !@status.stream_entry.hidden? && !@status.local_only? - NotificationWorker.perform_async(ostatus_xml, @status.account_id, mentioned_account.id) - elsif mentioned_account.activitypub? + elsif mentioned_account.activitypub? && !@status.local_only? ActivityPub::DeliveryWorker.perform_async(activitypub_json, mention.status.account_id, mentioned_account.inbox_url) end end diff --cc app/services/reblog_service.rb index 09403bae0,3bb460fca..0b12f143c --- a/app/services/reblog_service.rb +++ b/app/services/reblog_service.rb @@@ -24,11 -23,7 +23,7 @@@ class ReblogService < BaseServic reblog = account.statuses.create!(reblog: reblogged_status, text: '', visibility: visibility) DistributionWorker.perform_async(reblog.id) - - unless reblogged_status.local_only? - Pubsubhubbub::DistributionWorker.perform_async(reblog.stream_entry.id) - ActivityPub::DistributionWorker.perform_async(reblog.id) - end - ActivityPub::DistributionWorker.perform_async(reblog.id) ++ ActivityPub::DistributionWorker.perform_async(reblog.id) unless reblogged_status.local_only? create_notification(reblog) bump_potential_friendship(account, reblog) diff --cc app/services/remove_status_service.rb index 9d5d0fc14,a69fce8b8..958a67e8f --- a/app/services/remove_status_service.rb +++ b/app/services/remove_status_service.rb @@@ -25,7 -23,7 +23,8 @@@ class RemoveStatusService < BaseServic remove_from_hashtags remove_from_public remove_from_media if status.media_attachments.any? + remove_from_direct if status.direct_visibility? + remove_from_spam_check @status.destroy! else @@@ -158,12 -143,10 +145,16 @@@ redis.publish('timeline:public:local:media', @payload) if @status.local? end + def remove_from_direct + @mentions.each do |mention| + FeedManager.instance.unpush_from_direct(mention.account, @status) if mention.account.local? + end + end + + def remove_from_spam_check + redis.zremrangebyscore("spam_check:#{@status.account_id}", @status.id, @status.id) + end + def lock_options { redis: Redis.current, key: "distribute:#{@status.id}" } end diff --cc app/views/admin/dashboard/index.html.haml index 76dbf4388,77cc1a2a0..54cf9af5d --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@@ -49,10 -49,10 +49,12 @@@ = feature_hint(link_to(t('admin.dashboard.feature_profile_directory'), edit_admin_settings_path), @profile_directory) %li = feature_hint(link_to(t('admin.dashboard.feature_timeline_preview'), edit_admin_settings_path), @timeline_preview) + %li + = feature_hint(link_to(t('admin.dashboard.keybase'), edit_admin_settings_path), @keybase_integration) %li = feature_hint(link_to(t('admin.dashboard.feature_relay'), admin_relays_path), @relay_enabled) + %li + = feature_hint(link_to(t('admin.dashboard.feature_spam_check'), edit_admin_settings_path), @spam_check_enabled) .dashboard__widgets__versions %div diff --cc app/views/admin/settings/edit.html.haml index a8c9f6a58,b3bf3849c..854f4cf87 --- a/app/views/admin/settings/edit.html.haml +++ b/app/views/admin/settings/edit.html.haml @@@ -66,18 -66,9 +66,21 @@@ .fields-group = f.input :profile_directory, as: :boolean, wrapper: :with_label, label: t('admin.settings.profile_directory.title'), hint: t('admin.settings.profile_directory.desc_html') + .fields-group + = f.input :hide_followers_count, as: :boolean, wrapper: :with_label, label: t('admin.settings.hide_followers_count.title'), hint: t('admin.settings.hide_followers_count.desc_html') + + .fields-group + = f.input :enable_keybase, as: :boolean, wrapper: :with_label, label: t('admin.settings.enable_keybase.title'), hint: t('admin.settings.enable_keybase.desc_html') + + .fields-group + = f.input :show_reblogs_in_public_timelines, as: :boolean, wrapper: :with_label, label: t('admin.settings.show_reblogs_in_public_timelines.title'), hint: t('admin.settings.show_reblogs_in_public_timelines.desc_html') + + .fields-group + = f.input :show_replies_in_public_timelines, as: :boolean, wrapper: :with_label, label: t('admin.settings.show_replies_in_public_timelines.title'), hint: t('admin.settings.show_replies_in_public_timelines.desc_html') + + .fields-group + = f.input :spam_check_enabled, as: :boolean, wrapper: :with_label, label: t('admin.settings.spam_check_enabled.title'), hint: t('admin.settings.spam_check_enabled.desc_html') + %hr.spacer/ .fields-group diff --cc config/locales/simple_form.pl.yml index b74bbc2f5,553900855..6a9cf13eb --- a/config/locales/simple_form.pl.yml +++ b/config/locales/simple_form.pl.yml @@@ -34,7 -34,7 +34,8 @@@ pl setting_hide_network: Informacje o tym, kto Cię śledzi i kogo śledzisz nie będą widoczne setting_noindex: Wpływa na widoczność strony profilu i Twoich wpisów setting_show_application: W informacjach o wpisie będzie widoczna informacja o aplikacji, z której został wysłany + setting_skin: Zmienia wygląd używanej odmiany Mastodona + setting_use_blurhash: Gradienty są oparte na kolorach ukrywanej zawartości, ale uniewidaczniają wszystkie szczegóły username: Twoja nazwa użytkownika będzie niepowtarzalna na %{domain} whole_word: Jeśli słowo lub fraza składa się jedynie z liter lub cyfr, filtr będzie zastosowany tylko do pełnych wystąpień featured_tag: @@@ -108,9 -107,10 +109,10 @@@ setting_noindex: Nie indeksuj mojego profilu w wyszukiwarkach internetowych setting_reduce_motion: Ogranicz ruch w animacjach setting_show_application: Informuj o aplikacji z której wysłano wpisy + setting_skin: Motyw setting_system_font_ui: Używaj domyślnej czcionki systemu - setting_theme: Motyw strony setting_unfollow_modal: Pytaj o potwierdzenie przed cofnięciem śledzenia + setting_use_blurhash: Pokazuj kolorowe gradienty dla ukrytej zawartości multimedialnej severity: Priorytet type: Importowane dane username: Nazwa użytkownika diff --cc config/routes.rb index 1b88fe5e3,27b536641..66be635a5 --- a/config/routes.rb +++ b/config/routes.rb @@@ -324,16 -302,10 +308,15 @@@ Rails.application.routes.draw d get '/search', to: 'search#index', as: :search - resources :follows, only: [:create] resources :media, only: [:create, :update] resources :blocks, only: [:index] - resources :mutes, only: [:index] + resources :mutes, only: [:index] do + collection do + get 'details' + end + end resources :favourites, only: [:index] + resources :bookmarks, only: [:index] resources :reports, only: [:create] resources :filters, only: [:index, :create, :show, :update, :destroy] resources :endorsements, only: [:index] diff --cc config/settings.yml index bc97f650b,ad2970bb7..328a25a5a --- a/config/settings.yml +++ b/config/settings.yml @@@ -65,9 -61,7 +65,10 @@@ defaults: &default activity_api_enabled: true peers_api_enabled: true show_known_fediverse_at_about_page: true + show_reblogs_in_public_timelines: false + show_replies_in_public_timelines: false + default_content_type: 'text/plain' + spam_check_enabled: true development: <<: *defaults diff --cc spec/lib/sanitize_config_spec.rb index c5143bcef,54bd8693c..faefac803 --- a/spec/lib/sanitize_config_spec.rb +++ b/spec/lib/sanitize_config_spec.rb @@@ -7,12 -7,24 +7,16 @@@ describe Sanitize::Config d describe '::MASTODON_STRICT' do subject { Sanitize::Config::MASTODON_STRICT } - it 'converts h1 to p' do - expect(Sanitize.fragment('

Foo

', subject)).to eq '

Foo

' + it 'keeps h1' do + expect(Sanitize.fragment('

Foo

', subject)).to eq '

Foo

' end - it 'converts ul to p' do - expect(Sanitize.fragment('

Check out:

', subject)).to eq '

Check out:

Foo
Bar

' - end - - it 'converts p inside ul' do - expect(Sanitize.fragment('', subject)).to eq '

Foo
Bar
Baz

' - end - - it 'converts ul inside ul' do - expect(Sanitize.fragment('', subject)).to eq '

Foo
Bar
Baz

' + it 'keeps ul' do + expect(Sanitize.fragment('

Check out:

', subject)).to eq '

Check out:

' end + + it 'keep links in lists' do + expect(Sanitize.fragment('

Check out:

', subject)).to eq '

Check out:

joinmastodon.org
Bar

' + end end end