mirror of
https://github.com/mastodon/mastodon.git
synced 2026-03-21 18:05:23 -05:00
Migrate to new theming infrastructure (#37612)
This commit is contained in:
parent
fb89198460
commit
75ba314e6b
|
|
@ -21,9 +21,7 @@ import { reducerWithInitialState } from '@/mastodon/reducers';
|
|||
import { defaultMiddleware } from '@/mastodon/store/store';
|
||||
import { mockHandlers, unhandledRequestHandler } from '@/testing/api';
|
||||
|
||||
// If you want to run the dark theme during development,
|
||||
// you can change the below to `/application.scss`
|
||||
import '../app/javascript/styles/mastodon-light.scss';
|
||||
import '../app/javascript/styles/application.scss';
|
||||
import './styles.css';
|
||||
import { modes } from './modes';
|
||||
|
||||
|
|
|
|||
|
|
@ -180,22 +180,11 @@ class ApplicationController < ActionController::Base
|
|||
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'
|
||||
current_user&.setting_color_scheme || 'auto'
|
||||
end
|
||||
|
||||
def contrast
|
||||
current = current_user&.setting_contrast
|
||||
return current if current && current != 'auto'
|
||||
|
||||
return 'high' if current_theme.include?('contrast')
|
||||
|
||||
'auto'
|
||||
current_user&.setting_contrast || 'auto'
|
||||
end
|
||||
|
||||
def respond_with_error(code)
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@ module ThemeHelper
|
|||
end
|
||||
|
||||
def theme_style_tags(theme)
|
||||
# TODO: get rid of that when we retire the themes and perform the settings migration
|
||||
theme = 'default' if %w(mastodon-light contrast system).include?(theme)
|
||||
|
||||
vite_stylesheet_tag "themes/#{theme}", type: :virtual, media: 'all', crossorigin: 'anonymous'
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
@use 'common';
|
||||
|
|
@ -1 +0,0 @@
|
|||
@use 'common';
|
||||
|
|
@ -16,6 +16,6 @@ class Themes
|
|||
end
|
||||
|
||||
def names
|
||||
['system'] + @conf.keys
|
||||
@conf.keys
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
= vite_client_tag
|
||||
= vite_react_refresh_tag
|
||||
= vite_polyfills_tag
|
||||
= theme_style_tags 'system'
|
||||
= theme_style_tags 'default'
|
||||
= vite_preload_file_tag "mastodon/locales/#{I18n.locale}.json"
|
||||
= render_initial_state
|
||||
= vite_typescript_tag 'embed.tsx', integrity: true, crossorigin: 'anonymous'
|
||||
|
|
|
|||
|
|
@ -23,33 +23,34 @@
|
|||
|
||||
.fields-group
|
||||
= f.simple_fields_for :settings, current_user.settings do |ff|
|
||||
= ff.input :theme,
|
||||
collection: Themes.instance.names,
|
||||
hint: false,
|
||||
include_blank: false,
|
||||
label_method: ->(theme) { I18n.t("themes.#{theme}", default: theme) },
|
||||
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
|
||||
- if Themes.instance.names.size > 1
|
||||
= ff.input :theme,
|
||||
collection: Themes.instance.names,
|
||||
hint: false,
|
||||
include_blank: false,
|
||||
label_method: ->(theme) { I18n.t("themes.#{theme}", default: theme) },
|
||||
label: I18n.t('simple_form.labels.defaults.setting_theme'),
|
||||
wrapper: :with_label,
|
||||
required: false
|
||||
|
||||
.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|
|
||||
|
|
|
|||
|
|
@ -2022,10 +2022,7 @@ en:
|
|||
review_link: Review terms of service
|
||||
title: The terms of service of %{domain} are changing
|
||||
themes:
|
||||
contrast: Mastodon (High contrast)
|
||||
default: Mastodon (Dark)
|
||||
mastodon-light: Mastodon (Light)
|
||||
system: Automatic (use system theme)
|
||||
default: Mastodon
|
||||
time:
|
||||
formats:
|
||||
default: "%b %d, %Y, %H:%M"
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ defaults: &defaults
|
|||
show_staff_badge: true
|
||||
preview_sensitive_media: false
|
||||
noindex: false
|
||||
theme: 'system'
|
||||
theme: 'default'
|
||||
trends: true
|
||||
trendable_by_default: false
|
||||
disallowed_hashtags: # space separated string or list of hashtags without the hash
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
default: styles/application.scss
|
||||
contrast: styles/contrast.scss
|
||||
mastodon-light: styles/mastodon-light.scss
|
||||
|
|
|
|||
22
db/migrate/20260209142402_migrate_default_theme_setting.rb
Normal file
22
db/migrate/20260209142402_migrate_default_theme_setting.rb
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class MigrateDefaultThemeSetting < ActiveRecord::Migration[8.0]
|
||||
class Setting < ApplicationRecord; end
|
||||
|
||||
def up
|
||||
Setting.reset_column_information
|
||||
|
||||
setting = Setting.find_by(var: 'theme')
|
||||
return unless setting.present? && setting.attributes['value'].present? && %w(mastodon-light contrast system).include?(setting.attributes['value'])
|
||||
|
||||
Setting.upsert(
|
||||
{
|
||||
var: 'theme',
|
||||
value: "--- default\n",
|
||||
},
|
||||
unique_by: index_exists?(:settings, [:thing_type, :thing_id, :var]) ? [:thing_type, :thing_id, :var] : :var
|
||||
)
|
||||
end
|
||||
|
||||
def down; end
|
||||
end
|
||||
31
db/migrate/20260209143308_migrate_user_theme.rb
Normal file
31
db/migrate/20260209143308_migrate_user_theme.rb
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class MigrateUserTheme < ActiveRecord::Migration[8.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
# Dummy classes, to make migration possible across version changes
|
||||
class User < ApplicationRecord; end
|
||||
|
||||
def up
|
||||
User.where.not(settings: nil).find_each do |user|
|
||||
settings = Oj.load(user.attributes_before_type_cast['settings'])
|
||||
next if settings.nil? || settings['theme'].blank? || %w(system default mastodon-light contrast).exclude?(settings['theme'])
|
||||
|
||||
case settings['theme']
|
||||
when 'default'
|
||||
settings['web.color_scheme'] = 'dark'
|
||||
settings['web.contrast'] = 'auto'
|
||||
when 'contrast'
|
||||
settings['web.color_scheme'] = 'dark'
|
||||
settings['web.contrast'] = 'high'
|
||||
when 'mastodon-light'
|
||||
settings['web.color_scheme'] = 'light'
|
||||
settings['web.contrast'] = 'auto'
|
||||
end
|
||||
|
||||
settings['theme'] = 'default'
|
||||
|
||||
user.update_column('settings', Oj.dump(settings))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.0].define(version: 2026_01_27_141820) do
|
||||
ActiveRecord::Schema[8.0].define(version: 2026_02_09_143308) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_catalog.plpgsql"
|
||||
|
||||
|
|
@ -1127,6 +1127,7 @@ ActiveRecord::Schema[8.0].define(version: 2026_01_27_141820) do
|
|||
t.string "poll_options", array: true
|
||||
t.boolean "sensitive"
|
||||
t.bigint "quote_id"
|
||||
t.string "content_type"
|
||||
t.index ["account_id"], name: "index_status_edits_on_account_id"
|
||||
t.index ["status_id"], name: "index_status_edits_on_status_id"
|
||||
end
|
||||
|
|
@ -1189,6 +1190,8 @@ ActiveRecord::Schema[8.0].define(version: 2026_01_27_141820) do
|
|||
t.bigint "ordered_media_attachment_ids", array: true
|
||||
t.datetime "fetched_replies_at"
|
||||
t.integer "quote_approval_policy", default: 0, null: false
|
||||
t.boolean "local_only"
|
||||
t.string "content_type"
|
||||
t.index ["account_id", "id", "visibility", "updated_at"], name: "index_statuses_20190820", order: { id: :desc }, where: "(deleted_at IS NULL)"
|
||||
t.index ["account_id"], name: "index_statuses_on_account_id"
|
||||
t.index ["conversation_id"], name: "index_statuses_on_conversation_id"
|
||||
|
|
|
|||
|
|
@ -97,24 +97,6 @@ RSpec.describe ApplicationController do
|
|||
|
||||
expect(controller.view_context.current_theme).to eq 'contrast'
|
||||
end
|
||||
|
||||
it 'returns instances\'s default theme when user didn\'t set theme' do
|
||||
current_user = Fabricate(:user)
|
||||
current_user.settings.update(theme: 'contrast', noindex: false)
|
||||
current_user.save
|
||||
sign_in current_user
|
||||
|
||||
expect(controller.view_context.current_theme).to eq 'contrast'
|
||||
end
|
||||
|
||||
it 'returns user\'s theme when it is set' do
|
||||
current_user = Fabricate(:user)
|
||||
current_user.settings.update(theme: 'mastodon-light')
|
||||
current_user.save
|
||||
sign_in current_user
|
||||
|
||||
expect(controller.view_context.current_theme).to eq 'mastodon-light'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with ActionController::RoutingError' do
|
||||
|
|
|
|||
|
|
@ -6,17 +6,6 @@ RSpec.describe ThemeHelper do
|
|||
describe 'theme_style_tags' do
|
||||
let(:result) { helper.theme_style_tags(theme) }
|
||||
|
||||
context 'when using "system" theme' do
|
||||
let(:theme) { 'system' }
|
||||
|
||||
it 'returns the default theme' do
|
||||
expect(html_links.first.attributes.symbolize_keys)
|
||||
.to include(
|
||||
href: have_attributes(value: match(/default/))
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when using "default" theme' do
|
||||
let(:theme) { 'default' }
|
||||
|
||||
|
|
@ -27,17 +16,6 @@ RSpec.describe ThemeHelper do
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when using other theme' do
|
||||
let(:theme) { 'contrast' }
|
||||
|
||||
it 'returns the theme stylesheet without color scheme information' do
|
||||
expect(html_links.first.attributes.symbolize_keys)
|
||||
.to include(
|
||||
href: have_attributes(value: match(/default/))
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'theme_color_tags' do
|
||||
|
|
|
|||
|
|
@ -13,15 +13,13 @@ RSpec.describe 'Settings preferences appearance page' do
|
|||
expect(page)
|
||||
.to have_private_cache_control
|
||||
|
||||
select 'contrast', from: theme_selection_field
|
||||
check confirm_reblog_field
|
||||
uncheck confirm_delete_field
|
||||
|
||||
check advanced_layout_field
|
||||
|
||||
expect { save_changes }
|
||||
.to change { user.reload.settings.theme }.to('contrast')
|
||||
.and change { user.reload.settings['web.reblog_modal'] }.to(true)
|
||||
.to change { user.reload.settings['web.reblog_modal'] }.to(true)
|
||||
.and change { user.reload.settings['web.delete_modal'] }.to(false)
|
||||
.and(change { user.reload.settings['web.advanced_layout'] }.to(true))
|
||||
expect(page)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user