Chore: improve typing

This commit is contained in:
Pieter Vander Vennet 2025-04-09 17:10:33 +02:00
parent d01f830632
commit 01f1fbf89a
5 changed files with 38 additions and 14 deletions

View file

@ -16,7 +16,7 @@ export class Mapillary extends ImageProvider {
"http://mapillary.com", "http://mapillary.com",
"https://mapillary.com", "https://mapillary.com",
"http://www.mapillary.com", "http://www.mapillary.com",
"https://www.mapillary.com", "https://www.mapillary.com"
] ]
defaultKeyPrefixes = ["mapillary", "image"] defaultKeyPrefixes = ["mapillary", "image"]
@ -69,7 +69,7 @@ export class Mapillary extends ImageProvider {
lat: location?.lat, lat: location?.lat,
lng: location?.lon, lng: location?.lon,
z: location === undefined ? undefined : Math.max((zoom ?? 2) - 1, 1), z: location === undefined ? undefined : Math.max((zoom ?? 2) - 1, 1),
pKey, pKey
} }
const baselink = `https://www.mapillary.com/app/?` const baselink = `https://www.mapillary.com/app/?`
const paramsStr = Utils.NoNull( const paramsStr = Utils.NoNull(
@ -82,6 +82,8 @@ export class Mapillary extends ImageProvider {
/** /**
* Returns the correct key for API v4.0 * Returns the correct key for API v4.0
*
* Mapillary.ExtractKeyFromURL("999924810651016") // => 999924810651016
*/ */
private static ExtractKeyFromURL(value: string): number { private static ExtractKeyFromURL(value: string): number {
let key: string let key: string
@ -144,7 +146,9 @@ export class Mapillary extends ImageProvider {
mapillaryId + mapillaryId +
"?fields=thumb_1024_url,thumb_original_url,captured_at,creator&access_token=" + "?fields=thumb_1024_url,thumb_original_url,captured_at,creator&access_token=" +
Constants.mapillary_client_token_v4 Constants.mapillary_client_token_v4
const response = await Utils.downloadJsonCached(metadataUrl, 60 * 60) const response = await Utils.downloadJsonCached<{
thumb_1024_url: string, thumb_original_url: string, captured_at, creator: string
}>(metadataUrl, 60 * 60)
const license = new LicenseInfo() const license = new LicenseInfo()
license.artist = response["creator"]["username"] license.artist = response["creator"]["username"]
@ -164,9 +168,13 @@ export class Mapillary extends ImageProvider {
const metadataUrl = const metadataUrl =
"https://graph.mapillary.com/" + "https://graph.mapillary.com/" +
mapillaryId + mapillaryId +
"?fields=thumb_1024_url,thumb_original_url,captured_at,compass_angle,geometry,creator&access_token=" + "?fields=thumb_1024_url,thumb_original_url,captured_at,compass_angle,geometry,creator,camera_type&access_token=" +
Constants.mapillary_client_token_v4 Constants.mapillary_client_token_v4
const response = await Utils.downloadJsonCached(metadataUrl, 60 * 60) const response = await Utils.downloadJsonCached<{
thumb_1024_url: string, thumb_original_url: string, captured_at,
compass_angle: number,
creator: string
}>(metadataUrl, 60 * 60)
const url = <string>response["thumb_1024_url"] const url = <string>response["thumb_1024_url"]
const url_hd = <string>response["thumb_original_url"] const url_hd = <string>response["thumb_original_url"]
const date = new Date() const date = new Date()

View file

@ -131,7 +131,8 @@ export default class PanoramaxImageProvider extends ImageProvider {
} }
public async getInfo(hash: string): Promise<ProvidedImage> { public async getInfo(hash: string): Promise<ProvidedImage> {
return await this.getInfoFor(hash).then((r) => this.featureToImage(<any>r)) const r: { data: ImageData; url: string } = await this.getInfoFor(hash)
return this.featureToImage(r)
} }
getRelevantUrls(tags: Record<string, string>, prefixes: string[]): Store<ProvidedImage[]> { getRelevantUrls(tags: Record<string, string>, prefixes: string[]): Store<ProvidedImage[]> {

View file

@ -5,7 +5,6 @@ import Wikidata from "../Web/Wikidata"
import SvelteUIElement from "../../UI/Base/SvelteUIElement" import SvelteUIElement from "../../UI/Base/SvelteUIElement"
import * as Wikidata_icon from "../../assets/svg/Wikidata.svelte" import * as Wikidata_icon from "../../assets/svg/Wikidata.svelte"
import { Utils } from "../../Utils" import { Utils } from "../../Utils"
import { ImmutableStore, Store, Stores, UIEventSource } from "../UIEventSource"
export class WikidataImageProvider extends ImageProvider { export class WikidataImageProvider extends ImageProvider {
public static readonly singleton = new WikidataImageProvider() public static readonly singleton = new WikidataImageProvider()
@ -64,7 +63,7 @@ export class WikidataImageProvider extends ImageProvider {
return [].concat(...resolved) return [].concat(...resolved)
} }
public DownloadAttribution(_): Promise<any> { public DownloadAttribution(): Promise<undefined> {
throw new Error("Method not implemented; shouldn't be needed!") throw new Error("Method not implemented; shouldn't be needed!")
} }
} }

View file

@ -37,8 +37,10 @@ export class Stores {
*/ */
public static FromPromise<T>(promise: Promise<T>): Store<T | undefined> { public static FromPromise<T>(promise: Promise<T>): Store<T | undefined> {
const src = new UIEventSource<T>(undefined) const src = new UIEventSource<T>(undefined)
promise?.then((d) => src.setData(d)) promise?.catch((err): undefined => {
promise?.catch((err) => console.warn("Promise failed:", err)) console.warn("Promise failed:", err)
return undefined
})?.then((d) => src.setData(d))
return src return src
} }
@ -108,7 +110,6 @@ export class Stores {
public static fromArray<T>(sources: ReadonlyArray<UIEventSource<T>>): UIEventSource<T[]> { public static fromArray<T>(sources: ReadonlyArray<UIEventSource<T>>): UIEventSource<T[]> {
const src = new UIEventSource<T[]>(sources.map(s => s.data)) const src = new UIEventSource<T[]>(sources.map(s => s.data))
for (let i = 0; i < sources.length; i++) { for (let i = 0; i < sources.length; i++) {
sources[i].addCallback(content => { sources[i].addCallback(content => {
src.data[i] = content src.data[i] = content
@ -120,7 +121,17 @@ export class Stores {
sources[i].setData(contents[i]) sources[i].setData(contents[i])
} }
}) })
return src
}
public static fromStoresArray<T>(sources: ReadonlyArray<Store<T>>): Store<T[]> {
const src = new UIEventSource<T[]>(sources.map(s => s.data))
for (let i = 0; i < sources.length; i++) {
sources[i].addCallback(content => {
src.data[i] = content
src.ping()
})
}
return src return src
} }
} }
@ -388,7 +399,8 @@ export class ImmutableStore<T> extends Store<T> {
this.data = data this.data = data
} }
private static readonly pass: () => void = () => {} private static readonly pass: () => void = () => {
}
addCallback(_: (data: T) => void): () => void { addCallback(_: (data: T) => void): () => void {
// pass: data will never change // pass: data will never change
@ -666,7 +678,8 @@ class MappedStore<TIn, T> extends Store<T> {
} }
export class UIEventSource<T> extends Store<T> implements Writable<T> { export class UIEventSource<T> extends Store<T> implements Writable<T> {
private static readonly pass: () => void = () => {} private static readonly pass: () => void = () => {
}
public data: T public data: T
_callbacks: ListenerTracker<T> = new ListenerTracker<T>() _callbacks: ListenerTracker<T> = new ListenerTracker<T>()

View file

@ -332,9 +332,12 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
* @param toKey * @param toKey
* @constructor * @constructor
*/ */
public static DedupOnId<T>(arr: T[], toKey: (t: T) => string): T[] { public static DedupOnId<T = { id: string }>(arr: T[], toKey?: (t: T) => string): T[] {
const uniq: T[] = [] const uniq: T[] = []
const seen = new Set<string>() const seen = new Set<string>()
if (toKey === undefined) {
toKey = (item) => item["id"]
}
for (const img of arr) { for (const img of arr) {
if (!img) { if (!img) {
continue continue