Project

General

Profile

Feature #33056 » 0003-Add-a-color-scheme-preference-to-choose-between-ligh.patch

Florian Walchshofer, 2026-10-18 21:17

View differences:

app/helpers/application_helper.rb
929 929
    end
930 930
  end
931 931

  
932
  # Returns the tags that enable the dark color scheme of the default theme
933
  # according to the color scheme preference of the current user
934
  def color_scheme_tags
935
    return if current_theme
936

  
937
    case User.current.pref.color_scheme
938
    when 'light'
939
      tag.meta(name: 'color-scheme', content: 'light')
940
    when 'dark'
941
      tag.meta(name: 'color-scheme', content: 'dark') +
942
        stylesheet_link_tag('dark', media: 'screen')
943
    else
944
      tag.meta(name: 'color-scheme', content: 'light dark') +
945
        stylesheet_link_tag('dark', media: 'screen and (prefers-color-scheme: dark)')
946
    end
947
  end
948

  
932 949
  # Returns the theme, controller name, and action as css classes for the
933 950
  # HTML body.
934 951
  def body_css_classes
app/helpers/users_helper.rb
52 52
    [[l(:label_font_default), '']] + UserPreference::TEXTAREA_FONT_OPTIONS.map {|o| [l("label_font_#{o}"), o]}
53 53
  end
54 54

  
55
  def color_scheme_options
56
    [[l(:label_color_scheme_system), '']] + UserPreference::COLOR_SCHEME_OPTIONS.map {|o| [l("label_color_scheme_#{o}"), o]}
57
  end
58

  
55 59
  def history_default_tab_options
56 60
    [[l('label_issue_history_notes'), 'notes'],
57 61
     [l('label_history'), 'history'],
app/models/user_preference.rb
35 35
    'no_self_notified',
36 36
    'notify_about_high_priority_issues',
37 37
    'textarea_font',
38
    'color_scheme',
38 39
    'recently_used_projects',
39 40
    'history_default_tab',
40 41
    'default_issue_query',
......
43 44
    'auto_watch_on')
44 45

  
45 46
  TEXTAREA_FONT_OPTIONS = ['monospace', 'proportional']
47
  COLOR_SCHEME_OPTIONS = ['light', 'dark']
46 48
  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]
47 49
  AUTO_WATCH_ON_OPTIONS = %w[issue_created issue_contributed_to issue_assigned_to_me]
48 50

  
......
107 109
  def textarea_font; self[:textarea_font]; end
108 110
  def textarea_font=(value); self[:textarea_font]=value; end
109 111

  
112
  def color_scheme; self[:color_scheme]; end
113
  def color_scheme=(value); self[:color_scheme]=value; end
114

  
110 115
  def recently_used_projects; (self[:recently_used_projects] || 3).to_i; end
111 116
  def recently_used_projects=(value); self[:recently_used_projects] = value.to_i; end
112 117
  def history_default_tab; self[:history_default_tab]; end
app/views/layouts/base.html.erb
9 9
<%= csrf_meta_tag %>
10 10
<%= favicon %>
11 11
<%= stylesheet_link_tag 'jquery/jquery-ui-1.13.2', 'tribute-5.1.3', 'application', 'dropdown', 'responsive', :media => 'all' %>
12
<% unless current_theme %>
13
<meta name="color-scheme" content="light dark" />
14
<%= stylesheet_link_tag 'dark', :media => 'screen and (prefers-color-scheme: dark)' %>
15
<% end %>
12
<%= color_scheme_tags %>
16 13
<%= javascript_importmap_tags %>
17 14
<%= javascript_heads %>
18 15
<%= heads_for_theme %>
app/views/users/_preferences.html.erb
4 4
<p><%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %></p>
5 5
<p><%= pref_fields.check_box :warn_on_leaving_unsaved %></p>
6 6
<p><%= pref_fields.select :textarea_font, textarea_font_options %></p>
7
<% unless current_theme %>
8
<p><%= pref_fields.select :color_scheme, color_scheme_options %></p>
9
<% end %>
7 10
<p><%= pref_fields.text_field :recently_used_projects, :size => 2 %></p>
8 11
<p><%= pref_fields.select :history_default_tab, history_default_tab_options %></p>
9 12
<p><%= pref_fields.textarea :toolbar_language_options, :rows => 4 %></p>
config/locales/en.yml
1499 1499
  reaction_text_x_other_users:
