Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map color mode preference #5362

Merged
22 changes: 17 additions & 5 deletions app/assets/stylesheets/common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -502,11 +502,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);
}
Expand All @@ -516,6 +511,23 @@ body.small-nav {
}
}

@mixin dark-map-color-scheme {
.leaflet-tile-container .leaflet-tile,
.mapkey-table-entry td:first-child > * {
filter: brightness(.8);
Copy link
Contributor

@hlfan hlfan Dec 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't the mentioned step 5 include the need for the filters to be set individually to give the cartographers a choice?
I don't see that as a necessity for this PR, but already setting the filter through a custom property defined on the layer could ease the transition to that being implemented and also act as default and fallback:

here {
    filter: var(--dark-mode-map-filter);
}
somewhere else {
    .leaflet-layer {
        --dark-mode-map-filter: brightness(.8);
    }
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Step 5 has an impossible requirement of "make it dark but don't pick any filter". The closest possible thing is "don't touch existing filters".

}
}

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; }
Expand Down
1 change: 0 additions & 1 deletion app/assets/stylesheets/parameters.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
3 changes: 3 additions & 0 deletions app/assets/stylesheets/screen-auto-ltr.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@use "common" with (
$color-mode-type: media-query
);
3 changes: 3 additions & 0 deletions app/assets/stylesheets/screen-auto-rtl.rtlcss.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@use "common" with (
$color-mode-type: media-query
);
1 change: 0 additions & 1 deletion app/assets/stylesheets/screen-ltr.scss

This file was deleted.

3 changes: 3 additions & 0 deletions app/assets/stylesheets/screen-manual-ltr.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@use "common" with (
$color-mode-type: data
);
3 changes: 3 additions & 0 deletions app/assets/stylesheets/screen-manual-rtl.rtlcss.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@use "common" with (
$color-mode-type: data
);
1 change: 0 additions & 1 deletion app/assets/stylesheets/screen-rtl.rtlcss.scss

This file was deleted.

10 changes: 9 additions & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,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)
Expand Down
15 changes: 14 additions & 1 deletion app/controllers/preferences_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion app/views/layouts/_head.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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" %>
Expand Down
11 changes: 7 additions & 4 deletions app/views/layouts/site.html.erb
Original file line number Diff line number Diff line change
@@ -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 %>
16 changes: 16 additions & 0 deletions app/views/preferences/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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 %>
9 changes: 9 additions & 0 deletions app/views/preferences/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,16 @@
<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>

Expand Down
10 changes: 10 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1807,6 +1807,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
Expand Down
52 changes: 52 additions & 0 deletions test/controllers/preferences_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand All @@ -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"
Expand All @@ -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