From 77b1c8015fb0eeba3297e238ef447a494937fa45 Mon Sep 17 00:00:00 2001 From: Marwin Hochfelsner <50826859+hlfan@users.noreply.github.com> Date: Sat, 1 Mar 2025 00:34:13 +0100 Subject: [PATCH] Add basic PWA geo protocol handler --- app/assets/favicons/manifest.json.erb | 8 +++++++- app/assets/javascripts/osm.js.erb | 9 +++++++++ test/javascripts/osm_test.js | 12 ++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/app/assets/favicons/manifest.json.erb b/app/assets/favicons/manifest.json.erb index 2e97cebc3..53fdfcc77 100644 --- a/app/assets/favicons/manifest.json.erb +++ b/app/assets/favicons/manifest.json.erb @@ -14,5 +14,11 @@ "start_url": "/", "theme_color": "#7ebc6f", "background_color": "#fff", - "display": "minimal-ui" + "display": "minimal-ui", + "protocol_handlers": [ + { + "protocol": "geo", + "url": "/?geouri=%s" + } + ] } diff --git a/app/assets/javascripts/osm.js.erb b/app/assets/javascripts/osm.js.erb index a40ae6eb8..9c38db987 100644 --- a/app/assets/javascripts/osm.js.erb +++ b/app/assets/javascripts/osm.js.erb @@ -63,6 +63,7 @@ OSM = { mapParams: function (search) { const params = OSM.params(search), + geoURI = URL.canParse(params.geouri) ? new URL(params.geouri) : {}, mapParams = {}; if (params.mlon && params.mlat) { @@ -70,6 +71,11 @@ OSM = { mapParams.mlon = parseFloat(params.mlon); mapParams.mlat = parseFloat(params.mlat); } + if (geoURI.lon && geoURI.lat) { + mapParams.marker = true; + mapParams.mlon = parseFloat(geoURI.lon); + mapParams.mlat = parseFloat(geoURI.lat); + } // Old-style object parameters; still in use for edit links e.g. /edit?way=1234 for (const type of ["node", "way", "relation", "note"]) { @@ -100,6 +106,9 @@ OSM = { mapParams.lon = params.mlon; mapParams.lat = params.mlat; mapParams.zoom = params.zoom || 12; + } else if (geoURI.pathname) { + [mapParams.lat, mapParams.lon] = geoURI.pathname.split(","); + mapParams.zoom = geoURI.searchParams?.get("z") || (geoURI.pathname.replaceAll(/,?[-\d]+\./g, "").length / 0.6) - 2; } else if (loc) { [mapParams.lon, mapParams.lat, mapParams.zoom] = loc; } else if (OSM.home) { diff --git a/test/javascripts/osm_test.js b/test/javascripts/osm_test.js index 2f96ccb3d..6486d3cbc 100644 --- a/test/javascripts/osm_test.js +++ b/test/javascripts/osm_test.js @@ -82,6 +82,18 @@ describe("OSM", function () { expect(params).to.have.property("zoom", 16); }); + it("parses geoURIs", function () { + let params = OSM.mapParams("?geouri=geo%3A57.6247%2C-3.6845"); + expect(params).to.have.property("lat", 57.6247); + expect(params).to.have.property("lon", -3.6845); + expect(params).to.have.property("zoom", 34 / 3); + + params = OSM.mapParams("?geouri=geo%3A57.6247%2C-3.6845%3Fz%3D16"); + expect(params).to.have.property("lat", 57.6247); + expect(params).to.have.property("lon", -3.6845); + expect(params).to.have.property("zoom", 16); + }); + it("parses lat/lon/zoom from the hash", function () { location.hash = "#map=16/57.6247/-3.6845"; const params = OSM.mapParams("?");