forked from MapComplete/MapComplete
Improvements in loading images
This commit is contained in:
parent
634f4e316a
commit
8b870474d7
9 changed files with 61 additions and 31 deletions
|
@ -46,7 +46,7 @@ export default class SelectedFeatureHandler {
|
|||
// IF the selected element changes, set the hash correctly
|
||||
state.selectedElement.addCallback(feature => {
|
||||
if (feature === undefined) {
|
||||
if (SelectedFeatureHandler._no_trigger_on.has(hash.data)) {
|
||||
if (!SelectedFeatureHandler._no_trigger_on.has(hash.data)) {
|
||||
hash.setData("")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ export default class AllImageProviders {
|
|||
Mapillary.singleton,
|
||||
WikidataImageProvider.singleton,
|
||||
WikimediaImageProvider.singleton,
|
||||
new GenericImageProvider([].concat(...Imgur.defaultValuePrefix, WikimediaImageProvider.commonsPrefix))]
|
||||
new GenericImageProvider([].concat(...Imgur.defaultValuePrefix, WikimediaImageProvider.commonsPrefix, ...Mapillary.valuePrefixes))]
|
||||
|
||||
|
||||
private static _cache: Map<string, UIEventSource<ProvidedImage[]>> = new Map<string, UIEventSource<ProvidedImage[]>>()
|
||||
|
@ -37,8 +37,18 @@ export default class AllImageProviders {
|
|||
this._cache.set(id, source)
|
||||
const allSources = []
|
||||
for (const imageProvider of AllImageProviders.ImageAttributionSource) {
|
||||
|
||||
let prefixes = imageProvider.defaultKeyPrefixes
|
||||
if(imagePrefix !== undefined){
|
||||
prefixes = [...prefixes]
|
||||
if(prefixes.indexOf("image") >= 0){
|
||||
prefixes.splice(prefixes.indexOf("image"), 1)
|
||||
}
|
||||
prefixes.push(imagePrefix)
|
||||
}
|
||||
|
||||
const singleSource = imageProvider.GetRelevantUrls(tags, {
|
||||
prefixes: imagePrefix !== undefined ? [imagePrefix] : undefined
|
||||
prefixes: prefixes
|
||||
})
|
||||
allSources.push(singleSource)
|
||||
singleSource.addCallbackAndRunD(_ => {
|
||||
|
|
|
@ -8,7 +8,7 @@ export interface ProvidedImage {
|
|||
|
||||
export default abstract class ImageProvider {
|
||||
|
||||
protected abstract readonly defaultKeyPrefixes : string[]
|
||||
public abstract readonly defaultKeyPrefixes : string[] = ["mapillary", "image"]
|
||||
|
||||
private _cache = new Map<string, UIEventSource<LicenseInfo>>()
|
||||
|
||||
|
@ -33,6 +33,9 @@ export default abstract class ImageProvider {
|
|||
prefixes?: string[]
|
||||
}):UIEventSource<ProvidedImage[]> {
|
||||
const prefixes = options?.prefixes ?? this.defaultKeyPrefixes
|
||||
if(prefixes === undefined){
|
||||
throw "The image provider"+this.constructor.name+" doesn't define `defaultKeyPrefixes`"
|
||||
}
|
||||
const relevantUrls = new UIEventSource<{ url: string; key: string; provider: ImageProvider }[]>([])
|
||||
const seenValues = new Set<string>()
|
||||
allTags.addCallbackAndRunD(tags => {
|
||||
|
@ -45,10 +48,15 @@ export default abstract class ImageProvider {
|
|||
continue
|
||||
}
|
||||
seenValues.add(value)
|
||||
|
||||
this.ExtractUrls(key, value).then(promises => {
|
||||
for (const promise of promises) {
|
||||
for (const promise of promises ?? []) {
|
||||
if(promise === undefined){
|
||||
continue
|
||||
}
|
||||
promise.then(providedImage => {
|
||||
if(providedImage === undefined){
|
||||
return
|
||||
}
|
||||
relevantUrls.data.push(providedImage)
|
||||
relevantUrls.ping()
|
||||
})
|
||||
|
|
|
@ -5,24 +5,25 @@ import Svg from "../../Svg";
|
|||
import {Utils} from "../../Utils";
|
||||
import {LicenseInfo} from "./LicenseInfo";
|
||||
import Constants from "../../Models/Constants";
|
||||
import {fail} from "assert";
|
||||
|
||||
export class Mapillary extends ImageProvider {
|
||||
|
||||
defaultKeyPrefixes = ["mapillary"]
|
||||
defaultKeyPrefixes = ["mapillary","image"]
|
||||
|
||||
public static readonly singleton = new Mapillary();
|
||||
|
||||
private static readonly v4_cached_urls = new Map<string, UIEventSource<string>>();
|
||||
private static readonly valuePrefix = "https://a.mapillary.com"
|
||||
public static readonly valuePrefixes = [Mapillary.valuePrefix, "http://mapillary.com","https://mapillary.com"]
|
||||
|
||||
private constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
private static ExtractKeyFromURL(value: string): {
|
||||
private static ExtractKeyFromURL(value: string, failIfNoMath = false): {
|
||||
key: string,
|
||||
isApiv4?: boolean
|
||||
} {
|
||||
if (value.startsWith("https://a.mapillary.com")) {
|
||||
if (value.startsWith(Mapillary.valuePrefix)) {
|
||||
const key = value.substring(0, value.lastIndexOf("?")).substring(value.lastIndexOf("/") + 1)
|
||||
return {key: key, isApiv4: !isNaN(Number(key))};
|
||||
}
|
||||
|
@ -47,8 +48,11 @@ export class Mapillary extends ImageProvider {
|
|||
if (matchApi !== null) {
|
||||
return {key: matchApi[1]};
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(failIfNoMath){
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {key: value, isApiv4: !isNaN(Number(value))};
|
||||
}
|
||||
|
||||
|
@ -61,7 +65,12 @@ export class Mapillary extends ImageProvider {
|
|||
}
|
||||
|
||||
private async PrepareUrlAsync(key: string, value: string): Promise<ProvidedImage> {
|
||||
const keyV = Mapillary.ExtractKeyFromURL(value)
|
||||
const failIfNoMatch = key.indexOf("mapillary") < 0
|
||||
const keyV = Mapillary.ExtractKeyFromURL(value, failIfNoMatch)
|
||||
if(keyV === undefined){
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!keyV.isApiv4) {
|
||||
const url = `https://images.mapillary.com/${keyV.key}/thumb-640.jpg?client_id=${Constants.mapillary_client_token_v3}`
|
||||
return {
|
||||
|
@ -70,10 +79,8 @@ export class Mapillary extends ImageProvider {
|
|||
key: key
|
||||
}
|
||||
} else {
|
||||
const key = keyV.key;
|
||||
const metadataUrl = 'https://graph.mapillary.com/' + key + '?fields=thumb_1024_url&&access_token=' + Constants.mapillary_client_token_v4;
|
||||
const source = new UIEventSource<string>(undefined)
|
||||
Mapillary.v4_cached_urls.set(key, source)
|
||||
const mapillaryId = keyV.key;
|
||||
const metadataUrl = 'https://graph.mapillary.com/' + mapillaryId + '?fields=thumb_1024_url&&access_token=' + Constants.mapillary_client_token_v4;
|
||||
const response = await Utils.downloadJson(metadataUrl)
|
||||
const url = <string> response["thumb_1024_url"];
|
||||
return {
|
||||
|
|
|
@ -26,6 +26,10 @@ export class WikidataImageProvider extends ImageProvider {
|
|||
if (value.startsWith(wikidataUrl)) {
|
||||
value = value.substring(wikidataUrl.length)
|
||||
}
|
||||
if(value.startsWith("http")){
|
||||
// Probably some random link in the image field - we skip it
|
||||
return undefined
|
||||
}
|
||||
if (!value.startsWith("Q")) {
|
||||
value = "Q" + value
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ export class WikimediaImageProvider extends ImageProvider {
|
|||
if (continueParameter !== undefined) {
|
||||
url = `${url}&cmcontinue=${continueParameter}`;
|
||||
}
|
||||
console.log("Loading a wikimedia category: ", url)
|
||||
console.debug("Loading a wikimedia category: ", url)
|
||||
const response = await Utils.downloadJson(url)
|
||||
const members = response.query?.categorymembers ?? [];
|
||||
const imageOverview: string[] = members.map(member => member.title);
|
||||
|
@ -55,7 +55,7 @@ export class WikimediaImageProvider extends ImageProvider {
|
|||
}
|
||||
|
||||
if (maxLoad - imageOverview.length <= 0) {
|
||||
console.log(`Recursive wikimedia category load stopped for ${categoryName}`)
|
||||
console.debug(`Recursive wikimedia category load stopped for ${categoryName}`)
|
||||
return imageOverview;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import Attribution from "./Attribution";
|
|||
import Img from "../Base/Img";
|
||||
import {ProvidedImage} from "../../Logic/ImageProviders/ImageProvider";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import {Mapillary} from "../../Logic/ImageProviders/Mapillary";
|
||||
|
||||
|
||||
export class AttributedImage extends Combine {
|
||||
|
@ -10,7 +11,9 @@ export class AttributedImage extends Combine {
|
|||
constructor(imageInfo: ProvidedImage) {
|
||||
let img: BaseUIElement;
|
||||
let attr: BaseUIElement
|
||||
img = new Img(imageInfo.url);
|
||||
img = new Img(imageInfo.url, false, {
|
||||
fallbackImage: imageInfo.provider === Mapillary.singleton ? "./assets/svg/blocked.svg" : undefined
|
||||
});
|
||||
attr = new Attribution(imageInfo.provider.GetAttributionFor(imageInfo.url),
|
||||
imageInfo.provider.SourceIcon(),
|
||||
)
|
||||
|
|
|
@ -13,9 +13,7 @@ export class ImageCarousel extends Toggle {
|
|||
const uiElements = images.map((imageURLS: { key: string, url: string, provider: ImageProvider }[]) => {
|
||||
const uiElements: BaseUIElement[] = [];
|
||||
for (const url of imageURLS) {
|
||||
|
||||
try {
|
||||
|
||||
let image = new AttributedImage(url)
|
||||
|
||||
if (url.key !== undefined) {
|
||||
|
|
|
@ -912,14 +912,14 @@ video {
|
|||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.mb-1 {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.box-border {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
@ -1156,14 +1156,14 @@ video {
|
|||
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
}
|
||||
|
||||
.cursor-wait {
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cursor-wait {
|
||||
cursor: wait;
|
||||
}
|
||||
|
||||
.resize {
|
||||
resize: both;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue