diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f906d0ddf..ca428e464 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -929,6 +929,23 @@ module ApplicationHelper end end + # Returns the tags that enable the dark color scheme of the default theme + # according to the color scheme preference of the current user + def color_scheme_tags + return if current_theme + + case User.current.pref.color_scheme + when 'light' + tag.meta(name: 'color-scheme', content: 'light') + when 'dark' + tag.meta(name: 'color-scheme', content: 'dark') + + stylesheet_link_tag('dark', media: 'screen') + else + tag.meta(name: 'color-scheme', content: 'light dark') + + stylesheet_link_tag('dark', media: 'screen and (prefers-color-scheme: dark)') + end + end + # Returns the theme, controller name, and action as css classes for the # HTML body. def body_css_classes diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 0da236e38..86d1772ae 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -52,6 +52,10 @@ module UsersHelper [[l(:label_font_default), '']] + UserPreference::TEXTAREA_FONT_OPTIONS.map {|o| [l("label_font_#{o}"), o]} end + def color_scheme_options + [[l(:label_color_scheme_system), '']] + UserPreference::COLOR_SCHEME_OPTIONS.map {|o| [l("label_color_scheme_#{o}"), o]} + end + def history_default_tab_options [[l('label_issue_history_notes'), 'notes'], [l('label_history'), 'history'], diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb index 67937e201..e55d66757 100644 --- a/app/models/user_preference.rb +++ b/app/models/user_preference.rb @@ -35,6 +35,7 @@ class UserPreference < ApplicationRecord 'no_self_notified', 'notify_about_high_priority_issues', 'textarea_font', + 'color_scheme', 'recently_used_projects', 'history_default_tab', 'default_issue_query', @@ -43,6 +44,7 @@ class UserPreference < ApplicationRecord 'auto_watch_on') TEXTAREA_FONT_OPTIONS = ['monospace', 'proportional'] + COLOR_SCHEME_OPTIONS = ['light', 'dark'] DEFAULT_TOOLBAR_LANGUAGE_OPTIONS = %w[c cpp csharp css diff go groovy html java javascript objc perl php python r ruby sass scala shell sql swift xml yaml] AUTO_WATCH_ON_OPTIONS = %w[issue_created issue_contributed_to issue_assigned_to_me] @@ -107,6 +109,9 @@ class UserPreference < ApplicationRecord def textarea_font; self[:textarea_font]; end def textarea_font=(value); self[:textarea_font]=value; end + def color_scheme; self[:color_scheme]; end + def color_scheme=(value); self[:color_scheme]=value; end + def recently_used_projects; (self[:recently_used_projects] || 3).to_i; end def recently_used_projects=(value); self[:recently_used_projects] = value.to_i; end def history_default_tab; self[:history_default_tab]; end diff --git a/app/views/layouts/base.html.erb b/app/views/layouts/base.html.erb index af0cd4e08..883d4b6d4 100644 --- a/app/views/layouts/base.html.erb +++ b/app/views/layouts/base.html.erb @@ -9,10 +9,7 @@ <%= csrf_meta_tag %> <%= favicon %> <%= stylesheet_link_tag 'jquery/jquery-ui-1.13.2', 'tribute-5.1.3', 'application', 'dropdown', 'responsive', :media => 'all' %> -<% unless current_theme %> - -<%= stylesheet_link_tag 'dark', :media => 'screen and (prefers-color-scheme: dark)' %> -<% end %> +<%= color_scheme_tags %> <%= javascript_importmap_tags %> <%= javascript_heads %> <%= heads_for_theme %> diff --git a/app/views/users/_preferences.html.erb b/app/views/users/_preferences.html.erb index e961ee0db..d15a62298 100644 --- a/app/views/users/_preferences.html.erb +++ b/app/views/users/_preferences.html.erb @@ -4,6 +4,9 @@
<%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %>
<%= pref_fields.check_box :warn_on_leaving_unsaved %>
<%= pref_fields.select :textarea_font, textarea_font_options %>
+<% unless current_theme %> +<%= pref_fields.select :color_scheme, color_scheme_options %>
+<% end %><%= pref_fields.text_field :recently_used_projects, :size => 2 %>
<%= pref_fields.select :history_default_tab, history_default_tab_options %>
<%= pref_fields.textarea :toolbar_language_options, :rows => 4 %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 279539b88..2d277177b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1499,3 +1499,7 @@ en: reaction_text_x_other_users: one: "1 other" other: "%{count} others" + field_color_scheme: Color scheme + label_color_scheme_system: Use system setting + label_color_scheme_light: Light + label_color_scheme_dark: Dark diff --git a/test/functional/my_controller_test.rb b/test/functional/my_controller_test.rb index 92fbb9643..6e05c0781 100644 --- a/test/functional/my_controller_test.rb +++ b/test/functional/my_controller_test.rb @@ -535,6 +535,24 @@ class MyControllerTest < Redmine::ControllerTest assert mail.to.include?('foobar@example.com') end + def test_my_account_color_scheme_preference + get :account + assert_select 'select[name=?]', 'pref[color_scheme]' do + assert_select 'option', 3 + assert_select 'option[value=""][selected=selected]' + end + + put :account, :params => {:pref => {:color_scheme => 'dark'}} + assert_equal 'dark', User.find(2).pref.color_scheme + end + + def test_my_account_should_not_show_color_scheme_preference_with_theme + with_settings :ui_theme => 'classic' do + get :account + assert_select 'select[name=?]', 'pref[color_scheme]', 0 + end + end + def test_my_account_notify_about_high_priority_issues_preference # normally, preference should be shown get :account diff --git a/test/functional/users_controller_test.rb b/test/functional/users_controller_test.rb index 6ec7f2bb5..fc236dee3 100644 --- a/test/functional/users_controller_test.rb +++ b/test/functional/users_controller_test.rb @@ -519,6 +519,7 @@ class UsersControllerTest < Redmine::ControllerTest 'comments_sorting' => 'desc', 'warn_on_leaving_unsaved' => '0', 'textarea_font' => 'proportional', + 'color_scheme' => 'dark', 'history_default_tab' => 'history' } } @@ -530,6 +531,7 @@ class UsersControllerTest < Redmine::ControllerTest assert_equal 'desc', user.pref[:comments_sorting] assert_equal '0', user.pref[:warn_on_leaving_unsaved] assert_equal 'proportional', user.pref[:textarea_font] + assert_equal 'dark', user.pref.color_scheme assert_equal 'history', user.pref[:history_default_tab] end diff --git a/test/functional/welcome_controller_test.rb b/test/functional/welcome_controller_test.rb index ba1a30235..e17d0f876 100644 --- a/test/functional/welcome_controller_test.rb +++ b/test/functional/welcome_controller_test.rb @@ -115,6 +115,34 @@ class WelcomeControllerTest < Redmine::ControllerTest assert_select 'body.textarea-proportional' end + def test_color_scheme_should_follow_system_setting_by_default + @request.session[:user_id] = 1 + get :index + assert_select 'meta[name=color-scheme][content=?]', 'light dark' + assert_select "link[rel=stylesheet][media=?]:match('href', ?)", + 'screen and (prefers-color-scheme: dark)', %r{/dark(-\w+)?\.css} + end + + def test_color_scheme_set_to_dark + user = User.find(1) + user.pref.color_scheme = 'dark' + user.pref.save! + @request.session[:user_id] = 1 + get :index + assert_select 'meta[name=color-scheme][content=?]', 'dark' + assert_select "link[rel=stylesheet][media=screen]:match('href', ?)", %r{/dark(-\w+)?\.css} + end + + def test_color_scheme_set_to_light + user = User.find(1) + user.pref.color_scheme = 'light' + user.pref.save! + @request.session[:user_id] = 1 + get :index + assert_select 'meta[name=color-scheme][content=?]', 'light' + assert_select "link[rel=stylesheet]:match('href', ?)", %r{/dark(-\w+)?\.css}, 0 + end + def test_data_text_setting_attribute formats = %w(textile common_mark) formats.each do |format| -- 2.43.0