From 20f4f6b8694c48c236d23f69b3699b69cda35a1e Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Mon, 18 Aug 2025 14:00:42 +0200 Subject: [PATCH] UX: immediately download a feature that has the ID via the hash to display it faster --- src/Logic/Osm/OsmObject.ts | 10 +++---- src/Logic/Web/ThemeViewStateHashActor.ts | 30 ++++++++++++++++----- src/Models/ThemeViewState/WithImageState.ts | 7 +---- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/Logic/Osm/OsmObject.ts b/src/Logic/Osm/OsmObject.ts index b85bc55b8..bd60a9a28 100644 --- a/src/Logic/Osm/OsmObject.ts +++ b/src/Logic/Osm/OsmObject.ts @@ -2,7 +2,7 @@ import { Utils } from "../../Utils" import polygon_features from "../../assets/polygon-features.json" import { OsmFeature, OsmId, OsmTags, WayId } from "../../Models/OsmFeature" import OsmToGeoJson from "osmtogeojson" -import { Feature, LineString, Polygon } from "geojson" +import { Feature, LineString, Point, Polygon } from "geojson" import Constants from "../../Models/Constants" export abstract class OsmObject { @@ -131,7 +131,7 @@ export abstract class OsmObject { */ public abstract centerpoint(): [number, number] - public abstract asGeoJson(): any + public abstract asGeoJson(): OsmFeature abstract SaveExtraData(element: any, allElements: OsmObject[] | any) @@ -228,7 +228,7 @@ ${tags} return [this.lat, this.lon] } - asGeoJson(): OsmFeature { + asGeoJson(): Feature { return { type: "Feature", properties: this.tags, @@ -305,7 +305,7 @@ ${nds}${tags} this.nodes = element.nodes } - public asGeoJson(): Feature & { properties: { id: WayId } } { + public asGeoJson(): Feature & { properties: { id: WayId } } { const coordinates: [number, number][] | [number, number][][] = this.coordinates.map( ([lat, lon]) => [lon, lat] ) @@ -384,7 +384,7 @@ ${members}${tags} this.geojson = geojson } - asGeoJson(): any { + asGeoJson(): OsmFeature { if (this.geojson !== undefined) { return this.geojson } diff --git a/src/Logic/Web/ThemeViewStateHashActor.ts b/src/Logic/Web/ThemeViewStateHashActor.ts index e02f23d19..aee944c9d 100644 --- a/src/Logic/Web/ThemeViewStateHashActor.ts +++ b/src/Logic/Web/ThemeViewStateHashActor.ts @@ -4,13 +4,17 @@ import { AndroidPolyfill } from "./AndroidPolyfill" import { IndexedFeatureSource } from "../FeatureSource/FeatureSource" import { Feature } from "geojson" import { Store, UIEventSource } from "../UIEventSource" +import ThemeViewState from "../../Models/ThemeViewState" +import OsmObjectDownloader from "../Osm/OsmObjectDownloader" +import ThemeSource from "../FeatureSource/Sources/ThemeSource" export default class ThemeViewStateHashActor { - private readonly _state: { + private readonly _state: Readonly<{ indexedFeatures: IndexedFeatureSource selectedElement: UIEventSource - guistate: MenuState - } + guistate: MenuState, + osmObjectDownloader: OsmObjectDownloader + }> private isUpdatingHash = false public static readonly documentation = [ @@ -35,12 +39,13 @@ export default class ThemeViewStateHashActor { * As such, we use a change in the hash to close the appropriate windows * */ - constructor(state: { + constructor(state: Readonly<{ featureSwitches: { featureSwitchBackToThemeOverview: Store } - indexedFeatures: IndexedFeatureSource + indexedFeatures: IndexedFeatureSource & ThemeSource selectedElement: UIEventSource - guistate: MenuState - }) { + guistate: MenuState, + osmObjectDownloader: OsmObjectDownloader + }> ) { this._state = state AndroidPolyfill.onBackButton(() => this.back(), { returnToIndex: state.featureSwitches.featureSwitchBackToThemeOverview, @@ -50,6 +55,17 @@ export default class ThemeViewStateHashActor { const containsMenu = this.loadStateFromHash(hashOnLoad) // First of all, try to recover the selected element if (!containsMenu && hashOnLoad?.length > 0) { + if (hashOnLoad.startsWith("node/") || hashOnLoad.startsWith("way/") || hashOnLoad.startsWith("relation/")) { + // This is an OSM-element. Let's download it and add it to the indexedFeatures + console.log("Directly downloading item from hash") + state.osmObjectDownloader.DownloadObjectAsync(hashOnLoad) + .then(osmObj => { + if (osmObj === "deleted") { + return + } + state.indexedFeatures.addItem(osmObj.asGeoJson()) + }) + } state.indexedFeatures.featuresById.addCallbackAndRunD(() => { // once that we have found a matching element, we can be sure the indexedFeaturesource was popuplated and that the job is done return this.loadSelectedElementFromHash(hashOnLoad) diff --git a/src/Models/ThemeViewState/WithImageState.ts b/src/Models/ThemeViewState/WithImageState.ts index 79a55aa8b..179baabcd 100644 --- a/src/Models/ThemeViewState/WithImageState.ts +++ b/src/Models/ThemeViewState/WithImageState.ts @@ -51,12 +51,7 @@ export class WithImageState extends WithGuiState implements SpecialVisualization * Setup various services for which no reference are needed */ private initActors() { - new ThemeViewStateHashActor({ - featureSwitches: this.featureSwitches, - selectedElement: this.selectedElement, - indexedFeatures: this.indexedFeatures, - guistate: this.guistate, - }) + new ThemeViewStateHashActor(this) new PendingChangesUploader(this.changes, this.selectedElement, this.imageUploadManager) } }