diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 82d9e8380f..efee54cb7b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -18,6 +18,8 @@ class ApplicationController < ActionController::Base helper_method :current_account helper_method :current_session helper_method :current_theme + helper_method :color_scheme + helper_method :contrast helper_method :single_user_mode? helper_method :use_seamless_external_login? helper_method :sso_account_settings @@ -177,6 +179,25 @@ class ApplicationController < ActionController::Base current_user.setting_theme end + def color_scheme + current = current_user&.setting_color_scheme + return current if current && current != 'auto' + + return 'dark' if current_theme.include?('default') || current_theme.include?('contrast') + return 'light' if current_theme.include?('light') + + 'auto' + end + + def contrast + current = current_user&.setting_contrast + return current if current && current != 'auto' + + return 'high' if current_theme.include?('contrast') + + 'auto' + end + def respond_with_error(code) respond_to do |format| format.any { render "errors/#{code}", layout: 'error', status: code, formats: [:html] } diff --git a/app/javascript/styles/mastodon/forms.scss b/app/javascript/styles/mastodon/forms.scss index 9f716c2126..88103ebc87 100644 --- a/app/javascript/styles/mastodon/forms.scss +++ b/app/javascript/styles/mastodon/forms.scss @@ -716,6 +716,17 @@ code { } } + .horizontal-options .label_input__wrapper { + display: flex; + flex-wrap: wrap; + gap: 20px; + + .radio, + .radio > label { + margin-bottom: 0; + } + } + .status-card { contain: unset; } diff --git a/app/models/concerns/user/has_settings.rb b/app/models/concerns/user/has_settings.rb index d917732d8a..f46a2ac53d 100644 --- a/app/models/concerns/user/has_settings.rb +++ b/app/models/concerns/user/has_settings.rb @@ -59,6 +59,14 @@ module User::HasSettings settings['theme'] end + def setting_color_scheme + settings['web.color_scheme'] + end + + def setting_contrast + settings['web.contrast'] + end + def setting_display_media settings['web.display_media'] end diff --git a/app/models/user_settings.rb b/app/models/user_settings.rb index d6cc23e732..c5f02ae2e9 100644 --- a/app/models/user_settings.rb +++ b/app/models/user_settings.rb @@ -37,6 +37,8 @@ class UserSettings setting :display_media, default: 'default', in: %w(default show_all hide_all) setting :auto_play, default: false setting :emoji_style, default: 'auto', in: %w(auto native twemoji) + setting :color_scheme, default: 'auto', in: %w(auto light dark) + setting :contrast, default: 'auto', in: %w(auto high) end namespace :notification_emails do diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 0bfa9e74f9..47e602f0f3 100755 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,5 +1,5 @@ !!! 5 -%html{ lang: I18n.locale, class: html_classes, 'data-user-theme': current_theme.parameterize } +%html{ lang: I18n.locale, class: html_classes, 'data-user-theme': current_theme.parameterize, 'data-contrast': contrast.parameterize, 'data-mode': color_scheme.parameterize } %head %meta{ charset: 'utf-8' }/ %meta{ name: 'viewport', content: 'width=device-width, initial-scale=1, viewport-fit=cover' }/ diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index 911a544ddb..ec1c799a3a 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -31,6 +31,25 @@ label: I18n.t('simple_form.labels.defaults.setting_theme'), wrapper: :with_label, required: false + - if Mastodon::Feature.new_theme_options_enabled? + .input.horizontal-options + = ff.input :'web.color_scheme', + as: :radio_buttons, + collection: %w(auto light dark), + include_blank: false, + label: I18n.t('simple_form.labels.defaults.setting_color_scheme'), + label_method: ->(contrast) { I18n.t("color_scheme.#{contrast}", default: contrast) }, + wrapper: :with_label, + required: false + .input.horizontal-options + = ff.input :'web.contrast', + as: :radio_buttons, + collection: %w(auto high), + include_blank: false, + label: I18n.t('simple_form.labels.defaults.setting_contrast'), + label_method: ->(contrast) { I18n.t("contrast.#{contrast}", default: contrast) }, + wrapper: :with_label, + required: false .fields-group = f.simple_fields_for :settings, current_user.settings do |ff| diff --git a/config/locales/en.yml b/config/locales/en.yml index 84a556292f..37c0709038 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1319,6 +1319,13 @@ en: hint_html: "Tip: We won't ask you for your password again for the next hour." invalid_password: Invalid password prompt: Confirm password to continue + color_scheme: + auto: Auto + dark: Dark + light: Light + contrast: + auto: Auto + high: High crypto: errors: invalid_key: is not a valid Ed25519 or Curve25519 key diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index 7455078203..e4e6d50ead 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -239,6 +239,8 @@ en: setting_always_send_emails: Always send e-mail notifications setting_auto_play_gif: Auto-play animated GIFs setting_boost_modal: Control boosting visibility + setting_color_scheme: Mode + setting_contrast: Contrast setting_default_language: Posting language setting_default_privacy: Posting visibility setting_default_quote_policy: Who can quote