diff --git a/app/assets/javascripts/index/contextmenu.js b/app/assets/javascripts/index/contextmenu.js index ea284f29b9..60257291d5 100644 --- a/app/assets/javascripts/index/contextmenu.js +++ b/app/assets/javascripts/index/contextmenu.js @@ -74,6 +74,66 @@ OSM.initializeContextMenu = function (map) { } }); + const expiry = new Date(); + expiry.setYear(expiry.getFullYear() + 10); + let selectedDarkModeFilter = Cookies.get("_osm_dark_mode_filter") || "brightness80"; + + let darkModeMenuElements = $(map.contextmenu.addItem({ + separator: true + })); + + const darkModeMenuItems = [ + { + name: "brightness100", + filter: "none" + }, + { + name: "brightness80", + filter: "brightness(.8)" + }, + { + name: "brightness60", + filter: "brightness(.6)" + }, + { + name: "invert", + filter: "invert(.8) hue-rotate(180deg)" + } + ]; + darkModeMenuItems.forEach((menuItem) => { + if (selectedDarkModeFilter === menuItem.name) { + $(":root").css("--dark-mode-filter", menuItem.filter); + } + const darkModeMenuElement = $(map.contextmenu.addItem({ + text: I18n.t("javascripts.map.filters." + menuItem.name), + callback: () => { + selectedDarkModeFilter = menuItem.name; + Cookies.set("_osm_dark_mode_filter", menuItem.name, { secure: true, expires: expiry, path: "/", samesite: "lax" }); + $(":root").css("--dark-mode-filter", menuItem.filter); + updateDarkModeMenu(); + } + })); + darkModeMenuElement.prepend( + $("") + .data("filter", menuItem.name) + .css("transform", "scale(80%)") + ); + darkModeMenuElements = darkModeMenuElements.add(darkModeMenuElement); + }); + + const prefersDarkQuery = matchMedia("(prefers-color-scheme: dark)"); + L.DomEvent.on(prefersDarkQuery, "change", () => { + updateDarkModeMenu(); + }); + updateDarkModeMenu(); + + function updateDarkModeMenu() { + darkModeMenuElements.toggle(prefersDarkQuery.matches); + darkModeMenuElements.find("input[type='radio']").each(function () { + $(this).prop("checked", $(this).data("filter") === selectedDarkModeFilter); + }); + } + map.on("mousedown", function (e) { if (e.originalEvent.shiftKey) map.contextmenu.disable(); else map.contextmenu.enable(); diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index 31ce7dd28a..10ce596e29 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -504,7 +504,7 @@ body.small-nav { @include color-mode(dark) { .leaflet-tile-container .leaflet-tile, .mapkey-table-entry td:first-child > * { - filter: brightness(.8); + filter: var(--dark-mode-filter, brightness(.8)); } .leaflet-control-attribution a { diff --git a/config/locales/en.yml b/config/locales/en.yml index f68488c09c..8ac959316c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3073,6 +3073,11 @@ en: tracestrack: Tracestrack hotosm_credit: "Tiles style by %{hotosm_link} hosted by %{osm_france_link}" hotosm_name: Humanitarian OpenStreetMap Team + filters: + brightness100: 100% brightness + brightness80: 80% brightness + brightness60: 60% brightness + invert: Invert site: edit_tooltip: Edit the map edit_disabled_tooltip: Zoom in to edit the map