Merge master

This commit is contained in:
Pieter Vander Vennet 2025-01-28 16:37:41 +01:00
commit c939d8ea8e
352 changed files with 976 additions and 212534 deletions

View file

@ -8,11 +8,13 @@ import { FeatureSource, WritableFeatureSource } from "../FeatureSource/FeatureSo
import { LocalStorageSource } from "../Web/LocalStorageSource"
import { GeoOperations } from "../GeoOperations"
import { OsmTags } from "../../Models/OsmFeature"
import StaticFeatureSource, { WritableStaticFeatureSource } from "../FeatureSource/Sources/StaticFeatureSource"
import StaticFeatureSource, {
WritableStaticFeatureSource,
} from "../FeatureSource/Sources/StaticFeatureSource"
import { MapProperties } from "../../Models/MapProperties"
import { Orientation } from "../../Sensors/Orientation"
("use strict")
;("use strict")
/**
* The geolocation-handler takes a map-location and a geolocation state.
* It'll move the map as appropriate given the state of the geolocation-API

View file

@ -32,7 +32,6 @@ export default class NoElementsInViewDetector {
return "zoom-to-low"
}
for (const [layerName, source] of themeViewState.perLayerFiltered) {
if (priviliged.has(layerName)) {
continue

View file

@ -34,11 +34,15 @@ export default class SelectedElementTagsUpdater {
})
}
public static applyUpdate(latestTags: OsmTags, id: string, state: {
theme: ThemeConfig,
changes: Changes,
featureProperties: FeaturePropertiesStore
}) {
public static applyUpdate(
latestTags: OsmTags,
id: string,
state: {
theme: ThemeConfig
changes: Changes
featureProperties: FeaturePropertiesStore
}
) {
try {
const leftRightSensitive = state.theme.isLeftRightSensitive()

View file

@ -69,7 +69,7 @@ export default class DetermineTheme {
tagRenderings: DetermineTheme.getSharedTagRenderings(),
tagRenderingOrder: DetermineTheme.getSharedTagRenderingOrder(),
sharedLayers: knownLayersDict,
publicLayers: new Set<string>()
publicLayers: new Set<string>(),
}
return convertState
}

View file

@ -84,10 +84,10 @@ export default class FavouritesFeatureSource extends StaticFeatureSource {
private async updateFeature(
feature: Feature,
state: {
theme: ThemeConfig,
changes: Changes,
featureProperties: FeaturePropertiesStore,
osmObjectDownloader: OsmObjectDownloader,
theme: ThemeConfig
changes: Changes
featureProperties: FeaturePropertiesStore
osmObjectDownloader: OsmObjectDownloader
}
) {
const id = feature.properties.id

View file

@ -32,7 +32,6 @@ export default class ThemeSource implements IndexedFeatureSource {
public readonly featuresById: Store<Map<string, Feature>>
private readonly core: Store<ThemeSourceCore>
private readonly addedSources: FeatureSource[] = []
private readonly addedItems: OsmFeature[] = []
@ -48,14 +47,23 @@ export default class ThemeSource implements IndexedFeatureSource {
const isLoading = new UIEventSource(true)
this.isLoading = isLoading
const features = this.features = new UIEventSource<Feature[]>([])
const featuresById = this.featuresById = new UIEventSource(new Map())
this.core = mvtAvailableLayers.mapD(mvtAvailableLayers => {
const core = new ThemeSourceCore(layers, featureSwitches, mapProperties, backend, isDisplayed, mvtAvailableLayers, isLoading, fullNodeDatabaseSource)
this.addedSources.forEach(src => core.addSource(src))
this.addedItems.forEach(item => core.addItem(item))
core.features.addCallbackAndRun(data => features.set(data))
core.featuresById.addCallbackAndRun(data => featuresById.set(data))
const features = (this.features = new UIEventSource<Feature[]>([]))
const featuresById = (this.featuresById = new UIEventSource(new Map()))
this.core = mvtAvailableLayers.mapD((mvtAvailableLayers) => {
const core = new ThemeSourceCore(
layers,
featureSwitches,
mapProperties,
backend,
isDisplayed,
mvtAvailableLayers,
isLoading,
fullNodeDatabaseSource
)
this.addedSources.forEach((src) => core.addSource(src))
this.addedItems.forEach((item) => core.addItem(item))
core.features.addCallbackAndRun((data) => features.set(data))
core.featuresById.addCallbackAndRun((data) => featuresById.set(data))
return core
})
}
@ -69,7 +77,6 @@ export default class ThemeSource implements IndexedFeatureSource {
this.addedSources.push(source)
}
public addItem(obj: OsmFeature) {
this.core.data?.addItem(obj)
this.addedItems.push(obj)
@ -82,7 +89,6 @@ export default class ThemeSource implements IndexedFeatureSource {
* Note that special layers (with `source=null` will be ignored)
*/
class ThemeSourceCore extends FeatureSourceMerger {
/**
* This source is _only_ triggered when the data is downloaded for CSV export
* @private
@ -116,7 +122,7 @@ class ThemeSourceCore extends FeatureSourceMerger {
mapProperties,
{
isActive: isDisplayed(layer.id),
maxAge: layer.maxAgeOfCache
maxAge: layer.maxAgeOfCache,
}
)
fromCache.set(layer.id, src)
@ -169,11 +175,11 @@ class ThemeSourceCore extends FeatureSourceMerger {
overpassUrl: featureSwitches.overpassUrl,
overpassTimeout: featureSwitches.overpassTimeout,
overpassMaxZoom: new ImmutableStore(99),
widenFactor: 0
widenFactor: 0,
},
{
ignoreZoom: true,
isActive: new ImmutableStore(false)
isActive: new ImmutableStore(false),
}
)
@ -247,7 +253,7 @@ class ThemeSourceCore extends FeatureSourceMerger {
backend,
isActive,
patchRelations: true,
fullNodeDatabase
fullNodeDatabase,
})
}
@ -279,11 +285,11 @@ class ThemeSourceCore extends FeatureSourceMerger {
widenFactor: 1.5,
overpassUrl: featureSwitches.overpassUrl,
overpassTimeout: featureSwitches.overpassTimeout,
overpassMaxZoom: featureSwitches.overpassMaxZoom
overpassMaxZoom: featureSwitches.overpassMaxZoom,
},
{
padToTiles: zoom.map((zoom) => Math.min(15, zoom + 1)),
isActive
isActive,
}
)
}

View file

@ -22,7 +22,7 @@ export default class AllImageProviders {
...WikimediaImageProvider.commonsPrefixes,
...Mapillary.valuePrefixes,
...AllImageProviders.dontLoadFromPrefixes,
"Category:"
"Category:",
])
private static imageAttributionSources: ImageProvider[] = [
@ -31,7 +31,7 @@ export default class AllImageProviders {
WikidataImageProvider.singleton,
WikimediaImageProvider.singleton,
Panoramax.singleton,
AllImageProviders.genericImageProvider
AllImageProviders.genericImageProvider,
]
public static apiUrls: string[] = [].concat(
...AllImageProviders.imageAttributionSources.map((src) => src.apiUrls())
@ -44,7 +44,7 @@ export default class AllImageProviders {
mapillary: Mapillary.singleton,
wikidata: WikidataImageProvider.singleton,
wikimedia: WikimediaImageProvider.singleton,
panoramax: Panoramax.singleton
panoramax: Panoramax.singleton,
}
public static byName(name: string) {
@ -77,7 +77,10 @@ export default class AllImageProviders {
*
*
*/
public static estimateNumberOfImages(tags: Record<string, string>, prefixes: string[] = undefined): number {
public static estimateNumberOfImages(
tags: Record<string, string>,
prefixes: string[] = undefined
): number {
let count = 0
const sources = [Imgur.singleton,
@ -137,7 +140,7 @@ export default class AllImageProviders {
*/
public static loadImagesFrom(urls: string[]): Store<ProvidedImage[]> {
const tags = {
id: urls.join(";")
id: urls.join(";"),
}
for (let i = 0; i < urls.length; i++) {
tags["image:" + i] = urls[i]

View file

@ -604,14 +604,16 @@ export class OsmConnection {
if (this.fakeUser) {
return
}
this.FetchCapabilities().then(({ api, gpx }) => {
this.apiIsOnline.setData(api)
this.gpxServiceIsOnline.setData(gpx)
}).catch(err => {
console.log("Could not reach the api:", err)
this.apiIsOnline.set("unreachable")
this.gpxServiceIsOnline.set("unreachable")
})
this.FetchCapabilities()
.then(({ api, gpx }) => {
this.apiIsOnline.setData(api)
this.gpxServiceIsOnline.setData(gpx)
})
.catch((err) => {
console.log("Could not reach the api:", err)
this.apiIsOnline.set("unreachable")
this.gpxServiceIsOnline.set("unreachable")
})
}
private readonly _userInfoCache: Record<number, OsmUserInfo> = {}

View file

@ -210,7 +210,7 @@ export class OsmPreferences {
* @private
*/
private async getPreferencesDictDirectly(): Promise<Record<string, string>> {
if(!this.osmConnection.isLoggedIn.data){
if (!this.osmConnection.isLoggedIn.data) {
return {}
}
return new Promise<Record<string, string>>((resolve, reject) => {
@ -260,7 +260,7 @@ export class OsmPreferences {
*
*/
private async uploadKvSplit(k: string, v: string) {
if(!this.osmConnection.isLoggedIn.data){
if (!this.osmConnection.isLoggedIn.data) {
return
}
if (v === null || v === undefined || v === "" || v === "undefined" || v === "null") {

View file

@ -15,7 +15,6 @@ export default class OpenStreetMapIdSearch implements GeocodingProvider {
}
private readonly _osmObjectDownloader: OsmObjectDownloader
constructor(osmObjectDownloader: OsmObjectDownloader) {
this._osmObjectDownloader = osmObjectDownloader
}

View file

@ -41,7 +41,7 @@ export default class SearchState {
new OpenLocationCodeSearch(),
new OpenStreetMapIdSearch(state.osmObjectDownloader),
new PhotonSearch(true, 2),
new PhotonSearch()
new PhotonSearch(),
// new NominatimGeocoding(),
]

View file

@ -414,7 +414,7 @@ export default class UserRelatedState {
typeof window === "undefined" ? "no" : window.navigator.share ? "yes" : "no",
_iframe: Utils.isIframe ? "yes" : "no",
})
if(!Utils.runningFromConsole){
if (!Utils.runningFromConsole) {
amendedPrefs.data["_host"] = window.location.host
amendedPrefs.data["_path"] = window.location.pathname
amendedPrefs.data["_userAgent"] = navigator.userAgent
@ -492,7 +492,7 @@ export default class UserRelatedState {
})
const usersettingMetaTagging = new ThemeMetaTagging()
osmConnection.isLoggedIn.addCallbackAndRun(loggedIn => {
osmConnection.isLoggedIn.addCallbackAndRun((loggedIn) => {
amendedPrefs.data["_loggedIn"] = "" + loggedIn
amendedPrefs.ping()
})

View file

@ -1,14 +1,42 @@
import { Utils } from "../../Utils"
/** This code is autogenerated - do not edit. Edit ./assets/layers/usersettings/usersettings.json instead */
export class ThemeMetaTagging {
public static readonly themeName = "usersettings"
public static readonly themeName = "usersettings"
public metaTaggging_for_usersettings(feat: {properties: Record<string, string>}) {
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_md', () => feat.properties._description.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)?.at(1) )
Utils.AddLazyProperty(feat.properties, '_d', () => feat.properties._description?.replace(/&lt;/g,'<')?.replace(/&gt;/g,'>') ?? '' )
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_a', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.href.match(/mastodon|en.osm.town/) !== null)[0]?.href }) (feat) )
Utils.AddLazyProperty(feat.properties, '_mastodon_link', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.getAttribute("rel")?.indexOf('me') >= 0)[0]?.href})(feat) )
Utils.AddLazyProperty(feat.properties, '_mastodon_candidate', () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a )
feat.properties['__current_backgroun'] = 'initial_value'
}
}
public metaTaggging_for_usersettings(feat: { properties: Record<string, string> }) {
Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_md", () =>
feat.properties._description
.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)
?.at(1)
)
Utils.AddLazyProperty(
feat.properties,
"_d",
() => feat.properties._description?.replace(/&lt;/g, "<")?.replace(/&gt;/g, ">") ?? ""
)
Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_a", () =>
((feat) => {
const e = document.createElement("div")
e.innerHTML = feat.properties._d
return Array.from(e.getElementsByTagName("a")).filter(
(a) => a.href.match(/mastodon|en.osm.town/) !== null
)[0]?.href
})(feat)
)
Utils.AddLazyProperty(feat.properties, "_mastodon_link", () =>
((feat) => {
const e = document.createElement("div")
e.innerHTML = feat.properties._d
return Array.from(e.getElementsByTagName("a")).filter(
(a) => a.getAttribute("rel")?.indexOf("me") >= 0
)[0]?.href
})(feat)
)
Utils.AddLazyProperty(
feat.properties,
"_mastodon_candidate",
() => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a
)
feat.properties["__current_backgroun"] = "initial_value"
}
}

View file

@ -51,7 +51,7 @@ export interface NSIItem {
}
readonly tags: Readonly<Record<string, string>>
fromTemplate?: boolean
ext? : string
ext?: string
}
export default class NameSuggestionIndex {
@ -214,9 +214,7 @@ export default class NameSuggestionIndex {
for (const nsiItem of actualBrands) {
const tags = nsiItem.tags
const frequency = frequencies[nsiItem.displayName]
const iconUrl = this.getIconExternalUrl(nsiItem, type)
const hasIcon = iconUrl !== undefined
const icon = hasIcon ? this.getIconUrl(nsiItem, type) : undefined
const icon = this.getIconUrl(nsiItem)
mappings.push({
if: new Tag(type, tags[type]),
addExtraTags: Object.keys(tags)
@ -274,7 +272,7 @@ export default class NameSuggestionIndex {
const values = tags[osmKey]
for (const osmValue of values) {
const suggestions = this.getSuggestionsForKV(type, osmKey, osmValue)
if(!suggestions){
if (!suggestions) {
console.warn("No suggestions found for", type, osmKey, osmValue)
continue
}
@ -399,9 +397,14 @@ export default class NameSuggestionIndex {
return logos?.facebook ?? logos?.wikidata
}
public getIconUrl(nsiItem: NSIItem, type: string) {
public getIconUrl(nsiItem: NSIItem): string | undefined {
if (!nsiItem.ext) {
// No extension -> there is no logo
return undefined
}
return "./assets/data/nsi/logos/" + nsiItem.id + "." + nsiItem.ext
}
private static readonly brandPrefix = ["name", "alt_name", "operator", "brand"] as const
/**

View file

@ -6,8 +6,8 @@ import { UIEventSource } from "../UIEventSource"
export default class ThemeViewStateHashActor {
private readonly _state: {
indexedFeatures: IndexedFeatureSource,
selectedElement: UIEventSource<Feature>,
indexedFeatures: IndexedFeatureSource
selectedElement: UIEventSource<Feature>
guistate: MenuState
}
private isUpdatingHash = false
@ -22,7 +22,7 @@ export default class ThemeViewStateHashActor {
"",
"The possible hashes are:",
"",
MenuState.pageNames.map((tab) => "`" + tab + "`").join(",")
MenuState.pageNames.map((tab) => "`" + tab + "`").join(","),
]
/**
@ -35,9 +35,9 @@ export default class ThemeViewStateHashActor {
*
*/
constructor(state: {
indexedFeatures: IndexedFeatureSource,
selectedElement: UIEventSource<Feature>,
guistate: MenuState,
indexedFeatures: IndexedFeatureSource
selectedElement: UIEventSource<Feature>
guistate: MenuState
}) {
this._state = state