Skip to content

Commit

Permalink
Fix applying hash query on page load (#268)
Browse files Browse the repository at this point in the history
  • Loading branch information
cdauth committed Apr 21, 2024
1 parent c9d20ce commit e080834
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export interface MapComponents {
bboxHandler: BboxHandler;
container: HTMLElement;
graphicScale: any;
hashHandler: HashHandler;
hashHandler: HashHandler & { _fmActivate: () => Promise<void> };
linesLayer: LinesLayer;
locateControl?: L.Control.Locate;
map: Map;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export interface WritableSearchFormTabContext {
setQuery(query: string, zoom?: boolean, smooth?: boolean, autofocus?: boolean): void;
setQuery(query: string, zoom?: boolean, smooth?: boolean, autofocus?: boolean): Promise<void>;
}

export type SearchFormTabContext = Readonly<WritableSearchFormTabContext>;
86 changes: 51 additions & 35 deletions frontend/src/lib/components/leaflet-map/leaflet-map-components.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type Ref, ref, watch, markRaw, reactive, watchEffect, shallowRef, shallowReadonly, type Raw } from "vue";
import { type Ref, ref, watch, markRaw, reactive, watchEffect, shallowRef, shallowReadonly, type Raw, nextTick } from "vue";
import { type Control, latLng, latLngBounds, type Map, map as leafletMap, DomUtil, control } from "leaflet";
import "leaflet/dist/leaflet.css";
import { BboxHandler, getSymbolHtml, getVisibleLayers, HashHandler, LinesLayer, MarkersLayer, SearchResultsLayer, OverpassLayer, OverpassLoadStatus, displayView, getInitialView, coreSymbolList } from "facilmap-leaflet";
Expand All @@ -15,7 +15,7 @@ import type { MapComponents, MapContextData, MapContextEvents, WritableMapContex
import type { ClientContext } from "../facil-map-context-provider/client-context";
import type { FacilMapContext } from "../facil-map-context-provider/facil-map-context";
import { requireClientContext } from "../facil-map-context-provider/facil-map-context-provider.vue";
import { type Optional, sleep } from "facilmap-utils";
import { type Optional } from "facilmap-utils";
import { getI18n, i18nResourceChangeCounter } from "../../utils/i18n";
import { AttributionControl } from "./attribution";
import { fixOnCleanup } from "../../utils/vue";
Expand Down Expand Up @@ -310,31 +310,36 @@ function useSelectionHandler(map: Ref<Map>, context: FacilMapContext, mapContext
);
}

function useHashHandler(map: Ref<Map>, client: Ref<ClientContext>, context: FacilMapContext, mapContext: MapContextWithoutComponents, overpassLayer: Ref<OverpassLayer>): Ref<Raw<HashHandler>> {
function useHashHandler(map: Ref<Map>, client: Ref<ClientContext>, context: FacilMapContext, mapContext: MapContextWithoutComponents, overpassLayer: Ref<OverpassLayer>): Ref<Raw<HashHandler & { _fmActivate: () => Promise<void> }>> {
return useMapComponent(
map,
() => markRaw(new HashHandler(map.value, client.value, { overpassLayer: overpassLayer.value, simulate: !context.settings.updateHash }))
.on("fmQueryChange", async (e: any) => {
let smooth = true;
let autofocus = false;
if (!mapContext.components) {
// This is called while the hash handler is being enabled, so it is the initial view
smooth = false;
autofocus = context.settings.autofocus;
await sleep(0); // Wait for components to be initialized (needed by openSpecialQuery())
() => {
let queryChangePromise: Promise<void> | undefined;
const hashHandler = markRaw(new HashHandler(map.value, client.value, { overpassLayer: overpassLayer.value, simulate: !context.settings.updateHash }))
.on("fmQueryChange", async (e: any) => {
let smooth = true;
let autofocus = false;

const searchFormTab = context.components.searchFormTab;
queryChangePromise = (async () => {
if (!e.query)
await searchFormTab?.setQuery("", false, false);
else if (!await openSpecialQuery(e.query, context, e.zoom, smooth))
await searchFormTab?.setQuery(e.query, e.zoom, smooth, autofocus);
})();
await queryChangePromise;
})
.on("fmHash", (e: any) => {
mapContext.hash = e.hash;
});
return Object.assign(hashHandler, {
_fmActivate: async () => {
hashHandler.enable();
await queryChangePromise;
}

const searchFormTab = context.components.searchFormTab;
if (!e.query)
searchFormTab?.setQuery("", false, false);
else if (!await openSpecialQuery(e.query, context, e.zoom, smooth))
searchFormTab?.setQuery(e.query, e.zoom, smooth, autofocus);
})
.on("fmHash", (e: any) => {
mapContext.hash = e.hash;
}),
});
},
(hashHandler, onCleanup) => {
hashHandler.enable();
onCleanup(() => {
hashHandler.disable();
});
Expand Down Expand Up @@ -420,20 +425,31 @@ export async function useMapContext(context: FacilMapContext, mapRef: Ref<HTMLEl

const client = requireClientContext(context);

if (!map._loaded) {
try {
// Initial view was not set by hash handler
displayView(map, await getInitialView(client.value), { overpassLayer });
} catch (error) {
console.error(error);
displayView(map, undefined, { overpassLayer });
(async () => {
await nextTick(); // useMapContext() return promise is resolved, setting mapContext.value in <LeafletMap>
await nextTick(); // <LeafletMap> rerenders with its slot, search box tabs are now available and can receive the query from the hash handler

await mapContext.components.hashHandler._fmActivate();

if (!map._loaded) {
try {
// Initial view was not set by hash handler
displayView(map, await getInitialView(client.value), { overpassLayer });
} catch (error) {
console.error(error);
displayView(map, undefined, { overpassLayer });
}
}
}

watchEffect(() => {
mapContext.activeQuery = getHashQuery(mapContext.components.map, client.value, mapContext.selection) || mapContext.fallbackQuery;
mapContext.components.hashHandler.setQuery(mapContext.activeQuery);
});
watch(() => mapContext.components.hashHandler, async (hashHandler) => {
await hashHandler._fmActivate();
});

watchEffect(() => {
mapContext.activeQuery = getHashQuery(mapContext.components.map, client.value, mapContext.selection) || mapContext.fallbackQuery;
mapContext.components.hashHandler.setQuery(mapContext.activeQuery);
});
})().catch(console.error);

return mapContext;
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/lib/components/search-form/search-form-tab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
}
const searchFormTabContext: WritableSearchFormTabContext = {
setQuery(query, zoom = false, smooth = true, autofocus = false): void {
async setQuery(query, zoom = false, smooth = true, autofocus = false): Promise<void> {
searchForm.value!.setSearchString(query);
searchForm.value!.search(zoom, undefined, smooth);
searchBoxContext.value.activateTab(`fm${context.id}-search-form-tab`, { expand: !!query, autofocus });
await searchForm.value!.search(zoom, undefined, smooth);
}
};
Expand Down
2 changes: 1 addition & 1 deletion leaflet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"leaflet-auto-graticule": "^2.0.0",
"leaflet-draggable-lines": "^2.0.0",
"leaflet-freie-tonne": "^2.0.1",
"leaflet-highlightable-layers": "^3.0.0",
"leaflet-highlightable-layers": "^3.0.1",
"leaflet.markercluster": "^1.5.3",
"lodash-es": "^4.17.21"
},
Expand Down
4 changes: 2 additions & 2 deletions leaflet/src/lines/lines-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,13 @@ export default class LinesLayer extends FeatureGroup {

highlightLine(id: ID): void {
this.highlightedLinesIds.add(id);
if (this.client.lines[id])
if (this._map && this.client.lines[id])
this.handleLine(this.client.lines[id]);
}

unhighlightLine(id: ID): void {
this.highlightedLinesIds.delete(id);
if (this.client.lines[id])
if (this._map && this.client.lines[id])
this.handleLine(this.client.lines[id]);
}

Expand Down
4 changes: 2 additions & 2 deletions leaflet/src/markers/markers-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,13 @@ export default class MarkersLayer extends MarkerCluster {

highlightMarker(id: ID): void {
this.highlightedMarkerIds.add(id);
if (this.client.markers[id])
if (this._map && this.client.markers[id])
this.handleMarker(this.client.markers[id]);
}

unhighlightMarker(id: ID): void {
this.highlightedMarkerIds.delete(id);
if (this.client.markers[id])
if (this._map && this.client.markers[id])
this.handleMarker(this.client.markers[id]);
}

Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4013,7 +4013,7 @@ __metadata:
leaflet-auto-graticule: ^2.0.0
leaflet-draggable-lines: ^2.0.0
leaflet-freie-tonne: ^2.0.1
leaflet-highlightable-layers: ^3.0.0
leaflet-highlightable-layers: ^3.0.1
leaflet.markercluster: ^1.5.3
lodash-es: ^4.17.21
node-fetch: ^3.3.2
Expand Down Expand Up @@ -5490,12 +5490,12 @@ __metadata:
languageName: node
linkType: hard

"leaflet-highlightable-layers@npm:^3.0.0":
version: 3.0.0
resolution: "leaflet-highlightable-layers@npm:3.0.0"
"leaflet-highlightable-layers@npm:^3.0.1":
version: 3.0.1
resolution: "leaflet-highlightable-layers@npm:3.0.1"
peerDependencies:
leaflet: x
checksum: b0ffe1210f5f5cde618866980589f41b4083e6361624bece3bd8f1cce9e0498ad8554bea5791d73ab95fe36aeb23094f4aa372773c0c96036dcedc94ff865703
checksum: 7f9478533eb86cf411f247b38a446c25d3530d077349896ba55527c9bb9300b4162ad6786a74b62ca103b8941c839336216412fd5fb03f120e247da3cb0946bf
languageName: node
linkType: hard

Expand Down

0 comments on commit e080834

Please sign in to comment.