diff --git a/langs/en.json b/langs/en.json index 28dded7a2..923021a67 100644 --- a/langs/en.json +++ b/langs/en.json @@ -561,6 +561,7 @@ "seeNearby": "Browse nearby pictures", "title": "Nearby streetview imagery" }, + "openOnWebsite": "Open this image on {name}", "panoramax": { "deletionRequested": "The report has been sent. A moderator will look to it shortly", "freeform": "Is there other relevant information?", diff --git a/src/Logic/ImageProviders/GenericImageProvider.ts b/src/Logic/ImageProviders/GenericImageProvider.ts index 34d1417f4..c3e6a0c34 100644 --- a/src/Logic/ImageProviders/GenericImageProvider.ts +++ b/src/Logic/ImageProviders/GenericImageProvider.ts @@ -33,6 +33,7 @@ export default class GenericImageProvider extends ImageProvider { url: value, provider: this, id: value, + isSpherical: undefined }, ] } @@ -45,7 +46,11 @@ export default class GenericImageProvider extends ImageProvider { return undefined } - getPanoramaInfo(image: { id: string }): undefined { + getPanoramaInfo(): undefined { return undefined } + + visitUrl(image: { url: string }): string | undefined { + return image.url + } } diff --git a/src/Logic/ImageProviders/ImageProvider.ts b/src/Logic/ImageProviders/ImageProvider.ts index 690842bfa..64254a76d 100644 --- a/src/Logic/ImageProviders/ImageProvider.ts +++ b/src/Logic/ImageProviders/ImageProvider.ts @@ -125,6 +125,11 @@ export default abstract class ImageProvider { public abstract apiUrls(): string[] + /** + * URL to visit the image on the original website + */ + public abstract visitUrl(image: Partial, location?: { lon: number, lat: number }): string | undefined + public abstract getPanoramaInfo(image: { id: string }): Promise> | undefined diff --git a/src/Logic/ImageProviders/Imgur.ts b/src/Logic/ImageProviders/Imgur.ts index cf6314f48..8b18be9ff 100644 --- a/src/Logic/ImageProviders/Imgur.ts +++ b/src/Logic/ImageProviders/Imgur.ts @@ -118,7 +118,11 @@ export class Imgur extends ImageProvider { return license } - getPanoramaInfo(image: { id: string }): undefined { + getPanoramaInfo(): undefined { + return undefined + } + + visitUrl(): string | undefined { return undefined } } diff --git a/src/Logic/ImageProviders/Mapillary.ts b/src/Logic/ImageProviders/Mapillary.ts index 9b77a8ba4..52b5c7195 100644 --- a/src/Logic/ImageProviders/Mapillary.ts +++ b/src/Logic/ImageProviders/Mapillary.ts @@ -8,6 +8,7 @@ import MapillaryIcon from "./MapillaryIcon.svelte" import { Feature, Point } from "geojson" export class Mapillary extends ImageProvider { + public static readonly singleton = new Mapillary() public readonly name = "Mapillary" @@ -237,4 +238,11 @@ export class Mapillary extends ImageProvider { 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) + } } diff --git a/src/Logic/ImageProviders/Panoramax.ts b/src/Logic/ImageProviders/Panoramax.ts index 0b6dc4e80..4763e3110 100644 --- a/src/Logic/ImageProviders/Panoramax.ts +++ b/src/Logic/ImageProviders/Panoramax.ts @@ -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) { PanoramaxImageProvider.knownMeta[meta.id] = { data: Promise.resolve({ data: meta, url }), time: new Date() } } diff --git a/src/Logic/ImageProviders/WikidataImageProvider.ts b/src/Logic/ImageProviders/WikidataImageProvider.ts index e5fa7e9fd..fa447f52f 100644 --- a/src/Logic/ImageProviders/WikidataImageProvider.ts +++ b/src/Logic/ImageProviders/WikidataImageProvider.ts @@ -71,4 +71,8 @@ export class WikidataImageProvider extends ImageProvider { public getPanoramaInfo(image: { id: string }): Promise> { return undefined } + + visitUrl(image: Partial, location?: { lon: number; lat: number }): string | undefined { + return undefined + } } diff --git a/src/Logic/ImageProviders/WikimediaImageProvider.ts b/src/Logic/ImageProviders/WikimediaImageProvider.ts index d2035f017..65a74165b 100644 --- a/src/Logic/ImageProviders/WikimediaImageProvider.ts +++ b/src/Logic/ImageProviders/WikimediaImageProvider.ts @@ -193,7 +193,11 @@ export class WikimediaImageProvider extends ImageProvider { } } - getPanoramaInfo(image: { id: string }): Promise> | undefined { + getPanoramaInfo(): Promise> | undefined { + return undefined + } + + visitUrl(): string | undefined { return undefined } } diff --git a/src/Models/RasterLayers.ts b/src/Models/RasterLayers.ts index 7496f563a..01547cc11 100644 --- a/src/Models/RasterLayers.ts +++ b/src/Models/RasterLayers.ts @@ -117,7 +117,7 @@ export class AvailableRasterLayers { ) ) return Stores.ListStabilized( - availableLayersBboxes.map( + availableLayersBboxes.mapD( (eliPolygons) => { const loc = location.data const lonlat: [number, number] = [loc?.lon ?? 0, loc?.lat ?? 0] diff --git a/src/UI/Image/AttributedImage.svelte b/src/UI/Image/AttributedImage.svelte index ea202fca5..8034e23b8 100644 --- a/src/UI/Image/AttributedImage.svelte +++ b/src/UI/Image/AttributedImage.svelte @@ -22,6 +22,7 @@ import { MenuState } from "../../Models/MenuState" import ThemeViewState from "../../Models/ThemeViewState" import Panorama360 from "../../assets/svg/Panorama360.svelte" + import { ExternalLinkIcon } from "@rgossiaux/svelte-heroicons/solid" export let image: Partial & { id: string; url: string } let fallbackImage: string = undefined @@ -40,6 +41,7 @@ | Store[]> = [] let loaded = false + let visitUrl = image.provider.visitUrl(image) let showBigPreview = new UIEventSource(false) onDestroy( showBigPreview.addCallbackAndRun((shown) => { @@ -110,9 +112,13 @@ on:mouseenter={() => highlight()} on:mouseleave={() => highlight(false)} > - {#if $$slots["dot-menu-actions"]} + {#if $$slots["dot-menu-actions"] || visitUrl !== undefined} + + + + {/if} {#if !loaded}