Merge develop

This commit is contained in:
Pieter Vander Vennet 2021-04-10 16:12:40 +02:00
commit 2ad72ae346
95 changed files with 2856 additions and 594 deletions

View file

@ -10,6 +10,9 @@ import Loc from "../../Models/Loc";
import LeafletMap from "../../Models/LeafletMap";
import * as L from "leaflet"
/**
* The bottom right attribution panel in the leaflet map
*/
export default class Attribution extends UIElement {
private readonly _location: UIEventSource<Loc>;

View file

@ -0,0 +1,69 @@
import {UIElement} from "../UIElement";
import Combine from "../Base/Combine";
import Translations from "../i18n/Translations";
import Attribution from "./Attribution";
import State from "../../State";
import {UIEventSource} from "../../Logic/UIEventSource";
import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
import {FixedUiElement} from "../Base/FixedUiElement";
import * as licenses from "../../assets/generated/license_info.json"
import SmallLicense from "../../Models/smallLicense";
import {Icon} from "leaflet";
import Img from "../Base/Img";
import {Utils} from "../../Utils";
/**
* The attribution panel shown on mobile
*/
export default class AttributionPanel extends Combine {
private static LicenseObject = AttributionPanel.GenerateLicenses();
constructor(layoutToUse: UIEventSource<LayoutConfig>) {
super([
Translations.t.general.attribution.attributionContent,
((layoutToUse.data.maintainer ?? "") == "") ? "" : Translations.t.general.attribution.themeBy.Subs({author: layoutToUse.data.maintainer}),
layoutToUse.data.credits ,
"<br/>",
new Attribution(undefined, undefined, State.state.layoutToUse, undefined),
"<br/>",
Translations.t.general.attribution.iconAttribution.title.Clone().SetClass("font-bold pt-12 pb-3"),
...Utils.NoNull(Array.from(layoutToUse.data.ExtractImages()))
.map(AttributionPanel.IconAttribution)
]);
this.SetClass("flex flex-col")
}
private static IconAttribution(iconPath: string) {
if (iconPath.startsWith("http")) {
iconPath = "." + new URL(iconPath).pathname;
}
const license: SmallLicense = AttributionPanel.LicenseObject[iconPath]
if (license == undefined) {
return undefined;
}
if(license.license.indexOf("trivial")>=0){
return undefined;
}
return new Combine([
`<img src='${iconPath}' style="width: 50px; height: 50px; margin-right: 0.5em;">`,
new Combine([
new FixedUiElement(license.authors.join("; ")).SetClass("font-bold"),
new Combine([license.license, license.sources.length > 0 ? " - " : "",
...license.sources.map(link => `<a href='${link}' target="_blank">${new URL(link).hostname}</a> `)]).SetClass("block")
]).SetClass("flex flex-col")
]).SetClass("flex")
}
private static GenerateLicenses() {
const allLicenses = {}
for (const key in licenses) {
const license: SmallLicense = licenses[key];
allLicenses[license.path] = license
}
return allLicenses;
}
}

View file

@ -85,16 +85,12 @@ export default class MoreScreen extends UIElement {
const linkButton: UIElement[] = []
for (const k in AllKnownLayouts.allSets) {
const layout: LayoutConfig = AllKnownLayouts.allSets[k];
if (k === personal.id) {
for (const layout of AllKnownLayouts.layoutsList) {
if (layout.id === personal.id) {
if (State.state.osmConnection.userDetails.data.csCount < Constants.userJourney.personalLayoutUnlock) {
continue;
}
}
if (layout.id !== k) {
continue; // This layout was added multiple time due to an uppercase
}
linkButton.push(this.createLinkButton(layout));
}

View file

@ -8,6 +8,8 @@ export class Translation extends UIElement {
public static forcedLanguage = undefined;
public readonly translations: object
return
allIcons;
constructor(translations: object, context?: string) {
super(Locale.language)
@ -17,6 +19,9 @@ export class Translation extends UIElement {
let count = 0;
for (const translationsKey in translations) {
count++;
if(typeof(translations[translationsKey]) != "string"){
throw "Error in an object depicting a translation: a non-string object was found. ("+context+")\n You probably put some other section accidentally in the translation"
}
}
this.translations = translations;
if (count === 0) {
@ -46,7 +51,7 @@ export class Translation extends UIElement {
public SupportedLanguages(): string[] {
const langs = []
for (const translationsKey in this.translations) {
if(translationsKey === "#"){
if (translationsKey === "#") {
continue;
}
langs.push(translationsKey)
@ -102,7 +107,6 @@ export class Translation extends UIElement {
return new Translation(this.translations)
}
FirstSentence() {
const tr = {};
@ -115,4 +119,38 @@ export class Translation extends UIElement {
return new Translation(tr);
}
public ExtractImages(isIcon = false): string[] {
const allIcons: string[] = []
for (const key in this.translations) {
const render = this.translations[key]
if (isIcon) {
const icons = render.split(";").filter(part => part.match(/(\.svg|\.png|\.jpg)$/) != null)
allIcons.push(...icons)
} else if (!Utils.runningFromConsole) {
// This might be a tagrendering containing some img as html
const htmlElement = document.createElement("div")
htmlElement.innerHTML = render
const images = Array.from(htmlElement.getElementsByTagName("img")).map(img => img.src)
allIcons.push(...images)
} else {
// We are running this in ts-node (~= nodejs), and can not access document
// So, we fallback to simple regex
try {
const matches = render.match(/<img[^>]+>/g)
if (matches != null) {
const sources = matches.map(img => img.match(/src=("[^"]+"|'[^']+'|[^/ ]+)/))
.filter(match => match != null)
.map(match => match[1].trim().replace(/^['"]/, '').replace(/['"]$/, ''));
allIcons.push(...sources)
}
}catch(e){
console.error("Could not search for images: ", render, this.txt)
throw e
}
}
}
return allIcons.filter(icon => icon != undefined)
}
}