diff --git a/Logic/Web/ImageAttributionSource.ts b/Logic/Web/ImageAttributionSource.ts new file mode 100644 index 0000000000..689a32c46c --- /dev/null +++ b/Logic/Web/ImageAttributionSource.ts @@ -0,0 +1,29 @@ +import {UIEventSource} from "../UIEventSource"; +import {LicenseInfo} from "./Wikimedia"; +import BaseUIElement from "../../UI/BaseUIElement"; + + +export default abstract class ImageAttributionSource { + + + private _cache = new Map>() + + GetAttributionFor(url: string): UIEventSource { + const cached = this._cache.get(url); + if (cached !== undefined) { + return cached; + } + const src = this.DownloadAttribution(url) + this._cache.set(url, src) + return src; + } + + + + public abstract SourceIcon(backlinkSource?: string) : BaseUIElement; + protected abstract DownloadAttribution(url: string): UIEventSource; + public PrepareUrl(value: string): string{ + return value; + } + +} \ No newline at end of file diff --git a/Logic/Web/Imgur.ts b/Logic/Web/Imgur.ts index d48771e112..a1ecd7eeed 100644 --- a/Logic/Web/Imgur.ts +++ b/Logic/Web/Imgur.ts @@ -1,16 +1,24 @@ // @ts-ignore import $ from "jquery" import {LicenseInfo} from "./Wikimedia"; +import ImageAttributionSource from "./ImageAttributionSource"; +import {UIEventSource} from "../UIEventSource"; +import BaseUIElement from "../../UI/BaseUIElement"; -export class Imgur { +export class Imgur extends ImageAttributionSource { + + public static readonly singleton = new Imgur(); + private constructor() { + super(); + } static uploadMultiple( title: string, description: string, blobs: FileList, handleSuccessfullUpload: ((imageURL: string) => void), allDone: (() => void), onFail: ((reason: string) => void), - offset:number = 0) { + offset: number = 0) { if (blobs.length == offset) { allDone(); @@ -32,56 +40,11 @@ export class Imgur { ); - } - - static getDescriptionOfImage(url: string, - handleDescription: ((license: LicenseInfo) => void)) { - - const hash = url.substr("https://i.imgur.com/".length).split(".jpg")[0]; - - const apiUrl = 'https://api.imgur.com/3/image/'+hash; - const apiKey = '7070e7167f0a25a'; - - const settings = { - async: true, - crossDomain: true, - processData: false, - contentType: false, - type: 'GET', - url: apiUrl, - headers: { - Authorization: 'Client-ID ' + apiKey, - Accept: 'application/json', - }, - }; - // @ts-ignore - $.ajax(settings).done(function (response) { - const descr: string = response.data.description ?? ""; - const data: any = {}; - for (const tag of descr.split("\n")) { - const kv = tag.split(":"); - const k = kv[0]; - const v = kv[1].replace("\r", ""); - data[k] = v; - } - - - const licenseInfo = new LicenseInfo(); - - licenseInfo.licenseShortName = data.license; - licenseInfo.artist = data.author; - - handleDescription(licenseInfo); - - }).fail((reason) => { - console.log("Getting metadata from to IMGUR failed", reason) - }); - } static uploadImage(title: string, description: string, blob, handleSuccessfullUpload: ((imageURL: string) => void), - onFail: (reason:string) => void) { + onFail: (reason: string) => void) { const apiUrl = 'https://api.imgur.com/3/image'; const apiKey = '7070e7167f0a25a'; @@ -119,4 +82,55 @@ export class Imgur { }); } + SourceIcon(): BaseUIElement { + return undefined; + } + + protected DownloadAttribution(url: string): UIEventSource { + const src = new UIEventSource(undefined) + + + const hash = url.substr("https://i.imgur.com/".length).split(".jpg")[0]; + + const apiUrl = 'https://api.imgur.com/3/image/' + hash; + const apiKey = '7070e7167f0a25a'; + + const settings = { + async: true, + crossDomain: true, + processData: false, + contentType: false, + type: 'GET', + url: apiUrl, + headers: { + Authorization: 'Client-ID ' + apiKey, + Accept: 'application/json', + }, + }; + // @ts-ignore + $.ajax(settings).done(function (response) { + const descr: string = response.data.description ?? ""; + const data: any = {}; + for (const tag of descr.split("\n")) { + const kv = tag.split(":"); + const k = kv[0]; + data[k] = kv[1].replace("\r", ""); + } + + + const licenseInfo = new LicenseInfo(); + + licenseInfo.licenseShortName = data.license; + licenseInfo.artist = data.author; + + src.setData(licenseInfo) + + }).fail((reason) => { + console.log("Getting metadata from to IMGUR failed", reason) + }); + + return src; + } + + } \ No newline at end of file diff --git a/Logic/Web/Mapillary.ts b/Logic/Web/Mapillary.ts index 048e637163..cad71f93b7 100644 --- a/Logic/Web/Mapillary.ts +++ b/Logic/Web/Mapillary.ts @@ -1,26 +1,57 @@ import $ from "jquery" import {LicenseInfo} from "./Wikimedia"; +import ImageAttributionSource from "./ImageAttributionSource"; +import BaseUIElement from "../../UI/BaseUIElement"; +import {UIEventSource} from "../UIEventSource"; +import Svg from "../../Svg"; -export class Mapillary { +export class Mapillary extends ImageAttributionSource { + public static readonly singleton = new Mapillary(); - static getDescriptionOfImage(key: string, - handleDescription: ((license: LicenseInfo) => void)) { - const url = `https://a.mapillary.com/v3/images/${key}?client_id=TXhLaWthQ1d4RUg0czVxaTVoRjFJZzowNDczNjUzNmIyNTQyYzI2` + private constructor() { + super(); + } - const settings = { - async: true, - type: 'GET', - url: url - }; - $.getJSON(url, function(data) { + private static ExtractKeyFromURL(value: string) { + if (value.startsWith("https://a.mapillary.com")) { + return value.substring(0, value.lastIndexOf("?")).substring(value.lastIndexOf("/") + 1); + } + const matchApi = value.match(/https?:\/\/images.mapillary.com\/([^/]*)/) + if (matchApi !== null) { + return matchApi[1]; + } + + if (value.toLowerCase().startsWith("https://www.mapillary.com/map/im/")) { + // Extract the key of the image + value = value.substring("https://www.mapillary.com/map/im/".length); + } + return value; + } + + SourceIcon(backlinkSource?: string): BaseUIElement { + return Svg.mapillary_svg(); + } + + PrepareUrl(value: string): string { + const key = Mapillary.ExtractKeyFromURL(value) + return `https://images.mapillary.com/${key}/thumb-640.jpg?client_id=TXhLaWthQ1d4RUg0czVxaTVoRjFJZzowNDczNjUzNmIyNTQyYzI2` + } + + protected DownloadAttribution(url: string): UIEventSource { + + const key = Mapillary.ExtractKeyFromURL(url) + const metadataURL = `https://a.mapillary.com/v3/images/${key}?client_id=TXhLaWthQ1d4RUg0czVxaTVoRjFJZzowNDczNjUzNmIyNTQyYzI2` + const source = new UIEventSource(undefined) + $.getJSON(metadataURL, function (data) { const license = new LicenseInfo(); license.artist = data.properties?.username; license.licenseShortName = "CC BY-SA 4.0"; license.license = "Creative Commons Attribution-ShareAlike 4.0 International License"; license.attributionRequired = true; - handleDescription(license); + source.setData(license); }) + return source } } \ No newline at end of file diff --git a/Logic/Web/Wikimedia.ts b/Logic/Web/Wikimedia.ts index bf68d22557..4668f35116 100644 --- a/Logic/Web/Wikimedia.ts +++ b/Logic/Web/Wikimedia.ts @@ -1,47 +1,28 @@ import * as $ from "jquery" +import ImageAttributionSource from "./ImageAttributionSource"; +import BaseUIElement from "../../UI/BaseUIElement"; +import Svg from "../../Svg"; +import {UIEventSource} from "../UIEventSource"; +import Link from "../../UI/Base/Link"; /** * This module provides endpoints for wikipedia/wikimedia and others */ -export class Wikimedia { +export class Wikimedia extends ImageAttributionSource { + + + public static readonly singleton = new Wikimedia(); + + private constructor() { + super(); + } - private static knownLicenses = {}; static ImageNameToUrl(filename: string, width: number = 500, height: number = 200): string { filename = encodeURIComponent(filename); return "https://commons.wikimedia.org/wiki/Special:FilePath/" + filename + "?width=" + width + "&height=" + height; } - static LicenseData(filename: string, handle: ((LicenseInfo) => void)): void { - if (filename in this.knownLicenses) { - return this.knownLicenses[filename]; - } - if (filename === "") { - return; - } - const url = "https://en.wikipedia.org/w/" + - "api.php?action=query&prop=imageinfo&iiprop=extmetadata&" + - "titles=" + filename + - "&format=json&origin=*"; - $.getJSON(url, function (data) { - const licenseInfo = new LicenseInfo(); - const license = data.query.pages[-1].imageinfo[0].extmetadata; - - licenseInfo.artist = license.Artist?.value; - licenseInfo.license = license.License?.value; - licenseInfo.copyrighted = license.Copyrighted?.value; - licenseInfo.attributionRequired = license.AttributionRequired?.value; - licenseInfo.usageTerms = license.UsageTerms?.value; - licenseInfo.licenseShortName = license.LicenseShortName?.value; - licenseInfo.credit = license.Credit?.value; - licenseInfo.description = license.ImageDescription?.value; - - Wikimedia.knownLicenses[filename] = licenseInfo; - handle(licenseInfo); - }); - - } - static GetCategoryFiles(categoryName: string, handleCategory: ((ImagesInCategory: ImagesInCategory) => void), alreadyLoaded = 0, continueParameter: { k: string, param: string } = undefined) { @@ -111,6 +92,71 @@ export class Wikimedia { }); } + private static ExtractFileName(url: string) { + if (!url.startsWith("http")) { + return url; + } + const path = new URL(url).pathname + return path.substring(path.lastIndexOf("/") + 1); + + } + + SourceIcon(backlink: string): BaseUIElement { + const img = Svg.wikimedia_commons_white_svg() + .SetStyle("width:2em;height: 2em"); + if (backlink === undefined) { + return img + } + + + return new Link(Svg.wikimedia_commons_white_img, + `https://commons.wikimedia.org/wiki/${backlink}`, true) + + + } + + PrepareUrl(value: string): string { + + if (value.toLowerCase().startsWith("https://commons.wikimedia.org/wiki/")) { + return value; + } + return Wikimedia.ImageNameToUrl(value, 500, 400) + .replace(/'/g, '%27'); + } + + protected DownloadAttribution(filename: string): UIEventSource { + + const source = new UIEventSource(undefined); + + filename = Wikimedia.ExtractFileName(filename) + + if (filename === "") { + return source; + } + + const url = "https://en.wikipedia.org/w/" + + "api.php?action=query&prop=imageinfo&iiprop=extmetadata&" + + "titles=" + filename + + "&format=json&origin=*"; + console.log("Getting attribution at ", url) + $.getJSON(url, function (data) { + const licenseInfo = new LicenseInfo(); + const license = data.query.pages[-1].imageinfo[0].extmetadata; + + licenseInfo.artist = license.Artist?.value; + licenseInfo.license = license.License?.value; + licenseInfo.copyrighted = license.Copyrighted?.value; + licenseInfo.attributionRequired = license.AttributionRequired?.value; + licenseInfo.usageTerms = license.UsageTerms?.value; + licenseInfo.licenseShortName = license.LicenseShortName?.value; + licenseInfo.credit = license.Credit?.value; + licenseInfo.description = license.ImageDescription?.value; + source.setData(licenseInfo); + }); + return source; + + } + } diff --git a/Svg.ts b/Svg.ts index 53889707c1..3f0ff50fe8 100644 --- a/Svg.ts +++ b/Svg.ts @@ -6,317 +6,317 @@ export default class Svg { public static SocialImageForeground = " image/svg+xml 010110010011010110010011  010110010011010110010011  " public static SocialImageForeground_img = Img.AsImageElement(Svg.SocialImageForeground) - public static SocialImageForeground_svg() { return new FixedUiElement(Svg.SocialImageForeground);} + public static SocialImageForeground_svg() { return new Img(Svg.SocialImageForeground, true);} public static SocialImageForeground_ui() { return new FixedUiElement(Svg.SocialImageForeground_img);} public static add = " image/svg+xml " public static add_img = Img.AsImageElement(Svg.add) - public static add_svg() { return new FixedUiElement(Svg.add);} + public static add_svg() { return new Img(Svg.add, true);} public static add_ui() { return new FixedUiElement(Svg.add_img);} public static addSmall = " image/svg+xml " public static addSmall_img = Img.AsImageElement(Svg.addSmall) - public static addSmall_svg() { return new FixedUiElement(Svg.addSmall);} + public static addSmall_svg() { return new Img(Svg.addSmall, true);} public static addSmall_ui() { return new FixedUiElement(Svg.addSmall_img);} public static ampersand = " image/svg+xml " public static ampersand_img = Img.AsImageElement(Svg.ampersand) - public static ampersand_svg() { return new FixedUiElement(Svg.ampersand);} + public static ampersand_svg() { return new Img(Svg.ampersand, true);} public static ampersand_ui() { return new FixedUiElement(Svg.ampersand_img);} public static arrow_left_smooth = " image/svg+xml " public static arrow_left_smooth_img = Img.AsImageElement(Svg.arrow_left_smooth) - public static arrow_left_smooth_svg() { return new FixedUiElement(Svg.arrow_left_smooth);} + public static arrow_left_smooth_svg() { return new Img(Svg.arrow_left_smooth, true);} public static arrow_left_smooth_ui() { return new FixedUiElement(Svg.arrow_left_smooth_img);} public static arrow_right_smooth = " image/svg+xml " public static arrow_right_smooth_img = Img.AsImageElement(Svg.arrow_right_smooth) - public static arrow_right_smooth_svg() { return new FixedUiElement(Svg.arrow_right_smooth);} + public static arrow_right_smooth_svg() { return new Img(Svg.arrow_right_smooth, true);} public static arrow_right_smooth_ui() { return new FixedUiElement(Svg.arrow_right_smooth_img);} public static back = " image/svg+xml " public static back_img = Img.AsImageElement(Svg.back) - public static back_svg() { return new FixedUiElement(Svg.back);} + public static back_svg() { return new Img(Svg.back, true);} public static back_ui() { return new FixedUiElement(Svg.back_img);} public static bug = " " public static bug_img = Img.AsImageElement(Svg.bug) - public static bug_svg() { return new FixedUiElement(Svg.bug);} + public static bug_svg() { return new Img(Svg.bug, true);} public static bug_ui() { return new FixedUiElement(Svg.bug_img);} public static camera_plus = " image/svg+xml " public static camera_plus_img = Img.AsImageElement(Svg.camera_plus) - public static camera_plus_svg() { return new FixedUiElement(Svg.camera_plus);} + public static camera_plus_svg() { return new Img(Svg.camera_plus, true);} public static camera_plus_ui() { return new FixedUiElement(Svg.camera_plus_img);} public static checkmark = "" public static checkmark_img = Img.AsImageElement(Svg.checkmark) - public static checkmark_svg() { return new FixedUiElement(Svg.checkmark);} + public static checkmark_svg() { return new Img(Svg.checkmark, true);} public static checkmark_ui() { return new FixedUiElement(Svg.checkmark_img);} public static circle = " " public static circle_img = Img.AsImageElement(Svg.circle) - public static circle_svg() { return new FixedUiElement(Svg.circle);} + public static circle_svg() { return new Img(Svg.circle, true);} public static circle_ui() { return new FixedUiElement(Svg.circle_img);} public static clock = " image/svg+xml " public static clock_img = Img.AsImageElement(Svg.clock) - public static clock_svg() { return new FixedUiElement(Svg.clock);} + public static clock_svg() { return new Img(Svg.clock, true);} public static clock_ui() { return new FixedUiElement(Svg.clock_img);} public static close = " image/svg+xml " public static close_img = Img.AsImageElement(Svg.close) - public static close_svg() { return new FixedUiElement(Svg.close);} + public static close_svg() { return new Img(Svg.close, true);} public static close_ui() { return new FixedUiElement(Svg.close_img);} public static compass = " image/svg+xml N S E W NW SW NE SE " public static compass_img = Img.AsImageElement(Svg.compass) - public static compass_svg() { return new FixedUiElement(Svg.compass);} + public static compass_svg() { return new Img(Svg.compass, true);} public static compass_ui() { return new FixedUiElement(Svg.compass_img);} public static cross_bottom_right = " image/svg+xml " public static cross_bottom_right_img = Img.AsImageElement(Svg.cross_bottom_right) - public static cross_bottom_right_svg() { return new FixedUiElement(Svg.cross_bottom_right);} + public static cross_bottom_right_svg() { return new Img(Svg.cross_bottom_right, true);} public static cross_bottom_right_ui() { return new FixedUiElement(Svg.cross_bottom_right_img);} public static crosshair_blue_center = " image/svg+xml " public static crosshair_blue_center_img = Img.AsImageElement(Svg.crosshair_blue_center) - public static crosshair_blue_center_svg() { return new FixedUiElement(Svg.crosshair_blue_center);} + public static crosshair_blue_center_svg() { return new Img(Svg.crosshair_blue_center, true);} public static crosshair_blue_center_ui() { return new FixedUiElement(Svg.crosshair_blue_center_img);} public static crosshair_blue = " image/svg+xml " public static crosshair_blue_img = Img.AsImageElement(Svg.crosshair_blue) - public static crosshair_blue_svg() { return new FixedUiElement(Svg.crosshair_blue);} + public static crosshair_blue_svg() { return new Img(Svg.crosshair_blue, true);} public static crosshair_blue_ui() { return new FixedUiElement(Svg.crosshair_blue_img);} public static crosshair = " image/svg+xml " public static crosshair_img = Img.AsImageElement(Svg.crosshair) - public static crosshair_svg() { return new FixedUiElement(Svg.crosshair);} + public static crosshair_svg() { return new Img(Svg.crosshair, true);} public static crosshair_ui() { return new FixedUiElement(Svg.crosshair_img);} public static delete_icon = " image/svg+xml " public static delete_icon_img = Img.AsImageElement(Svg.delete_icon) - public static delete_icon_svg() { return new FixedUiElement(Svg.delete_icon);} + public static delete_icon_svg() { return new Img(Svg.delete_icon, true);} public static delete_icon_ui() { return new FixedUiElement(Svg.delete_icon_img);} public static direction = " image/svg+xml " public static direction_img = Img.AsImageElement(Svg.direction) - public static direction_svg() { return new FixedUiElement(Svg.direction);} + public static direction_svg() { return new Img(Svg.direction, true);} public static direction_ui() { return new FixedUiElement(Svg.direction_img);} public static direction_gradient = " image/svg+xml " public static direction_gradient_img = Img.AsImageElement(Svg.direction_gradient) - public static direction_gradient_svg() { return new FixedUiElement(Svg.direction_gradient);} + public static direction_gradient_svg() { return new Img(Svg.direction_gradient, true);} public static direction_gradient_ui() { return new FixedUiElement(Svg.direction_gradient_img);} public static down = " image/svg+xml " public static down_img = Img.AsImageElement(Svg.down) - public static down_svg() { return new FixedUiElement(Svg.down);} + public static down_svg() { return new Img(Svg.down, true);} public static down_ui() { return new FixedUiElement(Svg.down_img);} public static envelope = " image/svg+xml " public static envelope_img = Img.AsImageElement(Svg.envelope) - public static envelope_svg() { return new FixedUiElement(Svg.envelope);} + public static envelope_svg() { return new Img(Svg.envelope, true);} public static envelope_ui() { return new FixedUiElement(Svg.envelope_img);} public static floppy = " " public static floppy_img = Img.AsImageElement(Svg.floppy) - public static floppy_svg() { return new FixedUiElement(Svg.floppy);} + public static floppy_svg() { return new Img(Svg.floppy, true);} public static floppy_ui() { return new FixedUiElement(Svg.floppy_img);} public static gear = " " public static gear_img = Img.AsImageElement(Svg.gear) - public static gear_svg() { return new FixedUiElement(Svg.gear);} + public static gear_svg() { return new Img(Svg.gear, true);} public static gear_ui() { return new FixedUiElement(Svg.gear_img);} public static help = " " public static help_img = Img.AsImageElement(Svg.help) - public static help_svg() { return new FixedUiElement(Svg.help);} + public static help_svg() { return new Img(Svg.help, true);} public static help_ui() { return new FixedUiElement(Svg.help_img);} public static home = " " public static home_img = Img.AsImageElement(Svg.home) - public static home_svg() { return new FixedUiElement(Svg.home);} + public static home_svg() { return new Img(Svg.home, true);} public static home_ui() { return new FixedUiElement(Svg.home_img);} public static home_white_bg = " image/svg+xml " public static home_white_bg_img = Img.AsImageElement(Svg.home_white_bg) - public static home_white_bg_svg() { return new FixedUiElement(Svg.home_white_bg);} + public static home_white_bg_svg() { return new Img(Svg.home_white_bg, true);} public static home_white_bg_ui() { return new FixedUiElement(Svg.home_white_bg_img);} public static josm_logo = " JOSM Logotype 2019 image/svg+xml JOSM Logotype 2019 2019-08-05 Diamond00744 Public Domain " public static josm_logo_img = Img.AsImageElement(Svg.josm_logo) - public static josm_logo_svg() { return new FixedUiElement(Svg.josm_logo);} + public static josm_logo_svg() { return new Img(Svg.josm_logo, true);} public static josm_logo_ui() { return new FixedUiElement(Svg.josm_logo_img);} public static layers = " image/svg+xml " public static layers_img = Img.AsImageElement(Svg.layers) - public static layers_svg() { return new FixedUiElement(Svg.layers);} + public static layers_svg() { return new Img(Svg.layers, true);} public static layers_ui() { return new FixedUiElement(Svg.layers_img);} public static layersAdd = " image/svg+xml " public static layersAdd_img = Img.AsImageElement(Svg.layersAdd) - public static layersAdd_svg() { return new FixedUiElement(Svg.layersAdd);} + public static layersAdd_svg() { return new Img(Svg.layersAdd, true);} public static layersAdd_ui() { return new FixedUiElement(Svg.layersAdd_img);} public static logo = " image/svg+xml " public static logo_img = Img.AsImageElement(Svg.logo) - public static logo_svg() { return new FixedUiElement(Svg.logo);} + public static logo_svg() { return new Img(Svg.logo, true);} public static logo_ui() { return new FixedUiElement(Svg.logo_img);} public static logout = " image/svg+xml " public static logout_img = Img.AsImageElement(Svg.logout) - public static logout_svg() { return new FixedUiElement(Svg.logout);} + public static logout_svg() { return new Img(Svg.logout, true);} public static logout_ui() { return new FixedUiElement(Svg.logout_img);} public static mapcomplete_logo = " OpenStreetMap logo 2011 image/svg+xml OpenStreetMap logo 2011 Ken Vermette April 2011 OpenStreetMap.org Replacement logo for OpenStreetMap Foundation OSM openstreetmap logo http://wiki.openstreetmap.org/wiki/File:Public-images-osm_logo.svg 010110010011010110010011  010110010011010110010011  " public static mapcomplete_logo_img = Img.AsImageElement(Svg.mapcomplete_logo) - public static mapcomplete_logo_svg() { return new FixedUiElement(Svg.mapcomplete_logo);} + public static mapcomplete_logo_svg() { return new Img(Svg.mapcomplete_logo, true);} public static mapcomplete_logo_ui() { return new FixedUiElement(Svg.mapcomplete_logo_img);} public static mapillary = "" public static mapillary_img = Img.AsImageElement(Svg.mapillary) - public static mapillary_svg() { return new FixedUiElement(Svg.mapillary);} + public static mapillary_svg() { return new Img(Svg.mapillary, true);} public static mapillary_ui() { return new FixedUiElement(Svg.mapillary_img);} public static mapillary_black = " image/svg+xml " public static mapillary_black_img = Img.AsImageElement(Svg.mapillary_black) - public static mapillary_black_svg() { return new FixedUiElement(Svg.mapillary_black);} + public static mapillary_black_svg() { return new Img(Svg.mapillary_black, true);} public static mapillary_black_ui() { return new FixedUiElement(Svg.mapillary_black_img);} public static min = " image/svg+xml " public static min_img = Img.AsImageElement(Svg.min) - public static min_svg() { return new FixedUiElement(Svg.min);} + public static min_svg() { return new Img(Svg.min, true);} public static min_ui() { return new FixedUiElement(Svg.min_img);} public static no_checkmark = " " public static no_checkmark_img = Img.AsImageElement(Svg.no_checkmark) - public static no_checkmark_svg() { return new FixedUiElement(Svg.no_checkmark);} + public static no_checkmark_svg() { return new Img(Svg.no_checkmark, true);} public static no_checkmark_ui() { return new FixedUiElement(Svg.no_checkmark_img);} public static or = " image/svg+xml " public static or_img = Img.AsImageElement(Svg.or) - public static or_svg() { return new FixedUiElement(Svg.or);} + public static or_svg() { return new Img(Svg.or, true);} public static or_ui() { return new FixedUiElement(Svg.or_img);} public static osm_copyright = " image/svg+xml " public static osm_copyright_img = Img.AsImageElement(Svg.osm_copyright) - public static osm_copyright_svg() { return new FixedUiElement(Svg.osm_copyright);} + public static osm_copyright_svg() { return new Img(Svg.osm_copyright, true);} public static osm_copyright_ui() { return new FixedUiElement(Svg.osm_copyright_img);} public static osm_logo_us = "" public static osm_logo_us_img = Img.AsImageElement(Svg.osm_logo_us) - public static osm_logo_us_svg() { return new FixedUiElement(Svg.osm_logo_us);} + public static osm_logo_us_svg() { return new Img(Svg.osm_logo_us, true);} public static osm_logo_us_ui() { return new FixedUiElement(Svg.osm_logo_us_img);} public static osm_logo = " OpenStreetMap logo 2011 image/svg+xml OpenStreetMap logo 2011 Ken Vermette April 2011 OpenStreetMap.org Replacement logo for OpenStreetMap Foundation OSM openstreetmap logo http://wiki.openstreetmap.org/wiki/File:Public-images-osm_logo.svg 010110010011010110010011 010110010011010110010011 " public static osm_logo_img = Img.AsImageElement(Svg.osm_logo) - public static osm_logo_svg() { return new FixedUiElement(Svg.osm_logo);} + public static osm_logo_svg() { return new Img(Svg.osm_logo, true);} public static osm_logo_ui() { return new FixedUiElement(Svg.osm_logo_img);} public static pencil = " " public static pencil_img = Img.AsImageElement(Svg.pencil) - public static pencil_svg() { return new FixedUiElement(Svg.pencil);} + public static pencil_svg() { return new Img(Svg.pencil, true);} public static pencil_ui() { return new FixedUiElement(Svg.pencil_img);} public static phone = " image/svg+xml " public static phone_img = Img.AsImageElement(Svg.phone) - public static phone_svg() { return new FixedUiElement(Svg.phone);} + public static phone_svg() { return new Img(Svg.phone, true);} public static phone_ui() { return new FixedUiElement(Svg.phone_img);} public static pin = " image/svg+xml " public static pin_img = Img.AsImageElement(Svg.pin) - public static pin_svg() { return new FixedUiElement(Svg.pin);} + public static pin_svg() { return new Img(Svg.pin, true);} public static pin_ui() { return new FixedUiElement(Svg.pin_img);} public static plus = " image/svg+xml " public static plus_img = Img.AsImageElement(Svg.plus) - public static plus_svg() { return new FixedUiElement(Svg.plus);} + public static plus_svg() { return new Img(Svg.plus, true);} public static plus_ui() { return new FixedUiElement(Svg.plus_img);} public static pop_out = " Svg Vector Icons : http://www.onlinewebfonts.com/icon " public static pop_out_img = Img.AsImageElement(Svg.pop_out) - public static pop_out_svg() { return new FixedUiElement(Svg.pop_out);} + public static pop_out_svg() { return new Img(Svg.pop_out, true);} public static pop_out_ui() { return new FixedUiElement(Svg.pop_out_img);} public static reload = " " public static reload_img = Img.AsImageElement(Svg.reload) - public static reload_svg() { return new FixedUiElement(Svg.reload);} + public static reload_svg() { return new Img(Svg.reload, true);} public static reload_ui() { return new FixedUiElement(Svg.reload_img);} public static ring = " image/svg+xml " public static ring_img = Img.AsImageElement(Svg.ring) - public static ring_svg() { return new FixedUiElement(Svg.ring);} + public static ring_svg() { return new Img(Svg.ring, true);} public static ring_ui() { return new FixedUiElement(Svg.ring_img);} public static search = " " public static search_img = Img.AsImageElement(Svg.search) - public static search_svg() { return new FixedUiElement(Svg.search);} + public static search_svg() { return new Img(Svg.search, true);} public static search_ui() { return new FixedUiElement(Svg.search_img);} public static send_email = " image/svg+xml " public static send_email_img = Img.AsImageElement(Svg.send_email) - public static send_email_svg() { return new FixedUiElement(Svg.send_email);} + public static send_email_svg() { return new Img(Svg.send_email, true);} public static send_email_ui() { return new FixedUiElement(Svg.send_email_img);} public static share = " image/svg+xml " public static share_img = Img.AsImageElement(Svg.share) - public static share_svg() { return new FixedUiElement(Svg.share);} + public static share_svg() { return new Img(Svg.share, true);} public static share_ui() { return new FixedUiElement(Svg.share_img);} public static square = " image/svg+xml " public static square_img = Img.AsImageElement(Svg.square) - public static square_svg() { return new FixedUiElement(Svg.square);} + public static square_svg() { return new Img(Svg.square, true);} public static square_ui() { return new FixedUiElement(Svg.square_img);} public static star = " Created by potrace 1.15, written by Peter Selinger 2001-2017 " public static star_img = Img.AsImageElement(Svg.star) - public static star_svg() { return new FixedUiElement(Svg.star);} + public static star_svg() { return new Img(Svg.star, true);} public static star_ui() { return new FixedUiElement(Svg.star_img);} public static star_half = " Created by potrace 1.15, written by Peter Selinger 2001-2017 image/svg+xml " public static star_half_img = Img.AsImageElement(Svg.star_half) - public static star_half_svg() { return new FixedUiElement(Svg.star_half);} + public static star_half_svg() { return new Img(Svg.star_half, true);} public static star_half_ui() { return new FixedUiElement(Svg.star_half_img);} public static star_outline = " Created by potrace 1.15, written by Peter Selinger 2001-2017 image/svg+xml " public static star_outline_img = Img.AsImageElement(Svg.star_outline) - public static star_outline_svg() { return new FixedUiElement(Svg.star_outline);} + public static star_outline_svg() { return new Img(Svg.star_outline, true);} public static star_outline_ui() { return new FixedUiElement(Svg.star_outline_img);} public static star_outline_half = " Created by potrace 1.15, written by Peter Selinger 2001-2017 image/svg+xml " public static star_outline_half_img = Img.AsImageElement(Svg.star_outline_half) - public static star_outline_half_svg() { return new FixedUiElement(Svg.star_outline_half);} + public static star_outline_half_svg() { return new Img(Svg.star_outline_half, true);} public static star_outline_half_ui() { return new FixedUiElement(Svg.star_outline_half_img);} public static statistics = " Svg Vector Icons : http://www.onlinewebfonts.com/icon " public static statistics_img = Img.AsImageElement(Svg.statistics) - public static statistics_svg() { return new FixedUiElement(Svg.statistics);} + public static statistics_svg() { return new Img(Svg.statistics, true);} public static statistics_ui() { return new FixedUiElement(Svg.statistics_img);} public static translate = " " public static translate_img = Img.AsImageElement(Svg.translate) - public static translate_svg() { return new FixedUiElement(Svg.translate);} + public static translate_svg() { return new Img(Svg.translate, true);} public static translate_ui() { return new FixedUiElement(Svg.translate_img);} public static up = " " public static up_img = Img.AsImageElement(Svg.up) - public static up_svg() { return new FixedUiElement(Svg.up);} + public static up_svg() { return new Img(Svg.up, true);} public static up_ui() { return new FixedUiElement(Svg.up_img);} public static wikidata = " " public static wikidata_img = Img.AsImageElement(Svg.wikidata) - public static wikidata_svg() { return new FixedUiElement(Svg.wikidata);} + public static wikidata_svg() { return new Img(Svg.wikidata, true);} public static wikidata_ui() { return new FixedUiElement(Svg.wikidata_img);} public static wikimedia_commons_white = " Wikimedia Commons Logo " public static wikimedia_commons_white_img = Img.AsImageElement(Svg.wikimedia_commons_white) - public static wikimedia_commons_white_svg() { return new FixedUiElement(Svg.wikimedia_commons_white);} + public static wikimedia_commons_white_svg() { return new Img(Svg.wikimedia_commons_white, true);} public static wikimedia_commons_white_ui() { return new FixedUiElement(Svg.wikimedia_commons_white_img);} public static wikipedia = " Wikipedia logo version 2" public static wikipedia_img = Img.AsImageElement(Svg.wikipedia) - public static wikipedia_svg() { return new FixedUiElement(Svg.wikipedia);} + public static wikipedia_svg() { return new Img(Svg.wikipedia, true);} public static wikipedia_ui() { return new FixedUiElement(Svg.wikipedia_img);} public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};} diff --git a/UI/Base/Img.ts b/UI/Base/Img.ts index 23c89fa33c..f2628bdb9f 100644 --- a/UI/Base/Img.ts +++ b/UI/Base/Img.ts @@ -3,10 +3,12 @@ import BaseUIElement from "../BaseUIElement"; export default class Img extends BaseUIElement { private _src: string; + private readonly _rawSvg: boolean; - constructor(src: string) { + constructor(src: string, rawSvg = false) { super(); this._src = src; + this._rawSvg = rawSvg; } static AsData(source: string) { @@ -21,6 +23,13 @@ export default class Img extends BaseUIElement { } protected InnerConstructElement(): HTMLElement { + + if (this._rawSvg) { + const e = document.createElement("div") + e.innerHTML = this._src + return e; + } + const el = document.createElement("img") el.src = this._src; el.onload = () => { diff --git a/UI/Base/SubtleButton.ts b/UI/Base/SubtleButton.ts index 9d87c903d0..f1530a1a1c 100644 --- a/UI/Base/SubtleButton.ts +++ b/UI/Base/SubtleButton.ts @@ -29,14 +29,14 @@ export class SubtleButton extends UIElement { } else { img = imageUrl; } - img?.SetClass("block flex items-center justify-center h-11 w-11 flex-shrink0") + img?.SetClass("block flex items-center justify-center h-11 w-11 flex-shrink0 mr-4") const image = new Combine([img]) .SetClass("flex-shrink-0"); if (linkTo == undefined) { return new Combine([ image, - message?.SetClass("blcok ml-4 overflow-ellipsis"), + message?.SetClass("block overflow-ellipsis"), ]).SetClass("flex group w-full"); } @@ -44,7 +44,7 @@ export class SubtleButton extends UIElement { return new Link( new Combine([ image, - message?.SetClass("block ml-4 overflow-ellipsis") + message?.SetClass("block overflow-ellipsis") ]).SetClass("flex group w-full"), linkTo.url, linkTo.newTab ?? false diff --git a/UI/BigComponents/Basemap.ts b/UI/BigComponents/Basemap.ts index 5db429e0f1..d2b7036587 100644 --- a/UI/BigComponents/Basemap.ts +++ b/UI/BigComponents/Basemap.ts @@ -34,11 +34,11 @@ export class Basemap { this.map.setMaxBounds( [[-100, -200], [100, 200]] ); + this.map.attributionControl.setPrefix( " | OpenStreetMap"); extraAttribution.AttachTo('leaflet-attribution') - const self = this; let previousLayer = currentLayer.data; diff --git a/UI/BigComponents/ThemeIntroductionPanel.ts b/UI/BigComponents/ThemeIntroductionPanel.ts index 7ea3701da9..f3b66e8803 100644 --- a/UI/BigComponents/ThemeIntroductionPanel.ts +++ b/UI/BigComponents/ThemeIntroductionPanel.ts @@ -20,7 +20,7 @@ export default class ThemeIntroductionPanel extends VariableUiElement { ; const toTheMap = new SubtleButton( - new FixedUiElement(""), + undefined, Translations.t.general.openTheMap.Clone().SetClass("text-xl font-bold w-full text-center") ).onClick(() =>{ isShown.setData(false) diff --git a/UI/Image/AttributedImage.ts b/UI/Image/AttributedImage.ts new file mode 100644 index 0000000000..260c5306f8 --- /dev/null +++ b/UI/Image/AttributedImage.ts @@ -0,0 +1,19 @@ +import Combine from "../Base/Combine"; +import Attribution from "./Attribution"; +import Img from "../Base/Img"; +import ImageAttributionSource from "../../Logic/Web/ImageAttributionSource"; + + +export class AttributedImage extends Combine { + + constructor(urlSource: string, imgSource: ImageAttributionSource) { + urlSource = imgSource.PrepareUrl(urlSource) + super([ + new Img( urlSource), + new Attribution(imgSource.GetAttributionFor(urlSource), imgSource.SourceIcon()) + ]); + this.SetClass('block relative h-full'); + } + + +} \ No newline at end of file diff --git a/UI/Image/Attribution.ts b/UI/Image/Attribution.ts index 78b6171d17..514bc475a9 100644 --- a/UI/Image/Attribution.ts +++ b/UI/Image/Attribution.ts @@ -1,19 +1,33 @@ -import {UIElement} from "../UIElement"; import Combine from "../Base/Combine"; import Translations from "../i18n/Translations"; import BaseUIElement from "../BaseUIElement"; +import {VariableUiElement} from "../Base/VariableUIElement"; +import {UIEventSource} from "../../Logic/UIEventSource"; +import {LicenseInfo} from "../../Logic/Web/Wikimedia"; -export default class Attribution extends Combine { +export default class Attribution extends VariableUiElement { - constructor(author: BaseUIElement | string, license: BaseUIElement | string, icon: BaseUIElement) { - super([ - icon?.SetClass("block left").SetStyle("height: 2em; width: 2em; padding-right: 0.5em"), - new Combine([ - Translations.W(author).SetClass("block font-bold"), - Translations.W((license ?? "") === "undefined" ? "CC0" : (license ?? "")) - ]).SetClass("flex flex-col") - ]); - this.SetClass("flex flex-row bg-black text-white text-sm absolute bottom-0 left-0 p-0.5 pl-5 pr-3 rounded-lg"); + constructor(license: UIEventSource, icon: BaseUIElement) { + if (license === undefined) { + throw "No license source given in the attribution element" + } + super( + license.map((license : LicenseInfo) => { + + if (license?.artist === undefined) { + return undefined; + } + + return new Combine([ + icon?.SetClass("block left").SetStyle("height: 2em; width: 2em; padding-right: 0.5em;"), + + new Combine([ + Translations.W(license.artist).SetClass("block font-bold"), + Translations.W((license.license ?? "") === "" ? "CC0" : (license.license ?? "")) + ]).SetClass("flex flex-col") + ]).SetClass("flex flex-row bg-black text-white text-sm absolute bottom-0 left-0 p-0.5 pl-5 pr-3 rounded-lg") + + })); } } \ No newline at end of file diff --git a/UI/Image/ImageCarousel.ts b/UI/Image/ImageCarousel.ts index 4a29d6a0b4..a28d89a2cf 100644 --- a/UI/Image/ImageCarousel.ts +++ b/UI/Image/ImageCarousel.ts @@ -2,12 +2,14 @@ import {SlideShow} from "./SlideShow"; import {UIEventSource} from "../../Logic/UIEventSource"; import Combine from "../Base/Combine"; import DeleteImage from "./DeleteImage"; -import {WikimediaImage} from "./WikimediaImage"; -import {ImgurImage} from "./ImgurImage"; -import {MapillaryImage} from "./MapillaryImage"; +import {AttributedImage} from "./AttributedImage"; import BaseUIElement from "../BaseUIElement"; import Img from "../Base/Img"; import Toggle from "../Input/Toggle"; +import ImageAttributionSource from "../../Logic/Web/ImageAttributionSource"; +import {Wikimedia} from "../../Logic/Web/Wikimedia"; +import {Mapillary} from "../../Logic/Web/Mapillary"; +import {Imgur} from "../../Logic/Web/Imgur"; export class ImageCarousel extends Toggle { @@ -45,17 +47,20 @@ export class ImageCarousel extends Toggle { */ private static CreateImageElement(url: string): BaseUIElement { // @ts-ignore + let attrSource : ImageAttributionSource = undefined; if (url.startsWith("File:")) { - return new WikimediaImage(url); + attrSource = Wikimedia.singleton } else if (url.toLowerCase().startsWith("https://commons.wikimedia.org/wiki/")) { - const commons = url.substr("https://commons.wikimedia.org/wiki/".length); - return new WikimediaImage(commons); + attrSource = Wikimedia.singleton; } else if (url.toLowerCase().startsWith("https://i.imgur.com/")) { - return new ImgurImage(url); + attrSource = Imgur.singleton } else if (url.toLowerCase().startsWith("https://www.mapillary.com/map/im/")) { - return new MapillaryImage(url); + attrSource = Mapillary.singleton } else { return new Img(url); } + + return new AttributedImage(url, attrSource) + } } \ No newline at end of file diff --git a/UI/Image/ImgurImage.ts b/UI/Image/ImgurImage.ts deleted file mode 100644 index 93355df4e3..0000000000 --- a/UI/Image/ImgurImage.ts +++ /dev/null @@ -1,48 +0,0 @@ -import {UIElement} from "../UIElement"; -import {UIEventSource} from "../../Logic/UIEventSource"; -import {LicenseInfo} from "../../Logic/Web/Wikimedia"; -import {Imgur} from "../../Logic/Web/Imgur"; -import Combine from "../Base/Combine"; -import Attribution from "./Attribution"; -import BaseUIElement from "../BaseUIElement"; -import Img from "../Base/Img"; -import {VariableUiElement} from "../Base/VariableUIElement"; - - -export class ImgurImage extends UIElement { - - - /*** - * Dictionary from url to alreayd known license info - */ - private static allLicenseInfos: any = {}; - private readonly _imageMeta: UIEventSource; - private readonly _imageLocation: string; - - constructor(source: string) { - super() - this._imageLocation = source; - if (ImgurImage.allLicenseInfos[source] !== undefined) { - this._imageMeta = ImgurImage.allLicenseInfos[source]; - } else { - this._imageMeta = new UIEventSource(null); - ImgurImage.allLicenseInfos[source] = this._imageMeta; - const self = this; - Imgur.getDescriptionOfImage(source, (license) => { - self._imageMeta.setData(license) - }) - } - } - - InnerRender(): BaseUIElement { - const image = new Img( this._imageLocation); - - return new Combine([ - image, - new VariableUiElement(this._imageMeta.map(meta => (meta === undefined || meta === null) ? undefined : new Attribution(meta.artist, meta.license, undefined))) - ]).SetClass('block relative h-full'); - - } - - -} \ No newline at end of file diff --git a/UI/Image/MapillaryImage.ts b/UI/Image/MapillaryImage.ts deleted file mode 100644 index 53ec504313..0000000000 --- a/UI/Image/MapillaryImage.ts +++ /dev/null @@ -1,61 +0,0 @@ -import {UIElement} from "../UIElement"; -import {UIEventSource} from "../../Logic/UIEventSource"; -import {LicenseInfo} from "../../Logic/Web/Wikimedia"; -import {Mapillary} from "../../Logic/Web/Mapillary"; -import Svg from "../../Svg"; -import Combine from "../Base/Combine"; -import Attribution from "./Attribution"; -import Img from "../Base/Img"; -import BaseUIElement from "../BaseUIElement"; - - -export class MapillaryImage extends UIElement { - - /*** - * Dictionary from url to already known license info - */ - private static allLicenseInfos: any = {}; - private readonly _imageMeta: UIEventSource; - private readonly _imageLocation: string; - - constructor(source: string) { - super() - - if (source.toLowerCase().startsWith("https://www.mapillary.com/map/im/")) { - source = source.substring("https://www.mapillary.com/map/im/".length); - } - - this._imageLocation = source; - if (MapillaryImage.allLicenseInfos[source] !== undefined) { - this._imageMeta = MapillaryImage.allLicenseInfos[source]; - } else { - this._imageMeta = new UIEventSource(null); - MapillaryImage.allLicenseInfos[source] = this._imageMeta; - const self = this; - Mapillary.getDescriptionOfImage(source, (license) => { - self._imageMeta.setData(license) - }) - } - - this.ListenTo(this._imageMeta); - - } - - InnerRender(): BaseUIElement { - const url = `https://images.mapillary.com/${this._imageLocation}/thumb-640.jpg?client_id=TXhLaWthQ1d4RUg0czVxaTVoRjFJZzowNDczNjUzNmIyNTQyYzI2`; - const image = new Img(url) - - const meta = this._imageMeta?.data; - if (!meta) { - return image; - } - - return new Combine([ - image, - new Attribution(meta.artist, meta.license, Svg.mapillary_svg()) - ]).SetClass("relative block h-full"); - - } - - -} \ No newline at end of file diff --git a/UI/Image/SlideShow.ts b/UI/Image/SlideShow.ts index eea8ea5668..fdc8920085 100644 --- a/UI/Image/SlideShow.ts +++ b/UI/Image/SlideShow.ts @@ -11,23 +11,27 @@ export class SlideShow extends BaseUIElement { constructor(embeddedElements: UIEventSource) { super() this.embeddedElements =embeddedElements; - } + this.SetStyle("scroll-snap-type: x mandatory; overflow-x: scroll") + } protected InnerConstructElement(): HTMLElement { const el = document.createElement("div") - el.style.overflowX = "auto" - el.style.width = "min-content" el.style.minWidth = "min-content" el.style.display = "flex" - + el.style.justifyContent = "center" this.embeddedElements.addCallbackAndRun(elements => { + + if(elements.length > 1){ + el.style.justifyContent = "unset" + } + while (el.firstChild) { el.removeChild(el.lastChild) } elements = Utils.NoNull(elements).map(el => new Combine([el]) .SetClass("block relative ml-1 bg-gray-200 m-1 rounded slideshow-item") - .SetStyle("min-width: 150px; width: max-content; height: var(--image-carousel-height);max-height: var(--image-carousel-height);") + .SetStyle("min-width: 150px; width: max-content; height: var(--image-carousel-height);max-height: var(--image-carousel-height);scroll-snap-align: start;") ) for (const element of elements ?? []) { diff --git a/UI/Image/WikimediaImage.ts b/UI/Image/WikimediaImage.ts deleted file mode 100644 index 85b4c50a49..0000000000 --- a/UI/Image/WikimediaImage.ts +++ /dev/null @@ -1,59 +0,0 @@ -import {UIElement} from "../UIElement"; -import {LicenseInfo, Wikimedia} from "../../Logic/Web/Wikimedia"; -import {UIEventSource} from "../../Logic/UIEventSource"; -import Svg from "../../Svg"; -import Link from "../Base/Link"; -import Combine from "../Base/Combine"; -import Attribution from "./Attribution"; -import BaseUIElement from "../BaseUIElement"; -import Img from "../Base/Img"; - - -export class WikimediaImage extends UIElement { - - - static allLicenseInfos: any = {}; - private readonly _imageMeta: UIEventSource; - private readonly _imageLocation: string; - - constructor(source: string) { - super(undefined) - this._imageLocation = source; - if (WikimediaImage.allLicenseInfos[source] !== undefined) { - this._imageMeta = WikimediaImage.allLicenseInfos[source]; - } else { - this._imageMeta = new UIEventSource(new LicenseInfo()); - WikimediaImage.allLicenseInfos[source] = this._imageMeta; - const self = this; - Wikimedia.LicenseData(source, (info) => { - self._imageMeta.setData(info); - }) - } - - this.ListenTo(this._imageMeta); - - - } - - InnerRender(): BaseUIElement { - const url = Wikimedia.ImageNameToUrl(this._imageLocation, 500, 400) - .replace(/'/g, '%27'); - const image = new Img(url) - const meta = this._imageMeta?.data; - - if (!meta) { - return image; - } - new Link(Svg.wikimedia_commons_white_img, - `https://commons.wikimedia.org/wiki/${this._imageLocation}`, true) - .SetStyle("width:2em;height: 2em"); - - return new Combine([ - image, - new Attribution(meta.artist, meta.license, Svg.wikimedia_commons_white_svg()) - ]).SetClass("relative block h-full") - - } - - -} \ No newline at end of file diff --git a/index.css b/index.css index 7e22c57b99..ebf83ca4bb 100644 --- a/index.css +++ b/index.css @@ -62,7 +62,7 @@ --variable-title-height: 0px; /* Set by javascript */ --return-to-the-map-height: 2em; - --image-carousel-height: 400px; + --image-carousel-height: 350px; } html, body { @@ -148,10 +148,6 @@ li::marker { .border-attention-catch{ border: 5px solid var(--catch-detail-color);} -.slick-prev:before, .slick-next:before { - /*Slideshow workaround*/ - color:black !important; -} #topleft-tools svg { fill: var(--foreground-color) !important; @@ -360,6 +356,6 @@ li::marker { .slideshow-item img{ - height: 100%; + height: var(--image-carousel-height); width: unset; } \ No newline at end of file diff --git a/index.manifest b/index.manifest index 9b311e9008..1eb1aec3ce 100644 --- a/index.manifest +++ b/index.manifest @@ -1,8 +1,10 @@ { "name": "index", + "short_name": "MapComplete", "start_url": "index.html", "display": "standalone", "background_color": "#fff", + "description": "A thematic map viewer and editor based on OpenStreetMap", "orientation": "portrait-primary, landscape-primary", "icons": [ { diff --git a/scripts/generateIncludedImages.ts b/scripts/generateIncludedImages.ts index f240be7ef8..f812bb2c41 100644 --- a/scripts/generateIncludedImages.ts +++ b/scripts/generateIncludedImages.ts @@ -28,7 +28,7 @@ function genImages() { .replace(/[ -]/g, "_"); module += ` public static ${name} = "${svg}"\n` module += ` public static ${name}_img = Img.AsImageElement(Svg.${name})\n` - module += ` public static ${name}_svg() { return new FixedUiElement(Svg.${name});}\n` + module += ` public static ${name}_svg() { return new Img(Svg.${name}, true);}\n` module += ` public static ${name}_ui() { return new FixedUiElement(Svg.${name}_img);}\n\n` allNames.push(`"${path}": Svg.${name}`) } diff --git a/test.ts b/test.ts index 8dc3264023..4bf602cf73 100644 --- a/test.ts +++ b/test.ts @@ -8,7 +8,8 @@ import TagRenderingQuestion from "./UI/Popup/TagRenderingQuestion"; import {SlideShow} from "./UI/Image/SlideShow"; import {FixedUiElement} from "./UI/Base/FixedUiElement"; import Img from "./UI/Base/Img"; -import {ImgurImage} from "./UI/Image/ImgurImage"; +import {AttributedImage} from "./UI/Image/AttributedImage"; +import {Imgur} from "./Logic/Web/Imgur"; function TestSlideshow(){ @@ -16,7 +17,7 @@ function TestSlideshow(){ new FixedUiElement("A"), new FixedUiElement("qmsldkfjqmlsdkjfmqlskdjfmqlksdf").SetClass("text-xl"), new Img("https://i.imgur.com/8lIQ5Hv.jpg"), - new ImgurImage("https://i.imgur.com/y5XudzW.jpg"), + new AttributedImage("https://i.imgur.com/y5XudzW.jpg", new Imgur()), new Img("https://www.grunge.com/img/gallery/the-real-reason-your-cat-sleeps-so-much/intro-1601496900.webp") ]) new SlideShow(elems).AttachTo("maindiv")