]> git.openstreetmap.org Git - rails.git/commitdiff
Merge pull request #5362 from AntonKhorev/color-mode-preference-map
authorAndy Allan <git@gravitystorm.co.uk>
Wed, 11 Dec 2024 16:53:15 +0000 (16:53 +0000)
committerGitHub <noreply@github.com>
Wed, 11 Dec 2024 16:53:15 +0000 (16:53 +0000)
Map color mode preference

16 files changed:
app/assets/stylesheets/common.scss
app/assets/stylesheets/parameters.scss
app/assets/stylesheets/screen-auto-ltr.scss [new file with mode: 0644]
app/assets/stylesheets/screen-auto-rtl.rtlcss.scss [new file with mode: 0644]
app/assets/stylesheets/screen-ltr.scss [deleted file]
app/assets/stylesheets/screen-manual-ltr.scss [new file with mode: 0644]
app/assets/stylesheets/screen-manual-rtl.rtlcss.scss [new file with mode: 0644]
app/assets/stylesheets/screen-rtl.rtlcss.scss [deleted file]
app/controllers/application_controller.rb
app/controllers/preferences_controller.rb
app/views/layouts/_head.html.erb
app/views/layouts/site.html.erb
app/views/preferences/edit.html.erb
app/views/preferences/show.html.erb
config/locales/en.yml
test/controllers/preferences_controller_test.rb

index c5e2d14b1577a8a35e90747739616b5f56b6b672..cabdfff493bac420e9daa5b1fe0b3cc3bc6570b9 100644 (file)
@@ -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; }
index 28bf569016a607d81b4aa01b994226ca8366845e..07549d69bb33e939238f98e6ef6d1e44eea4a816 100644 (file)
@@ -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 (file)
index 0000000..89e3159
--- /dev/null
@@ -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 (file)
index 0000000..89e3159
--- /dev/null
@@ -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 (file)
index c525060..0000000
+++ /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 (file)
index 0000000..00f65f7
--- /dev/null
@@ -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 (file)
index 0000000..00f65f7
--- /dev/null
@@ -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 (file)
index c525060..0000000
+++ /dev/null
@@ -1 +0,0 @@
-@import "common";
index bde7e028765c81b5426a5eed2e8c74957abee4b2..32b53bad71c3f431d79234d65e354f6cafcf13c9 100644 (file)
@@ -279,7 +279,15 @@ class ApplicationController < ActionController::Base
     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)
index dcf0d8b64e2682364b7c5b489ad1c9c72662bd19..1d96766ef227b7dbaa86b870f03ca1534c8513c6 100644 (file)
@@ -21,7 +21,20 @@ class PreferencesController < ApplicationController
                                     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
index 3c691612ab1d4c37ec1ad7a0f8c001b334e50272..bab19c217191fb089bc1681a5e93851c3df965dd 100644 (file)
@@ -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" %>
index 7c921658d46102d54b720eb5deb57a7107f07d9b..f02f024a57a69e84905c76122f1b16ff053e8f20 100644 (file)
@@ -1,11 +1,14 @@
 <!DOCTYPE html>
-<html lang="<%= I18n.locale %>" dir="<%= dir %>">
+<%= 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" %>
-  <body class="<%= body_class %>">
+  <%= 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) -%>
     <noscript><p><img src="<%= request.protocol %><%= Settings.matomo["location"] %>/matomo.php?idsite=<%= Settings.matomo["site"] %>" class="matomo" alt="" /></p></noscript>
     <% end -%>
-  </body>
-</html>
+  <% end %>
+<% end %>
index 07d89fbb5bcb567fe443f8ec30c11175ceffeb3f..aaf07e927e27a11b9d0a599a9ce2d4887563307d 100644 (file)
@@ -7,6 +7,22 @@
 
   <%= f.text_field :languages %>
 
+  <div class="mb-3">
+    <%= 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" %>
+  </div>
+
+  <div class="mb-3">
+    <%= 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" %>
+  </div>
+
   <%= f.primary t(".save") %>
   <%= link_to t(".cancel"), preferences_path, :class => "btn btn-link" %>
 <% end %>
index 7a63d0be8dadeb57514fba42b8b139b7335cce62..9bf83cbf1f0f72b846e3c43bbac278703fcef61a 100644 (file)
         <li><%= locale %></li>
       <% end %>
     </ul>
+  </dd>
 
+  <dt class="col-sm-4"><%= t ".preferred_site_color_scheme" %></dt>
+  <dd class="col-sm-8">
+    <%= t ".site_color_schemes.#{preferred_color_scheme(:site)}" %>
+  </dd>
+
+  <dt class="col-sm-4"><%= t ".preferred_map_color_scheme" %></dt>
+  <dd class="col-sm-8">
+    <%= t ".map_color_schemes.#{preferred_color_scheme(:map)}" %>
   </dd>
 </dl>
 
index c3a0c5aed0802f2afe1c8acaf4eafee1f5c7e8e4..94fc77247b8cadc74f8f433dbbc18a05ddedf1a2 100644 (file)
@@ -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
index 81760fe5de54816a88b448dcdd6a47e3ea008a8e..1cd07b7d9f68a4adfaa6fc655215a80a21edceab 100644 (file)
@@ -22,6 +22,8 @@ class PreferencesControllerTest < ActionDispatch::IntegrationTest
 
   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 @@ class PreferencesControllerTest < ActionDispatch::IntegrationTest
     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 @@ class PreferencesControllerTest < ActionDispatch::IntegrationTest
     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 @@ class PreferencesControllerTest < ActionDispatch::IntegrationTest
     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