Feature(pwa): add protocol handler

This commit is contained in:
Pieter Vander Vennet 2025-06-16 02:33:37 +02:00
parent 50c2abebdf
commit de74a5dc08
4 changed files with 43 additions and 17 deletions

View file

@ -168,6 +168,7 @@ class GenerateLayouts extends Script {
manifest: any manifest: any
whiteIcons: string[] whiteIcons: string[]
}> { }> {
const id = layout.id
Translation.forcedLanguage = "en" Translation.forcedLanguage = "en"
const icons = [] const icons = []
@ -228,7 +229,7 @@ class GenerateLayouts extends Script {
const manifest = { const manifest = {
name: ogTitle, name: ogTitle,
short_name: ogTitle, short_name: ogTitle,
start_url: `${layout.id.toLowerCase()}.html`, start_url: `${id.toLowerCase()}.html`,
lang: "en", lang: "en",
display: "standalone", display: "standalone",
background_color: "#fff", background_color: "#fff",
@ -236,6 +237,12 @@ class GenerateLayouts extends Script {
orientation: "portrait-primary, landscape-primary", orientation: "portrait-primary, landscape-primary",
icons: icons, icons: icons,
categories: ["map", "navigation"], categories: ["map", "navigation"],
"protocol_handlers": [
{
"protocol": "geo",
"url": `/${id.toLowerCase()}.html?geouri=%s`
}
]
} }
return { return {
manifest, manifest,

View file

@ -66,6 +66,21 @@ export default class InitialMapPositioning {
defaultLon, defaultLon,
"The initial/current longitude of the app" "The initial/current longitude of the app"
) )
const geouri = QueryParameters.GetQueryParameter("geouri", undefined, "Alternative format to set lat/lon; but with an entire geouri instead. ")
console.log("geouri", geouri.data, !!geouri.data)
if (geouri.data) {
try {
const url = new URL("geo:"+decodeURIComponent(geouri.data))
const [latN, lonN] = url.pathname.split(",").map(n => parseFloat(n))
lat.set(latN)
lon.set(lonN)
if(url.searchParams.has("q")){
QueryParameters.GetQueryParameter("q", undefined).set(url.searchParams.get("q"))
}
} catch (e) {
console.warn("Could not parse geoURI:", e)
}
}
this.location = new UIEventSource({ lon: lon.data, lat: lat.data }) this.location = new UIEventSource({ lon: lon.data, lat: lat.data })
// Note: this syncs only in one direction // Note: this syncs only in one direction

View file

@ -17,10 +17,11 @@ import { FeatureSource } from "../FeatureSource/FeatureSource"
import { Feature } from "geojson" import { Feature } from "geojson"
import OpenLocationCodeSearch from "../Search/OpenLocationCodeSearch" import OpenLocationCodeSearch from "../Search/OpenLocationCodeSearch"
import { BBox } from "../BBox" import { BBox } from "../BBox"
import { QueryParameters } from "../Web/QueryParameters"
export default class SearchState { export default class SearchState {
public readonly feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined) public readonly feedback: UIEventSource<Translation> = new UIEventSource<Translation>(undefined)
public readonly searchTerm: UIEventSource<string> = new UIEventSource<string>("") public readonly searchTerm: UIEventSource<string>
public readonly searchIsFocused = new UIEventSource(false) public readonly searchIsFocused = new UIEventSource(false)
public readonly suggestions: Store<GeocodeResult[]> public readonly suggestions: Store<GeocodeResult[]>
public readonly filterSuggestions: Store<FilterSearchResult[]> public readonly filterSuggestions: Store<FilterSearchResult[]>
@ -36,6 +37,8 @@ export default class SearchState {
constructor(state: ThemeViewState) { constructor(state: ThemeViewState) {
this.state = state this.state = state
this.searchTerm = QueryParameters.GetQueryParameter("q", "", "The term in the search field")
this.locationSearchers = [ this.locationSearchers = [
new LocalElementSearch(state, 5), new LocalElementSearch(state, 5),
new CoordinateSearch(), new CoordinateSearch(),

View file

@ -16,24 +16,25 @@ export class WithSearchState extends WithVisualFeedbackState {
super(theme, mvtAvailableLayers) super(theme, mvtAvailableLayers)
this.searchState = new SearchState(this) this.searchState = new SearchState(this)
this.initHotkeysSearch() this.initHotkeysSearch()
this.displaySearchLayer()
{ }
// Register the search layer on the map
const source = this.searchState.locationResults private displaySearchLayer() {
const flayer = this.layerState.filteredLayers.get("search")
this.featureProperties.trackFeatureSource(source) const source = this.searchState.locationResults
const options: ShowDataLayerOptions & { layer: LayerConfig } = { const flayer = this.layerState.filteredLayers.get("search")
features: source, this.featureProperties.trackFeatureSource(source)
doShowLayer: flayer.isDisplayed, const options: ShowDataLayerOptions & { layer: LayerConfig } = {
layer: flayer.layerDef, features: source,
metaTags: this.userRelatedState.preferencesAsTags, doShowLayer: flayer.isDisplayed,
onClick: (feature) => { layer: flayer.layerDef,
this.searchState.clickedOnMap(feature) metaTags: this.userRelatedState.preferencesAsTags,
}, onClick: (feature) => {
} this.searchState.clickedOnMap(feature)
new ShowDataLayer(this.map, options) },
} }
new ShowDataLayer(this.map, options)
} }
private initHotkeysSearch() { private initHotkeysSearch() {