Feature: add link to the original provider, see #2387

This commit is contained in:
Pieter Vander Vennet 2025-04-23 21:35:43 +02:00
parent 991925ba35
commit 3e5b1444cc
10 changed files with 51 additions and 5 deletions

View file

@ -561,6 +561,7 @@
"seeNearby": "Browse nearby pictures", "seeNearby": "Browse nearby pictures",
"title": "Nearby streetview imagery" "title": "Nearby streetview imagery"
}, },
"openOnWebsite": "Open this image on {name}",
"panoramax": { "panoramax": {
"deletionRequested": "The report has been sent. A moderator will look to it shortly", "deletionRequested": "The report has been sent. A moderator will look to it shortly",
"freeform": "Is there other relevant information?", "freeform": "Is there other relevant information?",

View file

@ -33,6 +33,7 @@ export default class GenericImageProvider extends ImageProvider {
url: value, url: value,
provider: this, provider: this,
id: value, id: value,
isSpherical: undefined
}, },
] ]
} }
@ -45,7 +46,11 @@ export default class GenericImageProvider extends ImageProvider {
return undefined return undefined
} }
getPanoramaInfo(image: { id: string }): undefined { getPanoramaInfo(): undefined {
return undefined return undefined
} }
visitUrl(image: { url: string }): string | undefined {
return image.url
}
} }

View file

@ -125,6 +125,11 @@ export default abstract class ImageProvider {
public abstract apiUrls(): string[] public abstract apiUrls(): string[]
/**
* URL to visit the image on the original website
*/
public abstract visitUrl(image: Partial<ProvidedImage>, location?: { lon: number, lat: number }): string | undefined
public abstract getPanoramaInfo(image: { public abstract getPanoramaInfo(image: {
id: string id: string
}): Promise<Feature<Point, PanoramaView>> | undefined }): Promise<Feature<Point, PanoramaView>> | undefined

View file

@ -118,7 +118,11 @@ export class Imgur extends ImageProvider {
return license return license
} }
getPanoramaInfo(image: { id: string }): undefined { getPanoramaInfo(): undefined {
return undefined
}
visitUrl(): string | undefined {
return undefined return undefined
} }
} }

View file

@ -8,6 +8,7 @@ import MapillaryIcon from "./MapillaryIcon.svelte"
import { Feature, Point } from "geojson" import { Feature, Point } from "geojson"
export class Mapillary extends ImageProvider { export class Mapillary extends ImageProvider {
public static readonly singleton = new Mapillary() public static readonly singleton = new Mapillary()
public readonly name = "Mapillary" public readonly name = "Mapillary"
@ -237,4 +238,11 @@ export class Mapillary extends ImageProvider {
lon: geometry.coordinates[0], lon: geometry.coordinates[0],
} }
} }
public visitUrl(image: { id: string }, location?: { lon: number, lat: number }): (string | undefined) {
if (!image.id) {
return
}
return Mapillary.createLink(location, 17, image.id)
}
} }

View file

@ -45,6 +45,15 @@ export default class PanoramaxImageProvider extends ImageProvider {
) )
} }
visitUrl(img: { id: string, url: string }, location?: { lon: number, lat: number }): string | undefined {
const host = "https://" + new URL(img.url).host
const p = new Panoramax(host)
return p.createViewLink({
imageId: img?.id,
location
})
}
public addKnownMeta(meta: ImageData, url?: string) { public addKnownMeta(meta: ImageData, url?: string) {
PanoramaxImageProvider.knownMeta[meta.id] = { data: Promise.resolve({ data: meta, url }), time: new Date() } PanoramaxImageProvider.knownMeta[meta.id] = { data: Promise.resolve({ data: meta, url }), time: new Date() }
} }

View file

@ -71,4 +71,8 @@ export class WikidataImageProvider extends ImageProvider {
public getPanoramaInfo(image: { id: string }): Promise<Feature<Point, PanoramaView>> { public getPanoramaInfo(image: { id: string }): Promise<Feature<Point, PanoramaView>> {
return undefined return undefined
} }
visitUrl(image: Partial<ProvidedImage>, location?: { lon: number; lat: number }): string | undefined {
return undefined
}
} }

View file

@ -193,7 +193,11 @@ export class WikimediaImageProvider extends ImageProvider {
} }
} }
getPanoramaInfo(image: { id: string }): Promise<Feature<Point, PanoramaView>> | undefined { getPanoramaInfo(): Promise<Feature<Point, PanoramaView>> | undefined {
return undefined
}
visitUrl(): string | undefined {
return undefined return undefined
} }
} }

View file

@ -117,7 +117,7 @@ export class AvailableRasterLayers {
) )
) )
return Stores.ListStabilized( return Stores.ListStabilized(
availableLayersBboxes.map( availableLayersBboxes.mapD(
(eliPolygons) => { (eliPolygons) => {
const loc = location.data const loc = location.data
const lonlat: [number, number] = [loc?.lon ?? 0, loc?.lat ?? 0] const lonlat: [number, number] = [loc?.lon ?? 0, loc?.lat ?? 0]

View file

@ -22,6 +22,7 @@
import { MenuState } from "../../Models/MenuState" import { MenuState } from "../../Models/MenuState"
import ThemeViewState from "../../Models/ThemeViewState" import ThemeViewState from "../../Models/ThemeViewState"
import Panorama360 from "../../assets/svg/Panorama360.svelte" import Panorama360 from "../../assets/svg/Panorama360.svelte"
import { ExternalLinkIcon } from "@rgossiaux/svelte-heroicons/solid"
export let image: Partial<ProvidedImage> & { id: string; url: string } export let image: Partial<ProvidedImage> & { id: string; url: string }
let fallbackImage: string = undefined let fallbackImage: string = undefined
@ -40,6 +41,7 @@
| Store<Feature<Geometry, HotspotProperties>[]> = [] | Store<Feature<Geometry, HotspotProperties>[]> = []
let loaded = false let loaded = false
let visitUrl = image.provider.visitUrl(image)
let showBigPreview = new UIEventSource(false) let showBigPreview = new UIEventSource(false)
onDestroy( onDestroy(
showBigPreview.addCallbackAndRun((shown) => { showBigPreview.addCallbackAndRun((shown) => {
@ -110,9 +112,13 @@
on:mouseenter={() => highlight()} on:mouseenter={() => highlight()}
on:mouseleave={() => highlight(false)} on:mouseleave={() => highlight(false)}
> >
{#if $$slots["dot-menu-actions"]} {#if $$slots["dot-menu-actions"] || visitUrl !== undefined}
<DotMenu dotsPosition="top-0 left-0 absolute" hideBackground> <DotMenu dotsPosition="top-0 left-0 absolute" hideBackground>
<slot name="dot-menu-actions" /> <slot name="dot-menu-actions" />
<a href={visitUrl} target="_blank" rel="noopener">
<ExternalLinkIcon class="w-6" />
<Tr t={Translations.t.image.openOnWebsite.Subs(image.provider)} />
</a>
</DotMenu> </DotMenu>
{/if} {/if}
{#if !loaded} {#if !loaded}