diff --git a/app/controllers/settings/preferences_controller.rb b/app/controllers/settings/preferences_controller.rb index b475c722d..ab74ad9f2 100644 --- a/app/controllers/settings/preferences_controller.rb +++ b/app/controllers/settings/preferences_controller.rb @@ -41,6 +41,7 @@ class Settings::PreferencesController < ApplicationController :setting_delete_modal, :setting_auto_play_gif, :setting_display_sensitive_media, + :setting_expand_spoilers, :setting_reduce_motion, :setting_system_font_ui, :setting_noindex, diff --git a/app/javascript/mastodon/actions/importer/normalizer.js b/app/javascript/mastodon/actions/importer/normalizer.js index 10a39e050..a2af3222e 100644 --- a/app/javascript/mastodon/actions/importer/normalizer.js +++ b/app/javascript/mastodon/actions/importer/normalizer.js @@ -1,6 +1,7 @@ import escapeTextContentForBrowser from 'escape-html'; import emojify from '../../features/emoji/emoji'; import { unescapeHTML } from '../../utils/html'; +import { expandSpoilers } from '../../initial_state'; const domParser = new DOMParser(); @@ -57,7 +58,7 @@ export function normalizeStatus(status, normalOldStatus) { normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent; normalStatus.contentHtml = emojify(normalStatus.content, emojiMap); normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap); - normalStatus.hidden = spoilerText.length > 0 || normalStatus.sensitive; + normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive; } return normalStatus; diff --git a/app/javascript/mastodon/initial_state.js b/app/javascript/mastodon/initial_state.js index 6ffb4cbfb..e615de09c 100644 --- a/app/javascript/mastodon/initial_state.js +++ b/app/javascript/mastodon/initial_state.js @@ -6,6 +6,7 @@ const getMeta = (prop) => initialState && initialState.meta && initialState.meta export const reduceMotion = getMeta('reduce_motion'); export const autoPlayGif = getMeta('auto_play_gif'); export const displaySensitiveMedia = getMeta('display_sensitive_media'); +export const expandSpoilers = getMeta('expand_spoilers'); export const unfollowModal = getMeta('unfollow_modal'); export const boostModal = getMeta('boost_modal'); export const deleteModal = getMeta('delete_modal'); diff --git a/app/lib/user_settings_decorator.rb b/app/lib/user_settings_decorator.rb index 833959397..7239dc194 100644 --- a/app/lib/user_settings_decorator.rb +++ b/app/lib/user_settings_decorator.rb @@ -25,6 +25,7 @@ class UserSettingsDecorator user.settings['delete_modal'] = delete_modal_preference if change?('setting_delete_modal') user.settings['auto_play_gif'] = auto_play_gif_preference if change?('setting_auto_play_gif') user.settings['display_sensitive_media'] = display_sensitive_media_preference if change?('setting_display_sensitive_media') + user.settings['expand_spoilers'] = expand_spoilers_preference if change?('setting_expand_spoilers') user.settings['reduce_motion'] = reduce_motion_preference if change?('setting_reduce_motion') user.settings['system_font_ui'] = system_font_ui_preference if change?('setting_system_font_ui') user.settings['noindex'] = noindex_preference if change?('setting_noindex') @@ -72,6 +73,10 @@ class UserSettingsDecorator boolean_cast_setting 'setting_display_sensitive_media' end + def expand_spoilers_preference + boolean_cast_setting 'setting_expand_spoilers' + end + def reduce_motion_preference boolean_cast_setting 'setting_reduce_motion' end diff --git a/app/models/user.rb b/app/models/user.rb index d83df28c2..541b5a638 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -96,7 +96,7 @@ class User < ApplicationRecord delegate :auto_play_gif, :default_sensitive, :unfollow_modal, :boost_modal, :delete_modal, :reduce_motion, :system_font_ui, :noindex, :theme, :display_sensitive_media, :hide_network, - :default_language, to: :settings, prefix: :setting, allow_nil: false + :expand_spoilers, :default_language, to: :settings, prefix: :setting, allow_nil: false attr_reader :invite_code diff --git a/app/serializers/initial_state_serializer.rb b/app/serializers/initial_state_serializer.rb index 78b96298c..35b869e38 100644 --- a/app/serializers/initial_state_serializer.rb +++ b/app/serializers/initial_state_serializer.rb @@ -25,6 +25,7 @@ class InitialStateSerializer < ActiveModel::Serializer store[:delete_modal] = object.current_account.user.setting_delete_modal store[:auto_play_gif] = object.current_account.user.setting_auto_play_gif store[:display_sensitive_media] = object.current_account.user.setting_display_sensitive_media + store[:expand_spoilers] = object.current_account.user.setting_expand_spoilers store[:reduce_motion] = object.current_account.user.setting_reduce_motion end diff --git a/app/views/settings/preferences/show.html.haml b/app/views/settings/preferences/show.html.haml index c79ecf6d5..a7b1a52fc 100644 --- a/app/views/settings/preferences/show.html.haml +++ b/app/views/settings/preferences/show.html.haml @@ -48,6 +48,7 @@ .fields-group = f.input :setting_auto_play_gif, as: :boolean, wrapper: :with_label = f.input :setting_display_sensitive_media, as: :boolean, wrapper: :with_label + = f.input :setting_expand_spoilers, as: :boolean, wrapper: :with_label = f.input :setting_reduce_motion, as: :boolean, wrapper: :with_label = f.input :setting_system_font_ui, as: :boolean, wrapper: :with_label diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index d0d9cc5fc..77346dba7 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -16,10 +16,10 @@ .status__content.emojify< - if status.spoiler_text? - %p{ style: 'margin-bottom: 0' }< + %p{ :style => ('margin-bottom: 0' unless current_account&.user&.setting_expand_spoilers) }< %span.p-summary> #{Formatter.instance.format_spoiler(status, autoplay: autoplay)}  %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') - .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) + .e-content{ lang: status.language, 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.media_attachments.empty? - if status.media_attachments.first.video? diff --git a/app/views/stream_entries/_simple_status.html.haml b/app/views/stream_entries/_simple_status.html.haml index fc2cacf30..206cf0aec 100644 --- a/app/views/stream_entries/_simple_status.html.haml +++ b/app/views/stream_entries/_simple_status.html.haml @@ -19,10 +19,10 @@ = fa_icon('lock') if status.account.locked? .status__content.emojify< - if status.spoiler_text? - %p{ style: 'margin-bottom: 0' }< + %p{ :style => ('margin-bottom: 0' unless current_account&.user&.setting_expand_spoilers) }< %span.p-summary> #{Formatter.instance.format_spoiler(status, autoplay: autoplay)}  %a.status__content__spoiler-link{ href: '#' }= t('statuses.show_more') - .e-content{ lang: status.language, style: "display: #{status.spoiler_text? ? 'none' : 'block'}; direction: #{rtl_status?(status) ? 'rtl' : 'ltr'}" }= Formatter.instance.format(status, custom_emojify: true, autoplay: autoplay) + .e-content{ lang: status.language, 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) - unless status.media_attachments.empty? - if status.media_attachments.first.video? diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index c2e572997..5b1a07a4a 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -73,6 +73,7 @@ en: setting_default_sensitive: Always mark media as sensitive setting_delete_modal: Show confirmation dialog before deleting a toot setting_display_sensitive_media: Always show media marked as sensitive + setting_expand_spoilers: Always expand toots marked with content warnings setting_hide_network: Hide your network setting_noindex: Opt-out of search engine indexing setting_reduce_motion: Reduce motion in animations diff --git a/config/settings.yml b/config/settings.yml index 78a801406..e2214b4b7 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -27,6 +27,7 @@ defaults: &defaults delete_modal: true auto_play_gif: false display_sensitive_media: false + expand_spoilers: false preview_sensitive_media: false reduce_motion: false system_font_ui: false