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