Feature: be able to set a default background layer, fix background layer query parameter

This commit is contained in:
Pieter Vander Vennet 2023-09-24 16:34:36 +02:00
parent 93a30fdba5
commit 456da1b6c3
7 changed files with 401 additions and 280 deletions

View file

@ -0,0 +1,67 @@
import { Store, UIEventSource } from "../UIEventSource";
import { RasterLayerPolygon } from "../../Models/RasterLayers";
/**
* Selects the appropriate raster layer as background for the given query parameter, theme setting, user preference or default value.
*
* It the requested layer is not available, a layer of the same type will be selected.
*/
export class PreferredRasterLayerSelector {
private readonly _rasterLayerSetting: UIEventSource<RasterLayerPolygon>;
private readonly _availableLayers: Store<RasterLayerPolygon[]>;
private readonly _preferredBackgroundLayer: UIEventSource<string | "photo" | "map" | "osmbasedmap" | undefined>;
private readonly _queryParameter: UIEventSource<string>;
constructor(rasterLayerSetting: UIEventSource<RasterLayerPolygon>, availableLayers: Store<RasterLayerPolygon[]>, queryParameter: UIEventSource<string>, preferredBackgroundLayer: UIEventSource<string | "photo" | "map" | "osmbasedmap" | undefined>) {
this._rasterLayerSetting = rasterLayerSetting;
this._availableLayers = availableLayers;
this._queryParameter = queryParameter;
this._preferredBackgroundLayer = preferredBackgroundLayer;
const self = this;
this._rasterLayerSetting.addCallbackD(layer => {
if (layer.properties.id !== this._queryParameter.data) {
this._queryParameter.setData(undefined);
return true;
}
});
this._queryParameter.addCallbackAndRunD(_ => {
const isApplied = self.updateLayer();
if (!isApplied) {
// A different layer was set as background
// We remove this queryParameter instead
self._queryParameter.setData(undefined);
return true; // Unregister
}
});
this._preferredBackgroundLayer.addCallbackD(_ => self.updateLayer());
this._availableLayers.addCallbackD(_ => self.updateLayer());
}
/**
* Returns 'true' if the target layer is set or is the current layer
* @private
*/
private updateLayer() {
// What is the ID of the layer we have to (try to) load?
const targetLayerId = this._queryParameter.data ?? this._preferredBackgroundLayer.data;
const available = this._availableLayers.data;
const isCategory = targetLayerId === "photo" || targetLayerId === "osmbasedmap" || targetLayerId === "map"
const foundLayer = isCategory ? available.find(l => l.properties.category === targetLayerId) : available.find(l => l.properties.id === targetLayerId);
if (foundLayer) {
this._rasterLayerSetting.setData(foundLayer);
return true;
}
// The current layer is not in view
}
}

View file

@ -198,7 +198,7 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches {
this.backgroundLayerId = QueryParameters.GetQueryParameter(
"background",
layoutToUse?.defaultBackgroundId ?? "osm",
layoutToUse?.defaultBackgroundId,
"The id of the background layer to start with"
)
}

View file

@ -17,6 +17,7 @@ import FeatureSwitchState from "./FeatureSwitchState"
import Constants from "../../Models/Constants"
import { QueryParameters } from "../Web/QueryParameters"
import { ThemeMetaTagging } from "./UserSettingsMetaTagging"
import { MapProperties } from "../../Models/MapProperties";
/**
* The part of the state which keeps track of user-related stuff, e.g. the OSM-connection,
@ -41,6 +42,7 @@ export default class UserRelatedState {
public readonly fixateNorth: UIEventSource<undefined | "yes">
public readonly homeLocation: FeatureSource
public readonly language: UIEventSource<string>
public readonly preferredBackgroundLayer: UIEventSource<string | "photo" | "map" | "osmbasedmap" | undefined>
/**
* The number of seconds that the GPS-locations are stored in memory.
* Time in seconds
@ -52,16 +54,23 @@ export default class UserRelatedState {
/**
* Preferences as tags exposes many preferences and state properties as record.
* This is used to bridge the internal state with the usersettings.json layerconfig file
*
* Some metainformation that should not be edited starts with a single underscore
* Constants and query parameters start with two underscores
* Note: these are linked via OsmConnection.preferences which exports all preferences as UIEventSource
*/
public readonly preferencesAsTags: UIEventSource<Record<string, string>>
private readonly _mapProperties: MapProperties;
constructor(
osmConnection: OsmConnection,
availableLanguages?: string[],
layout?: LayoutConfig,
featureSwitches?: FeatureSwitchState
featureSwitches?: FeatureSwitchState,
mapProperties?: MapProperties
) {
this.osmConnection = osmConnection
this._mapProperties = mapProperties;
{
const translationMode: UIEventSource<undefined | "true" | "false" | "mobile" | string> =
this.osmConnection.GetPreference("translation-mode", "false")
@ -90,10 +99,13 @@ export default class UserRelatedState {
)
this.language = this.osmConnection.GetPreference("language")
this.showTags = <UIEventSource<any>>this.osmConnection.GetPreference("show_tags")
this.fixateNorth = <any>this.osmConnection.GetPreference("fixate-north")
this.fixateNorth = <UIEventSource<"yes">>this.osmConnection.GetPreference("fixate-north")
this.mangroveIdentity = new MangroveIdentity(
this.osmConnection.GetLongPreference("identity", "mangrove")
)
this.preferredBackgroundLayer= this.osmConnection.GetPreference("preferred-background-layer", undefined, {
documentation: "The ID of a layer or layer category that MapComplete uses by default"
})
this.installedUserThemes = this.InitInstalledUserThemes()
@ -260,6 +272,7 @@ export default class UserRelatedState {
amendedPrefs.data["__url_parameter_initialized:" + key] = "yes"
}
const osmConnection = this.osmConnection
osmConnection.preferencesHandler.preferences.addCallback((newPrefs) => {
for (const k in newPrefs) {
@ -280,7 +293,6 @@ export default class UserRelatedState {
amendedPrefs.ping()
console.log("Amended prefs are:", amendedPrefs.data)
})
const usersettingsConfig = UserRelatedState.usersettingsConfig
const translationMode = osmConnection.GetPreference("translation-mode")
Locale.language.mapD(
@ -335,25 +347,6 @@ export default class UserRelatedState {
}
usersettingMetaTagging.metaTaggging_for_usersettings({ properties: amendedPrefs.data })
/*for (const [name, code, _] of usersettingsConfig.calculatedTags) {
try {
let result = new Function("feat", "return " + code + ";")({
properties: amendedPrefs.data,
})
if (result !== undefined && result !== "" && result !== null) {
if (typeof result !== "string") {
result = JSON.stringify(result)
}
amendedPrefs.data[name] = result
}
} catch (e) {
console.error(
"Calculating a tag for userprofile-settings failed for variable",
name,
e
)
}
}*/
const simplifiedName = userDetails.name.toLowerCase().replace(/\s+/g, "")
const isTranslator = translators.contributors.find(
@ -407,6 +400,13 @@ export default class UserRelatedState {
}
}
this._mapProperties?.rasterLayer?.addCallbackAndRun(l => {
amendedPrefs.data["__current_background"] = l?.properties?.id
amendedPrefs.ping()
})
return amendedPrefs
}
}

View file

@ -9,5 +9,6 @@ export class ThemeMetaTagging {
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 )
Utils.AddLazyProperty(feat.properties, '__backgroundLayerId', () => 'some value to let the validation run through' )
}
}