diff --git a/app/assets/javascripts/index/contextmenu.js b/app/assets/javascripts/index/contextmenu.js index cac5e6fbf8c..5ebb54d2d8a 100644 --- a/app/assets/javascripts/index/contextmenu.js +++ b/app/assets/javascripts/index/contextmenu.js @@ -74,6 +74,8 @@ OSM.initializeContextMenu = function (map) { } }); + L.OSM.colorSchemeWatcher.manageContextMenu(map.contextmenu); + map.on("mousedown", function (e) { if (e.originalEvent.shiftKey) map.contextmenu.disable(); else map.contextmenu.enable(); diff --git a/vendor/assets/leaflet/leaflet.osm.js b/vendor/assets/leaflet/leaflet.osm.js index cd1388b06e2..cf574e99c56 100644 --- a/vendor/assets/leaflet/leaflet.osm.js +++ b/vendor/assets/leaflet/leaflet.osm.js @@ -2,12 +2,16 @@ L.OSM = {}; L.OSM.colorSchemeWatcher = { darkFilter: 'brightness(.8)', + _managedContextMenuElements: [], _watchedLayers: [], enable: function() { var watcher = this; matchMedia("(prefers-color-scheme: dark)").addEventListener("change", function() { - var prefersDarkScheme = matchMedia("(prefers-color-scheme: dark)").matches; + var prefersDarkScheme = watcher._prefersDarkScheme(); + watcher._managedContextMenuElements.forEach(function (element) { + element.hidden = !prefersDarkScheme; + }); watcher._watchedLayers.forEach(function (watchedLayer) { if (prefersDarkScheme) { watcher._switchLayerToDarkScheme(watchedLayer); @@ -18,10 +22,57 @@ L.OSM.colorSchemeWatcher = { }); }, + // requires Leaflet.contextmenu plugin + manageContextMenu: function (contextmenu) { + var watcher = this; + var prefersDarkScheme = watcher._prefersDarkScheme(); + var separator = contextmenu.addItem({ + separator: true + }); + watcher._managedContextMenuElements.push(separator); + if (!prefersDarkScheme) { + separator.hidden = true; + } + var menuItems = [ + { + text: "100% brightness", + filter: "" + }, + { + text: "80% brightness", + filter: "brightness(.8)" + }, + { + text: "60% brightness", + filter: "brightness(.6)" + }, + { + text: "Invert", + filter: "invert(.8) hue-rotate(180deg)" + }, + ]; + menuItems.forEach(function (menuItem) { + var menuElement = contextmenu.addItem({ + text: menuItem.text, + callback: function () { + watcher.darkFilter = menuItem.filter; + if (watcher._prefersDarkScheme()) { + watcher._watchedLayers.forEach(function (watchedLayer) { + watcher._updateLayerDarkScheme(watchedLayer); + }); + } + } + }); + watcher._managedContextMenuElements.push(menuElement); + if (!prefersDarkScheme) { + menuElement.hidden = true; + } + }); + }, + addLayer: function (layer) { this._watchedLayers.push(layer); - var prefersDarkScheme = matchMedia("(prefers-color-scheme: dark)").matches; - if (prefersDarkScheme) { + if (this._prefersDarkScheme()) { this._switchLayerToDarkScheme(layer); } }, @@ -32,24 +83,40 @@ L.OSM.colorSchemeWatcher = { this._switchLayerToLightScheme(layer); }, + _prefersDarkScheme: function() { + return matchMedia("(prefers-color-scheme: dark)").matches; + }, + _switchLayerToDarkScheme: function (layer) { if (layer.options.darkUrl) { layer.setUrl(layer.options.darkUrl); } else { - var container = layer.getContainer(); - if (container) { - container.style.setProperty('filter', this.darkFilter); - } + this._setDarkFilterForLayer(layer); } }, _switchLayerToLightScheme: function (layer) { if (layer.options.darkUrl) { layer.setUrl(layer.options.url); } else { - var container = layer.getContainer(); - if (container) { - layer.getContainer().style.removeProperty('filter'); - } + this._removeDarkFilterFromLayer(layer); + } + }, + _updateLayerDarkScheme: function (layer) { + if (!layer.options.darkUrl) { + this._setDarkFilterForLayer(layer); + } + }, + + _setDarkFilterForLayer: function (layer) { + var container = layer.getContainer(); + if (container) { + container.style.setProperty('filter', this.darkFilter); + } + }, + _removeDarkFilterFromLayer: function (layer) { + var container = layer.getContainer(); + if (container) { + layer.getContainer().style.removeProperty('filter'); } } };