forked from MapComplete/MapComplete
		
	Performance: cache panoramax requests more aggressively; reuse license information that comes from the search-api; lower picture limit; should relieve #2384 greatly
This commit is contained in:
		
							parent
							
								
									bd287fd8b0
								
							
						
					
					
						commit
						549129671a
					
				
					 7 changed files with 53 additions and 45 deletions
				
			
		
							
								
								
									
										28
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										28
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							|  | @ -62,8 +62,7 @@ | |||
|         "latlon2country": "^1.2.7", | ||||
|         "libphonenumber-js": "^1.11.19", | ||||
|         "mangrove-reviews-typescript": "^1.3.1", | ||||
|         "maplibre": "^0.0.1-security", | ||||
|         "maplibre-gl": "^5.1.0  ", | ||||
|         "maplibre-gl": "^5.1.0", | ||||
|         "marked": "^12.0.2", | ||||
|         "monaco-editor": "^0.46.0", | ||||
|         "mvt-to-geojson": "^0.0.6", | ||||
|  | @ -73,7 +72,7 @@ | |||
|         "osm-auth": "^2.6.0", | ||||
|         "osmtogeojson": "^3.0.0-beta.5", | ||||
|         "pannellum": "^2.5.6", | ||||
|         "panoramax-js": "^0.4.8", | ||||
|         "panoramax-js": "^0.4.11", | ||||
|         "panzoom": "^9.4.3", | ||||
|         "papaparse": "^5.5.2", | ||||
|         "pg": "^8.11.3", | ||||
|  | @ -19352,11 +19351,6 @@ | |||
|         "url": "https://github.com/sponsors/sindresorhus" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/maplibre": { | ||||
|       "version": "0.0.1-security", | ||||
|       "resolved": "https://registry.npmjs.org/maplibre/-/maplibre-0.0.1-security.tgz", | ||||
|       "integrity": "sha512-XawLsomeCq3O+x3IYTlU1QH52m9JvgEZvffgzWZ9P61HdSghJFzLUJjGXvtwV3hEuuZy9v9iSCG7W8pfr8p4Eg==" | ||||
|     }, | ||||
|     "node_modules/maplibre-gl": { | ||||
|       "version": "5.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.1.0.tgz", | ||||
|  | @ -23013,9 +23007,10 @@ | |||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/panoramax-js": { | ||||
|       "version": "0.4.8", | ||||
|       "resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.4.8.tgz", | ||||
|       "integrity": "sha512-z4kV++aHZXJ18S29DwoPScMbewNsSm69LWkmHIJzBOB0xTEUZnWyMzx+lp+5ykAJEBqlYaEhanbETlavyFiMVw==", | ||||
|       "version": "0.4.11", | ||||
|       "resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.4.11.tgz", | ||||
|       "integrity": "sha512-TrNSFMOb1nCFej+nzu0d7iGdWbToALvPkfWZdMi0l/yeQr/xj/r/ONCvSb98w8q7kAWaZnstVjs3VEC1zRqftg==", | ||||
|       "license": "GPL-3.0-or-later", | ||||
|       "dependencies": { | ||||
|         "@ogcapi-js/features": "^1.1.1", | ||||
|         "@ogcapi-js/shared": "^1.1.1", | ||||
|  | @ -43837,11 +43832,6 @@ | |||
|       "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", | ||||
|       "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==" | ||||
|     }, | ||||
|     "maplibre": { | ||||
|       "version": "0.0.1-security", | ||||
|       "resolved": "https://registry.npmjs.org/maplibre/-/maplibre-0.0.1-security.tgz", | ||||
|       "integrity": "sha512-XawLsomeCq3O+x3IYTlU1QH52m9JvgEZvffgzWZ9P61HdSghJFzLUJjGXvtwV3hEuuZy9v9iSCG7W8pfr8p4Eg==" | ||||
|     }, | ||||
|     "maplibre-gl": { | ||||
|       "version": "5.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.1.0.tgz", | ||||
|  | @ -46230,9 +46220,9 @@ | |||
|       "integrity": "sha512-R4kSPpj36wQPlyIi9ZftxPfVYF11DEbNBATUEI+pkMGZDFYBV5Jxi6tYFVDdmxA2xaTeKZQHMIuIIj7njVSTQQ==" | ||||
|     }, | ||||
|     "panoramax-js": { | ||||
|       "version": "0.4.8", | ||||
|       "resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.4.8.tgz", | ||||
|       "integrity": "sha512-z4kV++aHZXJ18S29DwoPScMbewNsSm69LWkmHIJzBOB0xTEUZnWyMzx+lp+5ykAJEBqlYaEhanbETlavyFiMVw==", | ||||
|       "version": "0.4.11", | ||||
|       "resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.4.11.tgz", | ||||
|       "integrity": "sha512-TrNSFMOb1nCFej+nzu0d7iGdWbToALvPkfWZdMi0l/yeQr/xj/r/ONCvSb98w8q7kAWaZnstVjs3VEC1zRqftg==", | ||||
|       "requires": { | ||||
|         "@ogcapi-js/features": "^1.1.1", | ||||
|         "@ogcapi-js/shared": "^1.1.1", | ||||
|  |  | |||
|  | @ -233,7 +233,7 @@ | |||
|     "osm-auth": "^2.6.0", | ||||
|     "osmtogeojson": "^3.0.0-beta.5", | ||||
|     "pannellum": "^2.5.6", | ||||
|     "panoramax-js": "^0.4.8", | ||||
|     "panoramax-js": "^0.4.11", | ||||
|     "panzoom": "^9.4.3", | ||||
|     "papaparse": "^5.5.2", | ||||
|     "pg": "^8.11.3", | ||||
|  |  | |||
|  | @ -20,7 +20,8 @@ export interface ProvidedImage { | |||
|     lat?: number | ||||
|     lon?: number | ||||
|     host?: string | ||||
|     isSpherical: boolean | ||||
|     isSpherical: boolean, | ||||
|     license?: LicenseInfo | ||||
| } | ||||
| 
 | ||||
| export interface PanoramaView { | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ export default class PanoramaxImageProvider extends ImageProvider { | |||
|     public defaultKeyPrefixes: string[] = ["panoramax"] | ||||
|     public readonly name: string = "panoramax" | ||||
| 
 | ||||
|     private static knownMeta: Record<string, { data: ImageData; time: Date }> = {} | ||||
|     private static knownMeta: Record<string, { data: Promise<{ data: ImageData, url: string }>; time: Date }> = {} | ||||
| 
 | ||||
|     public SourceIcon( | ||||
|         img?: { id: string; url: string }, | ||||
|  | @ -45,8 +45,8 @@ export default class PanoramaxImageProvider extends ImageProvider { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     public addKnownMeta(meta: ImageData) { | ||||
|         PanoramaxImageProvider.knownMeta[meta.id] = { data: meta, time: new Date() } | ||||
|     public addKnownMeta(meta: ImageData, url?: string) { | ||||
|         PanoramaxImageProvider.knownMeta[meta.id] = { data: Promise.resolve({ data: meta, url }), time: new Date() } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -102,16 +102,7 @@ export default class PanoramaxImageProvider extends ImageProvider { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private async getInfoFor(id: string): Promise<{ data: ImageData; url: string }> { | ||||
|         if (!id.match(/^[a-zA-Z0-9-]+$/)) { | ||||
|             return undefined | ||||
|         } | ||||
|         const cached = PanoramaxImageProvider.knownMeta[id] | ||||
|         if (cached) { | ||||
|             if (new Date().getTime() - cached.time.getTime() < 1000) { | ||||
|                 return { data: cached.data, url: undefined } | ||||
|             } | ||||
|         } | ||||
|     private async getInfoForUncached(id: string) { | ||||
|         try { | ||||
|             return await this.getInfoFromMapComplete(id) | ||||
|         } catch (e) { | ||||
|  | @ -125,6 +116,25 @@ export default class PanoramaxImageProvider extends ImageProvider { | |||
|         return undefined | ||||
|     } | ||||
| 
 | ||||
|     private async getInfoFor(id: string): Promise<{ data: ImageData; url: string }> { | ||||
|         if (!id.match(/^[a-zA-Z0-9-]+$/)) { | ||||
|             return undefined | ||||
|         } | ||||
|         const cached = PanoramaxImageProvider.knownMeta[id] | ||||
|         if (cached) { | ||||
|             if (new Date().getTime() - cached.time.getTime() < 5000) { | ||||
|                 return await cached.data | ||||
|             } | ||||
|         } | ||||
|         const promise: Promise<{ data: ImageData; url: string }> = this.getInfoForUncached(id) | ||||
|         PanoramaxImageProvider.knownMeta[id] = { | ||||
|             time: new Date(), | ||||
|             data: promise | ||||
|         } | ||||
|         return await promise | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public async ExtractUrls(key: string, value: string): Promise<ProvidedImage[]> { | ||||
|         if (!Panoramax.isId(value)) { | ||||
|             return undefined | ||||
|  | @ -139,7 +149,7 @@ export default class PanoramaxImageProvider extends ImageProvider { | |||
| 
 | ||||
|     getRelevantUrls(tags: Record<string, string>, prefixes: string[]): Store<ProvidedImage[]> { | ||||
|         const source = UIEventSource.FromPromise(super.getRelevantUrlsFor(tags, prefixes)) | ||||
| 
 | ||||
|         console.trace("Getting relevant URLS for panoramax yielded", source.data) | ||||
|         function hasLoading(data: ProvidedImage[]) { | ||||
|             if (data === undefined) { | ||||
|                 return true | ||||
|  |  | |||
|  | @ -172,7 +172,7 @@ class ImagesFromPanoramaxFetcher implements ImageFetcher { | |||
|         "https://panoramax.mapcomplete.org", | ||||
|     ] | ||||
| 
 | ||||
|     constructor(url?: string, radius: number = 100) { | ||||
|     constructor(url?: string, radius: number = 50) { | ||||
|         this._radius = radius | ||||
|         if (url) { | ||||
|             this._panoramax = new Panoramax(url) | ||||
|  | @ -182,12 +182,11 @@ class ImagesFromPanoramaxFetcher implements ImageFetcher { | |||
|     } | ||||
| 
 | ||||
|     public async fetchImages(lat: number, lon: number): Promise<P4CPicture[]> { | ||||
|         const bboxObj = new BBox([ | ||||
|             GeoOperations.destination([lon, lat], this._radius * Math.sqrt(2), -45), | ||||
|             GeoOperations.destination([lon, lat], this._radius * Math.sqrt(2), 135), | ||||
|         ]) | ||||
|         const bbox: [number, number, number, number] = bboxObj.toLngLatFlat() | ||||
|         const images = await this._panoramax.search({ bbox, limit: 1000 }) | ||||
|         const images = await this._panoramax.search({ | ||||
|             place: [lon, lat], | ||||
|             place_distance: this._radius ?? 50, | ||||
|             limit: 50 | ||||
|         }) | ||||
| 
 | ||||
|         return images.map((i) => { | ||||
|             const [lng, lat] = i.geometry.coordinates | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <script lang="ts"> | ||||
|   import { LicenseInfo } from "../../Logic/ImageProviders/LicenseInfo" | ||||
|   import type { ProvidedImage } from "../../Logic/ImageProviders/ImageProvider" | ||||
|   import { Store, UIEventSource } from "../../Logic/UIEventSource" | ||||
|   import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource" | ||||
|   import ToSvelte from "../Base/ToSvelte.svelte" | ||||
|   import { EyeIcon } from "@rgossiaux/svelte-heroicons/solid" | ||||
|   import Tr from "../Base/Tr.svelte" | ||||
|  | @ -13,7 +13,7 @@ | |||
|   export let image: Partial<ProvidedImage> & { id: string; url: string } | ||||
|   export let attributionFormat: "minimal" | "medium" | "large" = "medium" | ||||
| 
 | ||||
|   let license: Store<LicenseInfo> = UIEventSource.FromPromise( | ||||
|   let license: Store<LicenseInfo> = image.license ? new ImmutableStore(image.license) : UIEventSource.FromPromise( | ||||
|     image.provider?.DownloadAttribution(image) | ||||
|   ) | ||||
|   let icon = image.provider?.SourceIcon(image) | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ | |||
|   import { Utils } from "../../Utils" | ||||
|   import ThemeViewState from "../../Models/ThemeViewState" | ||||
|   import { MenuState } from "../../Models/MenuState" | ||||
|   import { LicenseInfo } from "../../Logic/ImageProviders/LicenseInfo" | ||||
| 
 | ||||
|   export let tags: UIEventSource<OsmTags> | ||||
|   export let state: ThemeViewState | ||||
|  | @ -36,7 +37,13 @@ | |||
|     } | ||||
|   }) | ||||
|   const t = Translations.t.image.nearby | ||||
|   const providedImage: ProvidedImage = { | ||||
|   let license: LicenseInfo = { | ||||
|     artist: image.author, | ||||
|     license: image.license, | ||||
|     date: new Date(image.date), | ||||
|     informationLocation: image.detailsUrl | ||||
|   } | ||||
|   let providedImage: ProvidedImage = { | ||||
|     url: image.thumbUrl ?? image.pictureUrl, | ||||
|     url_hd: image.pictureUrl, | ||||
|     key: undefined, | ||||
|  | @ -44,6 +51,7 @@ | |||
|     date: new Date(image.date), | ||||
|     id: Object.values(image.osmTags)[0], | ||||
|     isSpherical: image.details.isSpherical, | ||||
|     license | ||||
|   } | ||||
| 
 | ||||
|   async function applyLink(isLinked: boolean) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue