diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index c5e2d14b15..cabdfff493 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -505,11 +505,6 @@ body.small-nav { } @include color-mode(dark) { - .leaflet-tile-container .leaflet-tile, - .mapkey-table-entry td:first-child > * { - filter: brightness(.8); - } - .leaflet-container .leaflet-control-attribution a { color: var(--bs-link-color); } @@ -519,6 +514,23 @@ body.small-nav { } } +@mixin dark-map-color-scheme { + .leaflet-tile-container .leaflet-tile, + .mapkey-table-entry td:first-child > * { + filter: brightness(.8); + } +} + +body[data-map-theme="dark"] { + @include dark-map-color-scheme; +} + +@include color-mode(dark) { + body:not([data-map-theme]) { + @include dark-map-color-scheme; + } +} + /* Rules for attribution text under the main map shown on printouts */ .donate-attr { color: darken($green, 10%) !important; } diff --git a/app/assets/stylesheets/parameters.scss b/app/assets/stylesheets/parameters.scss index 28bf569016..07549d69bb 100644 --- a/app/assets/stylesheets/parameters.scss +++ b/app/assets/stylesheets/parameters.scss @@ -20,4 +20,3 @@ $table-border-factor: .1; $list-group-hover-bg: rgba(var(--bs-emphasis-color-rgb), .075); $enable-negative-margins: true; -$color-mode-type: media-query; diff --git a/app/assets/stylesheets/screen-auto-ltr.scss b/app/assets/stylesheets/screen-auto-ltr.scss new file mode 100644 index 0000000000..89e31599ae --- /dev/null +++ b/app/assets/stylesheets/screen-auto-ltr.scss @@ -0,0 +1,3 @@ +@use "common" with ( + $color-mode-type: media-query +); diff --git a/app/assets/stylesheets/screen-auto-rtl.rtlcss.scss b/app/assets/stylesheets/screen-auto-rtl.rtlcss.scss new file mode 100644 index 0000000000..89e31599ae --- /dev/null +++ b/app/assets/stylesheets/screen-auto-rtl.rtlcss.scss @@ -0,0 +1,3 @@ +@use "common" with ( + $color-mode-type: media-query +); diff --git a/app/assets/stylesheets/screen-ltr.scss b/app/assets/stylesheets/screen-ltr.scss deleted file mode 100644 index c525060af5..0000000000 --- a/app/assets/stylesheets/screen-ltr.scss +++ /dev/null @@ -1 +0,0 @@ -@import "common"; diff --git a/app/assets/stylesheets/screen-manual-ltr.scss b/app/assets/stylesheets/screen-manual-ltr.scss new file mode 100644 index 0000000000..00f65f79ac --- /dev/null +++ b/app/assets/stylesheets/screen-manual-ltr.scss @@ -0,0 +1,3 @@ +@use "common" with ( + $color-mode-type: data +); diff --git a/app/assets/stylesheets/screen-manual-rtl.rtlcss.scss b/app/assets/stylesheets/screen-manual-rtl.rtlcss.scss new file mode 100644 index 0000000000..00f65f79ac --- /dev/null +++ b/app/assets/stylesheets/screen-manual-rtl.rtlcss.scss @@ -0,0 +1,3 @@ +@use "common" with ( + $color-mode-type: data +); diff --git a/app/assets/stylesheets/screen-rtl.rtlcss.scss b/app/assets/stylesheets/screen-rtl.rtlcss.scss deleted file mode 100644 index c525060af5..0000000000 --- a/app/assets/stylesheets/screen-rtl.rtlcss.scss +++ /dev/null @@ -1 +0,0 @@ -@import "common"; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index bde7e02876..32b53bad71 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -279,7 +279,15 @@ def preferred_editor end end - helper_method :preferred_editor + def preferred_color_scheme(subject) + if current_user + current_user.preferences.find_by(:k => "#{subject}.color_scheme")&.v || "auto" + else + "auto" + end + end + + helper_method :preferred_editor, :preferred_color_scheme def update_totp if Settings.key?(:totp_key) diff --git a/app/controllers/preferences_controller.rb b/app/controllers/preferences_controller.rb index dcf0d8b64e..1d96766ef2 100644 --- a/app/controllers/preferences_controller.rb +++ b/app/controllers/preferences_controller.rb @@ -21,7 +21,20 @@ def update else params[:user][:preferred_editor] end - if current_user.save + + success = current_user.save + + if params[:site_color_scheme] + site_color_scheme_preference = current_user.preferences.find_or_create_by(:k => "site.color_scheme") + success &= site_color_scheme_preference.update(:v => params[:site_color_scheme]) + end + + if params[:map_color_scheme] + map_color_scheme_preference = current_user.preferences.find_or_create_by(:k => "map.color_scheme") + success &= map_color_scheme_preference.update(:v => params[:map_color_scheme]) + end + + if success # Use a partial so that it is rendered during the next page load in the correct language. flash[:notice] = { :partial => "preferences/update_success_flash" } redirect_to preferences_path diff --git a/app/views/layouts/_head.html.erb b/app/views/layouts/_head.html.erb index 3c691612ab..bab19c2171 100644 --- a/app/views/layouts/_head.html.erb +++ b/app/views/layouts/_head.html.erb @@ -5,7 +5,11 @@ <%= javascript_include_tag "turbo", :type => "module" %> <%= javascript_include_tag "application" %> <%= javascript_include_tag "i18n/#{I18n.locale}" %> - <%= stylesheet_link_tag "screen-#{dir}", :media => "screen" %> + <% if preferred_color_scheme(:site) == "auto" %> + <%= stylesheet_link_tag "screen-auto-#{dir}", :media => "screen" %> + <% else %> + <%= stylesheet_link_tag "screen-manual-#{dir}", :media => "screen" %> + <% end %> <%= stylesheet_link_tag "print-#{dir}", :media => "print" %> <%= stylesheet_link_tag "leaflet-all", :media => "screen, print" %> <%= render :partial => "layouts/meta" %> diff --git a/app/views/layouts/site.html.erb b/app/views/layouts/site.html.erb index 7c921658d4..f02f024a57 100644 --- a/app/views/layouts/site.html.erb +++ b/app/views/layouts/site.html.erb @@ -1,11 +1,14 @@ - +<%= tag.html :lang => I18n.locale, + :dir => dir, + :data => { :bs_theme => (preferred_color_scheme(:site) if preferred_color_scheme(:site) != "auto") } do %> <%= render :partial => "layouts/head" %> - + <%= tag.body :class => body_class, + :data => { :map_theme => (preferred_color_scheme(:map) if preferred_color_scheme(:map) != "auto") } do %> <%= render :partial => "layouts/header" %> <%= render :partial => "layouts/content" %> <% if defined?(Settings.matomo) -%> <% end -%> - - + <% end %> +<% end %> diff --git a/app/views/preferences/edit.html.erb b/app/views/preferences/edit.html.erb index 07d89fbb5b..aaf07e927e 100644 --- a/app/views/preferences/edit.html.erb +++ b/app/views/preferences/edit.html.erb @@ -7,6 +7,22 @@ <%= f.text_field :languages %> +
+ <%= label_tag "site_color_scheme", t("preferences.show.preferred_site_color_scheme"), :class => "form-label" %> + <%= select_tag "site_color_scheme", + options_for_select(%w[auto light dark].map { |scheme| [t("preferences.show.site_color_schemes.#{scheme}"), scheme] }, + preferred_color_scheme(:site)), + :class => "form-select" %> +
+ +
+ <%= label_tag "map_color_scheme", t("preferences.show.preferred_map_color_scheme"), :class => "form-label" %> + <%= select_tag "map_color_scheme", + options_for_select(%w[auto light dark].map { |scheme| [t("preferences.show.map_color_schemes.#{scheme}"), scheme] }, + preferred_color_scheme(:map)), + :class => "form-select" %> +
+ <%= f.primary t(".save") %> <%= link_to t(".cancel"), preferences_path, :class => "btn btn-link" %> <% end %> diff --git a/app/views/preferences/show.html.erb b/app/views/preferences/show.html.erb index 7a63d0be8d..9bf83cbf1f 100644 --- a/app/views/preferences/show.html.erb +++ b/app/views/preferences/show.html.erb @@ -19,7 +19,16 @@
  • <%= locale %>
  • <% end %> + +
    <%= t ".preferred_site_color_scheme" %>
    +
    + <%= t ".site_color_schemes.#{preferred_color_scheme(:site)}" %> +
    + +
    <%= t ".preferred_map_color_scheme" %>
    +
    + <%= t ".map_color_schemes.#{preferred_color_scheme(:map)}" %>
    diff --git a/config/locales/en.yml b/config/locales/en.yml index c3a0c5aed0..94fc77247b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1810,6 +1810,16 @@ en: title: My Preferences preferred_editor: Preferred Editor preferred_languages: Preferred Languages + preferred_site_color_scheme: Preferred Website Color Scheme + site_color_schemes: + auto: Auto + light: Light + dark: Dark + preferred_map_color_scheme: Preferred Map Color Scheme + map_color_schemes: + auto: Auto + light: Light + dark: Dark edit_preferences: Edit Preferences edit: title: Edit Preferences diff --git a/test/controllers/preferences_controller_test.rb b/test/controllers/preferences_controller_test.rb index 81760fe5de..1cd07b7d9f 100644 --- a/test/controllers/preferences_controller_test.rb +++ b/test/controllers/preferences_controller_test.rb @@ -22,6 +22,8 @@ def test_routes def test_update_preferred_editor user = create(:user, :languages => []) + user.preferences.create(:k => "site.color_scheme", :v => "light") + user.preferences.create(:k => "map.color_scheme", :v => "light") session_for(user) # Changing to a invalid editor should fail @@ -32,6 +34,8 @@ def test_update_preferred_editor assert_select ".alert-success", false assert_select ".alert-danger", true assert_select "form > div > select#user_preferred_editor > option[selected]", false + assert_equal "light", user.preferences.find_by(:k => "site.color_scheme")&.v + assert_equal "light", user.preferences.find_by(:k => "map.color_scheme")&.v # Changing to a valid editor should work user.preferred_editor = "id" @@ -41,6 +45,8 @@ def test_update_preferred_editor assert_template :show assert_select ".alert-success", /^Preferences updated/ assert_select "dd", "iD (in-browser editor)" + assert_equal "light", user.preferences.find_by(:k => "site.color_scheme")&.v + assert_equal "light", user.preferences.find_by(:k => "map.color_scheme")&.v # Changing to the default editor should work user.preferred_editor = "default" @@ -50,5 +56,51 @@ def test_update_preferred_editor assert_template :show assert_select ".alert-success", /^Preferences updated/ assert_select "dd", "Default (currently iD)" + assert_equal "light", user.preferences.find_by(:k => "site.color_scheme")&.v + assert_equal "light", user.preferences.find_by(:k => "map.color_scheme")&.v + end + + def test_update_preferred_site_color_scheme + user = create(:user, :languages => []) + session_for(user) + assert_nil user.preferences.find_by(:k => "site.color_scheme") + + # Changing when previously not defined + put preferences_path, :params => { :user => user.attributes, :site_color_scheme => "light" } + assert_redirected_to preferences_path + follow_redirect! + assert_template :show + assert_select ".alert-success", /^Preferences updated/ + assert_equal "light", user.preferences.find_by(:k => "site.color_scheme")&.v + + # Changing when previously defined + put preferences_path, :params => { :user => user.attributes, :site_color_scheme => "auto" } + assert_redirected_to preferences_path + follow_redirect! + assert_template :show + assert_select ".alert-success", /^Preferences updated/ + assert_equal "auto", user.preferences.find_by(:k => "site.color_scheme")&.v + end + + def test_update_preferred_map_color_scheme + user = create(:user, :languages => []) + session_for(user) + assert_nil user.preferences.find_by(:k => "map.color_scheme") + + # Changing when previously not defined + put preferences_path, :params => { :user => user.attributes, :map_color_scheme => "light" } + assert_redirected_to preferences_path + follow_redirect! + assert_template :show + assert_select ".alert-success", /^Preferences updated/ + assert_equal "light", user.preferences.find_by(:k => "map.color_scheme")&.v + + # Changing when previously defined + put preferences_path, :params => { :user => user.attributes, :map_color_scheme => "auto" } + assert_redirected_to preferences_path + follow_redirect! + assert_template :show + assert_select ".alert-success", /^Preferences updated/ + assert_equal "auto", user.preferences.find_by(:k => "map.color_scheme")&.v end end