1500 1500
    one: "1 other"
1501 1501
    other: "%{count} others"
1502
  field_color_scheme: Color scheme
1503
  label_color_scheme_system: Use system setting
1504
  label_color_scheme_light: Light
1505
  label_color_scheme_dark: Dark
test/functional/my_controller_test.rb
535 535
    assert mail.to.include?('foobar@example.com')
536 536
  end
537 537

  
538
  def test_my_account_color_scheme_preference
539
    get :account
540
    assert_select 'select[name=?]', 'pref[color_scheme]' do
541
      assert_select 'option', 3
542
      assert_select 'option[value=""][selected=selected]'
543
    end
544

  
545
    put :account, :params => {:pref => {:color_scheme => 'dark'}}
546
    assert_equal 'dark', User.find(2).pref.color_scheme
547
  end
548

  
549
  def test_my_account_should_not_show_color_scheme_preference_with_theme
550
    with_settings :ui_theme => 'classic' do
551
      get :account
552
      assert_select 'select[name=?]', 'pref[color_scheme]', 0
553
    end
554
  end
555

  
538 556
  def test_my_account_notify_about_high_priority_issues_preference
539 557
    # normally, preference should be shown
540 558
    get :account
test/functional/users_controller_test.rb
519 519
          'comments_sorting' => 'desc',
520 520
          'warn_on_leaving_unsaved' => '0',
521 521
          'textarea_font' => 'proportional',
522
          'color_scheme' => 'dark',
522 523
          'history_default_tab' => 'history'
523 524
        }
524 525
      }
......
530 531
    assert_equal 'desc', user.pref[:comments_sorting]
531 532
    assert_equal '0', user.pref[:warn_on_leaving_unsaved]
532 533
    assert_equal 'proportional', user.pref[:textarea_font]
534
    assert_equal 'dark', user.pref.color_scheme
533 535
    assert_equal 'history', user.pref[:history_default_tab]
534 536
  end
535 537

  
test/functional/welcome_controller_test.rb
115 115
    assert_select 'body.textarea-proportional'
116 116
  end
117 117

  
118
  def test_color_scheme_should_follow_system_setting_by_default
119
    @request.session[:user_id] = 1
120
    get :index
121
    assert_select 'meta[name=color-scheme][content=?]', 'light dark'
122
    assert_select "link[rel=stylesheet][media=?]:match('href', ?)",
123
                  'screen and (prefers-color-scheme: dark)', %r{/dark(-\w+)?\.css}
124
  end
125

  
126
  def test_color_scheme_set_to_dark
127
    user = User.find(1)
128
    user.pref.color_scheme = 'dark'
129
    user.pref.save!
130
    @request.session[:user_id] = 1
131
    get :index
132
    assert_select 'meta[name=color-scheme][content=?]', 'dark'
133
    assert_select "link[rel=stylesheet][media=screen]:match('href', ?)", %r{/dark(-\w+)?\.css}
134
  end
135

  
136
  def test_color_scheme_set_to_light
137
    user = User.find(1)
138
    user.pref.color_scheme = 'light'
139
    user.pref.save!
140
    @request.session[:user_id] = 1
141
    get :index
142
    assert_select 'meta[name=color-scheme][content=?]', 'light'
143
    assert_select "link[rel=stylesheet]:match('href', ?)", %r{/dark(-\w+)?\.css}, 0
144
  end
145

  
118 146
  def test_data_text_setting_attribute
119 147
    formats = %w(textile common_mark)
120 148
    formats.each do |format|
(10-10/11)