Refactoring: use theme instead of layout in a lot of places

This commit is contained in:
Pieter Vander Vennet 2024-10-17 04:06:03 +02:00
parent 9427083939
commit bdc9ba52a6
104 changed files with 445 additions and 449 deletions

View file

@ -55,7 +55,7 @@ export default class Constants {
// The user journey states thresholds when a new feature gets unlocked
public static userJourney = {
moreScreenUnlock: 1,
personalLayoutUnlock: 5,
personalThemeUnlock: 5,
historyLinkVisible: 10,
deletePointsOfOthersUnlock: 20,
tagsVisibleAt: 25,

View file

@ -1,5 +1,5 @@
import { Conversion, DesugaringStep } from "./Conversion"
import { LayoutConfigJson } from "../Json/LayoutConfigJson"
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import { Utils } from "../../../Utils"
import metapaths from "../../../assets/schemas/layoutconfigmeta.json"
import tagrenderingmetapaths from "../../../assets/schemas/questionabletagrenderingconfigmeta.json"
@ -9,7 +9,7 @@ import { parse as parse_html } from "node-html-parser"
import { ConversionContext } from "./ConversionContext"
export class ExtractImages extends Conversion<
LayoutConfigJson,
ThemeConfigJson,
{ path: string; context: string }[]
> {
private static readonly layoutMetaPaths = metapaths.filter((mp) => {
@ -109,7 +109,7 @@ export class ExtractImages extends Conversion<
*
*/
convert(
json: LayoutConfigJson,
json: ThemeConfigJson,
context: ConversionContext
): { path: string; context: string }[] {
const allFoundImages: { path: string; context: string }[] = []
@ -243,7 +243,7 @@ export class ExtractImages extends Conversion<
}
}
export class FixImages extends DesugaringStep<LayoutConfigJson> {
export class FixImages extends DesugaringStep<ThemeConfigJson> {
private readonly _knownImages: Set<string>
constructor(knownImages: Set<string>) {
@ -289,7 +289,7 @@ export class FixImages extends DesugaringStep<LayoutConfigJson> {
* fixed.layers[0]["pointRendering"][0].marker[0].icon // => "https://raw.githubusercontent.com/seppesantens/MapComplete-Themes/main/VerkeerdeBordenDatabank/TS_bolt.svg"
* fixed.layers[0]["pointRendering"][0].iconBadges[0].then.mappings[0].then // => "https://raw.githubusercontent.com/seppesantens/MapComplete-Themes/main/VerkeerdeBordenDatabank/Something.svg"
*/
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
let url: URL
try {
url = new URL(json.id)

View file

@ -1,4 +1,4 @@
import { LayoutConfigJson } from "../Json/LayoutConfigJson"
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import { Utils } from "../../../Utils"
import LineRenderingConfigJson from "../Json/LineRenderingConfigJson"
import { LayerConfigJson } from "../Json/LayerConfigJson"
@ -257,12 +257,12 @@ export class UpdateLegacyLayer extends DesugaringStep<
}
}
class UpdateLegacyTheme extends DesugaringStep<LayoutConfigJson> {
class UpdateLegacyTheme extends DesugaringStep<ThemeConfigJson> {
constructor() {
super("Small fixes in the theme config", ["roamingRenderings"], "UpdateLegacyTheme")
}
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
const oldThemeConfig = { ...json }
if (oldThemeConfig.socialImage === "") {
@ -311,7 +311,7 @@ class UpdateLegacyTheme extends DesugaringStep<LayoutConfigJson> {
}
}
export class FixLegacyTheme extends Fuse<LayoutConfigJson> {
export class FixLegacyTheme extends Fuse<ThemeConfigJson> {
constructor() {
super(
"Fixes a legacy theme to the modern JSON format geared to humans. Syntactic sugars are kept (i.e. no tagRenderings are expandend, no dependencies are automatically gathered)",

View file

@ -1,5 +1,5 @@
import { Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, Pass, SetDefault } from "./Conversion"
import { LayoutConfigJson } from "../Json/LayoutConfigJson"
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import { PrepareLayer } from "./PrepareLayer"
import { LayerConfigJson } from "../Json/LayerConfigJson"
import { Utils } from "../../../Utils"
@ -165,7 +165,7 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
}
}
class AddDefaultLayers extends DesugaringStep<LayoutConfigJson> {
class AddDefaultLayers extends DesugaringStep<ThemeConfigJson> {
private readonly _state: DesugaringContext
constructor(state: DesugaringContext) {
@ -177,7 +177,7 @@ class AddDefaultLayers extends DesugaringStep<LayoutConfigJson> {
this._state = state
}
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
const state = this._state
json.layers = Utils.NoNull([...(json.layers ?? [])])
const alreadyLoaded = new Set(json.layers.map((l) => l["id"]))
@ -209,7 +209,7 @@ class AddDefaultLayers extends DesugaringStep<LayoutConfigJson> {
}
}
class AddContextToTranslationsInLayout extends DesugaringStep<LayoutConfigJson> {
class AddContextToTranslationsInLayout extends DesugaringStep<ThemeConfigJson> {
constructor() {
super(
"Adds context to translations, including the prefix 'themes:json.id'; this is to make sure terms in an 'overrides' or inline layer are linkable too",
@ -218,8 +218,8 @@ class AddContextToTranslationsInLayout extends DesugaringStep<LayoutConfigJson>
)
}
convert(json: LayoutConfigJson): LayoutConfigJson {
const conversion = new AddContextToTranslations<LayoutConfigJson>("themes:")
convert(json: ThemeConfigJson): ThemeConfigJson {
const conversion = new AddContextToTranslations<ThemeConfigJson>("themes:")
// The context is used to generate the 'context' in the translation .It _must_ be `json.id` to correctly link into weblate
return conversion.convert(
json,
@ -228,7 +228,7 @@ class AddContextToTranslationsInLayout extends DesugaringStep<LayoutConfigJson>
}
}
class ApplyOverrideAll extends DesugaringStep<LayoutConfigJson> {
class ApplyOverrideAll extends DesugaringStep<ThemeConfigJson> {
constructor() {
super(
"Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards",
@ -237,7 +237,7 @@ class ApplyOverrideAll extends DesugaringStep<LayoutConfigJson> {
)
}
convert(json: LayoutConfigJson, ctx: ConversionContext): LayoutConfigJson {
convert(json: ThemeConfigJson, ctx: ConversionContext): ThemeConfigJson {
const overrideAll = json.overrideAll
if (overrideAll === undefined) {
return json
@ -278,7 +278,7 @@ class ApplyOverrideAll extends DesugaringStep<LayoutConfigJson> {
}
}
class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
class AddDependencyLayersToTheme extends DesugaringStep<ThemeConfigJson> {
private readonly _state: DesugaringContext
constructor(state: DesugaringContext) {
@ -390,7 +390,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
return dependenciesToAdd
}
convert(theme: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
convert(theme: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
const state = this._state
const allKnownLayers: Map<string, LayerConfigJson> = state.sharedLayers
const knownTagRenderings: Map<string, TagRenderingConfigJson> = state.tagRenderings
@ -428,7 +428,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
}
}
class PreparePersonalTheme extends DesugaringStep<LayoutConfigJson> {
class PreparePersonalTheme extends DesugaringStep<ThemeConfigJson> {
private readonly _state: DesugaringContext
constructor(state: DesugaringContext) {
@ -436,7 +436,7 @@ class PreparePersonalTheme extends DesugaringStep<LayoutConfigJson> {
this._state = state
}
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
if (json.id !== "personal") {
return json
}
@ -452,7 +452,7 @@ class PreparePersonalTheme extends DesugaringStep<LayoutConfigJson> {
}
}
class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<LayoutConfigJson> {
class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<ThemeConfigJson> {
constructor() {
super(
"Generates a warning if a theme uses an unsubstituted layer",
@ -461,7 +461,7 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<LayoutConfigJson>
)
}
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
if (json.hideFromOverview === true) {
return json
}
@ -503,7 +503,7 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<LayoutConfigJson>
}
}
class PostvalidateTheme extends DesugaringStep<LayoutConfigJson> {
class PostvalidateTheme extends DesugaringStep<ThemeConfigJson> {
private readonly _state: DesugaringContext
constructor(state: DesugaringContext) {
@ -511,7 +511,7 @@ class PostvalidateTheme extends DesugaringStep<LayoutConfigJson> {
this._state = state
}
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
for (const l of json.layers) {
const layer = <LayerConfigJson>l
const basedOn = <string>layer["_basedOn"]
@ -582,7 +582,7 @@ class PostvalidateTheme extends DesugaringStep<LayoutConfigJson> {
}
}
export class PrepareTheme extends Fuse<LayoutConfigJson> {
export class PrepareTheme extends Fuse<ThemeConfigJson> {
private state: DesugaringContext
constructor(
@ -616,7 +616,7 @@ export class PrepareTheme extends Fuse<LayoutConfigJson> {
this.state = state
}
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
const result = super.convert(json, context)
if ((this.state.publicLayers?.size ?? 0) === 0) {
// THis is a bootstrapping run, no need to already set this flag

View file

@ -1,13 +1,13 @@
import { DesugaringStep } from "./Conversion"
import { LayoutConfigJson } from "../Json/LayoutConfigJson"
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import { AvailableRasterLayers } from "../../RasterLayers"
import { ExtractImages } from "./FixImages"
import { ConversionContext } from "./ConversionContext"
import LayoutConfig from "../LayoutConfig"
import ThemeConfig from "../ThemeConfig"
import { Utils } from "../../../Utils"
import { DetectDuplicatePresets, DoesImageExist, ValidateLanguageCompleteness } from "./Validation"
export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
export class ValidateTheme extends DesugaringStep<ThemeConfigJson> {
/**
* The paths where this layer is originally saved. Triggers some extra checks
* @private
@ -33,8 +33,8 @@ export class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
}
}
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
const theme = new LayoutConfig(json, this._isBuiltin)
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
const theme = new ThemeConfig(json, this._isBuiltin)
{
// Legacy format checks
if (this._isBuiltin) {

View file

@ -1,10 +1,10 @@
import { Bypass, Each, Fuse, On } from "./Conversion"
import { LayoutConfigJson } from "../Json/LayoutConfigJson"
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import Constants from "../../Constants"
import { DoesImageExist, ValidateLayerConfig } from "./Validation"
import { ValidateTheme } from "./ValidateTheme"
export class ValidateThemeAndLayers extends Fuse<LayoutConfigJson> {
export class ValidateThemeAndLayers extends Fuse<ThemeConfigJson> {
constructor(
doesImageExist: DoesImageExist,
path: string,

View file

@ -4,8 +4,8 @@ import LayerConfig from "../LayerConfig"
import { Utils } from "../../../Utils"
import Constants from "../../Constants"
import { Translation } from "../../../UI/i18n/Translation"
import { LayoutConfigJson } from "../Json/LayoutConfigJson"
import LayoutConfig from "../LayoutConfig"
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import ThemeConfig from "../ThemeConfig"
import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"
import { TagUtils } from "../../../Logic/Tags/TagUtils"
import { And } from "../../../Logic/Tags/And"
@ -23,7 +23,7 @@ import { PrevalidateLayer } from "./PrevalidateLayer"
import { AvailableRasterLayers } from "../../RasterLayers"
import { eliCategory } from "../../RasterLayerProperties"
export class ValidateLanguageCompleteness extends DesugaringStep<LayoutConfig> {
export class ValidateLanguageCompleteness extends DesugaringStep<ThemeConfig> {
private readonly _languages: string[]
constructor(...languages: string[]) {
@ -35,7 +35,7 @@ export class ValidateLanguageCompleteness extends DesugaringStep<LayoutConfig> {
this._languages = languages ?? ["en"]
}
convert(obj: LayoutConfig, context: ConversionContext): LayoutConfig {
convert(obj: ThemeConfig, context: ConversionContext): ThemeConfig {
const origLayers = obj.layers
obj.layers = [...obj.layers].filter((l) => l["id"] !== "favourite")
const translations = Translation.ExtractAllTranslationsFrom(obj)
@ -128,7 +128,7 @@ export class DoesImageExist extends DesugaringStep<string> {
}
}
class OverrideShadowingCheck extends DesugaringStep<LayoutConfigJson> {
class OverrideShadowingCheck extends DesugaringStep<ThemeConfigJson> {
constructor() {
super(
"Checks that an 'overrideAll' does not override a single override",
@ -137,7 +137,7 @@ class OverrideShadowingCheck extends DesugaringStep<LayoutConfigJson> {
)
}
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
const overrideAll = json.overrideAll
if (overrideAll === undefined) {
return json
@ -170,12 +170,12 @@ class OverrideShadowingCheck extends DesugaringStep<LayoutConfigJson> {
}
}
class MiscThemeChecks extends DesugaringStep<LayoutConfigJson> {
class MiscThemeChecks extends DesugaringStep<ThemeConfigJson> {
constructor() {
super("Miscelleanous checks on the theme", [], "MiscThemesChecks")
}
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
if (json.id !== "personal" && (json.layers === undefined || json.layers.length === 0)) {
context.err("The theme " + json.id + " has no 'layers' defined")
}
@ -240,7 +240,7 @@ class MiscThemeChecks extends DesugaringStep<LayoutConfigJson> {
}
}
export class PrevalidateTheme extends Fuse<LayoutConfigJson> {
export class PrevalidateTheme extends Fuse<ThemeConfigJson> {
constructor() {
super(
"Various consistency checks on the raw JSON",
@ -905,7 +905,7 @@ export class ValidateFilter extends DesugaringStep<FilterConfigJson> {
export class DetectDuplicateFilters extends DesugaringStep<{
layers: LayerConfigJson[]
themes: LayoutConfigJson[]
themes: ThemeConfigJson[]
}> {
constructor() {
super(
@ -916,15 +916,15 @@ export class DetectDuplicateFilters extends DesugaringStep<{
}
convert(
json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] },
json: { layers: LayerConfigJson[]; themes: ThemeConfigJson[] },
context: ConversionContext,
): { layers: LayerConfigJson[]; themes: LayoutConfigJson[] } {
): { layers: LayerConfigJson[]; themes: ThemeConfigJson[] } {
const { layers, themes } = json
const perOsmTag = new Map<
string,
{
layer: LayerConfigJson
layout: LayoutConfigJson | undefined
theme: ThemeConfigJson | undefined
filter: FilterConfigJson
}[]
>()
@ -955,10 +955,10 @@ export class DetectDuplicateFilters extends DesugaringStep<{
return
}
let msg = "Possible duplicate filter: " + key
for (const { filter, layer, layout } of value) {
for (const { filter, layer, theme } of value) {
let id = ""
if (layout !== undefined) {
id = layout.id + ":"
if (theme !== undefined) {
id = theme.id + ":"
}
msg += `\n - ${id}${layer.id}.${filter.id}`
}
@ -977,11 +977,11 @@ export class DetectDuplicateFilters extends DesugaringStep<{
string,
{
layer: LayerConfigJson
layout: LayoutConfigJson | undefined
theme: ThemeConfigJson | undefined
filter: FilterConfigJson
}[]
>,
layout?: LayoutConfigJson | undefined,
theme?: ThemeConfigJson | undefined,
): void {
if (layer.filter === undefined || layer.filter === null) {
return
@ -1009,14 +1009,14 @@ export class DetectDuplicateFilters extends DesugaringStep<{
perOsmTag.get(key).push({
layer,
filter,
layout,
theme,
})
}
}
}
}
export class DetectDuplicatePresets extends DesugaringStep<LayoutConfig> {
export class DetectDuplicatePresets extends DesugaringStep<ThemeConfig> {
constructor() {
super(
"Detects mappings which have identical (english) names or identical mappings.",
@ -1025,7 +1025,7 @@ export class DetectDuplicatePresets extends DesugaringStep<LayoutConfig> {
)
}
convert(json: LayoutConfig, context: ConversionContext): LayoutConfig {
convert(json: ThemeConfig, context: ConversionContext): ThemeConfig {
const presets: PresetConfig[] = [].concat(...json.layers.map((l) => l.presets))
const enNames = presets.map((p) => p.title.textFor("en"))
@ -1074,7 +1074,7 @@ export class DetectDuplicatePresets extends DesugaringStep<LayoutConfig> {
}
export class ValidateThemeEnsemble extends Conversion<
LayoutConfig[],
ThemeConfig[],
Map<
string,
{
@ -1093,7 +1093,7 @@ export class ValidateThemeEnsemble extends Conversion<
}
convert(
json: LayoutConfig[],
json: ThemeConfig[],
context: ConversionContext,
): Map<
string,

View file

@ -62,7 +62,7 @@ export default class FilterConfig {
const fields: { name: string; type: ValidatorType }[] = (option.fields ?? []).map((f, i) => {
const type = <ValidatorType> f.type ?? "regex"
if(Validators.availableTypes.indexOf(type) < 0){
throw `Invalid filter: type is not a valid validator. Did you mean one of ${Utils.sortedByLevenshteinDistance(type, <any>Validators.availableTypes, x => x).slice(0, 3)}`
throw `Invalid filter: type is not a valid validator. Did you mean one of ${Utils.sortedByLevenshteinDistance(type, <ReadonlyArray<string>>Validators.availableTypes, x => x).slice(0, 3)}`
}
// Type is validated against 'ValidatedTextField' in Validation.ts, in ValidateFilterConfig
if (f.name === undefined || f.name === "" || f.name.match(/[a-z0-9_-]+/) == null) {

View file

@ -16,7 +16,7 @@ import { Translatable } from "./Translatable"
*
* General remark: a type (string | any) indicates either a fixed or a translatable string.
*/
export interface LayoutConfigJson {
export interface ThemeConfigJson {
/**
* question: What is the id of this layout?
*

View file

@ -1,5 +1,5 @@
import { Translation } from "../../UI/i18n/Translation"
import { LayoutConfigJson } from "./Json/LayoutConfigJson"
import { ThemeConfigJson } from "./Json/ThemeConfigJson"
import LayerConfig from "./LayerConfig"
import { LayerConfigJson } from "./Json/LayerConfigJson"
import Constants from "../Constants"
@ -13,7 +13,7 @@ import { Translatable } from "./Json/Translatable"
/**
* Minimal information about a theme
**/
export class MinimalLayoutInformation {
export class MinimalThemeInformation {
id: string
icon: string
title: Translatable
@ -27,7 +27,7 @@ export class MinimalLayoutInformation {
/**
* Minimal information about a theme
**/
export class LayoutInformation {
export class ThemeInformation {
id: string
icon: string
title: Translatable | Translation
@ -39,7 +39,7 @@ export class LayoutInformation {
}
export default class LayoutConfig implements LayoutInformation {
export default class ThemeConfig implements ThemeInformation {
public static readonly defaultSocialImage = "assets/SocialImage.png"
public readonly id: string
public readonly credits?: string
@ -57,7 +57,6 @@ export default class LayoutConfig implements LayoutInformation {
public readonly startZoom: number
public readonly startLat: number
public readonly startLon: number
public widenFactor: number
public defaultBackgroundId?: string
public layers: LayerConfig[]
public tileLayerSources: (RasterLayerProperties & { defaultState?: true | boolean })[]
@ -92,11 +91,11 @@ export default class LayoutConfig implements LayoutInformation {
public readonly definitionRaw?: string
private readonly layersDict: Map<string, LayerConfig>
private readonly source: LayoutConfigJson
private readonly source: ThemeConfigJson
public readonly enableCache: boolean
constructor(
json: LayoutConfigJson,
json: ThemeConfigJson,
official = true,
options?: {
definedAtUrl?: string
@ -167,7 +166,7 @@ export default class LayoutConfig implements LayoutInformation {
? undefined
: new Translation(json.descriptionTail, "themes:" + context + ".descriptionTail")
this.icon = json.icon
this.socialImage = json.socialImage ?? LayoutConfig.defaultSocialImage
this.socialImage = json.socialImage ?? ThemeConfig.defaultSocialImage
if (this.socialImage === "") {
if (official) {
throw "Theme " + json.id + " has empty string as social image"
@ -176,7 +175,6 @@ export default class LayoutConfig implements LayoutInformation {
this.startZoom = json.startZoom
this.startLat = json.startLat
this.startLon = json.startLon
this.widenFactor = 1.5
this.defaultBackgroundId = json.defaultBackgroundId
this.tileLayerSources = json.tileLayerSources ?? []

View file

@ -1,4 +1,4 @@
import LayoutConfig from "./ThemeConfig/LayoutConfig"
import ThemeConfig from "./ThemeConfig/ThemeConfig"
import { SpecialVisualizationState } from "../UI/SpecialVisualization"
import { Changes } from "../Logic/Osm/Changes"
import { Store, UIEventSource } from "../Logic/UIEventSource"
@ -18,7 +18,7 @@ import UserRelatedState from "../Logic/State/UserRelatedState"
import LayerConfig from "./ThemeConfig/LayerConfig"
import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler"
import { AvailableRasterLayers, RasterLayerPolygon, RasterLayerUtils } from "./RasterLayers"
import LayoutSource from "../Logic/FeatureSource/Sources/LayoutSource"
import ThemeSource from "../Logic/FeatureSource/Sources/ThemeSource"
import StaticFeatureSource from "../Logic/FeatureSource/Sources/StaticFeatureSource"
import FeaturePropertiesStore from "../Logic/FeatureSource/Actors/FeaturePropertiesStore"
import PerLayerFeatureSourceSplitter from "../Logic/FeatureSource/PerLayerFeatureSourceSplitter"
@ -80,7 +80,7 @@ import { PanoramaxUploader } from "../Logic/ImageProviders/Panoramax"
* It ties up all the needed elements and starts some actors.
*/
export default class ThemeViewState implements SpecialVisualizationState {
readonly layout: LayoutConfig
readonly theme: ThemeConfig
readonly map: UIEventSource<MlMap>
readonly changes: Changes
readonly featureSwitches: FeatureSwitchState
@ -104,7 +104,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
readonly fullNodeDatabase?: FullNodeDatabaseSource
readonly historicalUserLocations: WritableFeatureSource<Feature<Point>>
readonly indexedFeatures: IndexedFeatureSource & LayoutSource
readonly indexedFeatures: IndexedFeatureSource & ThemeSource
readonly currentView: FeatureSource<Feature<Polygon>>
readonly featuresInView: FeatureSource
readonly favourites: FavouritesFeatureSource
@ -160,9 +160,9 @@ export default class ThemeViewState implements SpecialVisualizationState {
*/
public readonly featureSummary: SummaryTileSourceRewriter
constructor(layout: LayoutConfig, mvtAvailableLayers: Set<string>) {
constructor(layout: ThemeConfig, mvtAvailableLayers: Set<string>) {
Utils.initDomPurify()
this.layout = layout
this.theme = layout
this.featureSwitches = new FeatureSwitchState(layout)
this.guistate = new MenuState(
this.featureSwitches.featureSwitchWelcomeMessage.data,
@ -218,7 +218,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
{
const overlayLayerStates = new Map<string, { isDisplayed: UIEventSource<boolean> }>()
for (const rasterInfo of this.layout.tileLayerSources) {
for (const rasterInfo of this.theme.tileLayerSources) {
const isDisplayed = QueryParameters.GetBooleanQueryParameter(
"overlay-" + rasterInfo.id,
rasterInfo.defaultState ?? true,
@ -236,11 +236,11 @@ export default class ThemeViewState implements SpecialVisualizationState {
* A bit tricky, as this is heavily intertwined with the 'changes'-element, which generates a stream of new and changed features too
*/
if (this.layout.layers.some((l) => l._needsFullNodeDatabase)) {
if (this.theme.layers.some((l) => l._needsFullNodeDatabase)) {
this.fullNodeDatabase = new FullNodeDatabaseSource()
}
const layoutSource = new LayoutSource(
const layoutSource = new ThemeSource(
layout.layers,
this.featureSwitches,
this.mapProperties,
@ -340,7 +340,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
})
this.lastClickObject = new LastClickFeatureSource(
this.layout,
this.theme,
this.mapProperties.lastClickLocation,
this.userRelatedState.addNewFeatureMode,
)
@ -414,7 +414,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
const storage = new SaveFeatureSourceToLocalStorage(
this.osmConnection.Backend(),
fs.layer.layerDef.id,
LayoutSource.fromCacheZoomLevel,
ThemeSource.fromCacheZoomLevel,
fs,
this.featureProperties,
fs.layer.layerDef.maxAgeOfCache,
@ -509,7 +509,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
}
})
this.userRelatedState.markLayoutAsVisited(this.layout)
this.userRelatedState.markLayoutAsVisited(this.theme)
this.selectedElement.addCallback((selected) => {
if (selected === undefined) {
@ -517,8 +517,8 @@ export default class ThemeViewState implements SpecialVisualizationState {
}
})
if (this.layout.customCss !== undefined && window.location.pathname.indexOf("theme") >= 0) {
Utils.LoadCustomCss(this.layout.customCss)
if (this.theme.customCss !== undefined && window.location.pathname.indexOf("theme") >= 0) {
Utils.LoadCustomCss(this.theme.customCss)
}
Hash.hash.addCallbackAndRunD((hash) => {
@ -738,11 +738,11 @@ export default class ThemeViewState implements SpecialVisualizationState {
/**
* MaxZoom for the summary layer
*/
const normalLayers = this.layout.layers.filter(l => l.isNormal())
const normalLayers = this.theme.layers.filter(l => l.isNormal())
const maxzoom = Math.min(...normalLayers.map((l) => l.minzoom))
const layers = this.layout.layers.filter(
const layers = this.theme.layers.filter(
(l) =>
Constants.priviliged_layers.indexOf(<any>l.id) < 0 &&
l.source.geojsonSource === undefined &&
@ -796,8 +796,8 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.closestFeatures.registerSource(specialLayers.favourite, "favourite")
if (this.layout?.lockLocation) {
const bbox = new BBox(<any>this.layout.lockLocation)
if (this.theme?.lockLocation) {
const bbox = new BBox(<any>this.theme.lockLocation)
this.mapProperties.maxbounds.setData(bbox)
ShowDataLayer.showRange(
this.map,
@ -805,7 +805,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.featureSwitches.featureSwitchIsTesting,
)
}
const currentViewLayer = this.layout.layers.find((l) => l.id === "current_view")
const currentViewLayer = this.theme.layers.find((l) => l.id === "current_view")
if (currentViewLayer?.tagRenderings?.length > 0) {
const params = MetaTagging.createExtraFuncParams(this)
this.featureProperties.trackFeatureSource(specialLayers.current_view)
@ -814,7 +814,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
features,
params,
currentViewLayer,
this.layout,
this.theme,
this.osmObjectDownloader,
this.featureProperties,
)
@ -909,9 +909,9 @@ export default class ThemeViewState implements SpecialVisualizationState {
*/
private initActors() {
if (!this.layout.official) {
if (!this.theme.official) {
// Add custom themes to the "visited custom themes"
const th = this.layout
const th = this.theme
this.userRelatedState.addUnofficialTheme({
id: th.id,
icon: th.icon,
@ -945,7 +945,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.selectedElement.addCallbackD(selected => {
const [osm_type, osm_id] = selected.properties.id.split("/")
const [lon, lat] = GeoOperations.centerpointCoordinates(selected)
const layer = this.layout.getMatchingLayer(selected.properties)
const layer = this.theme.getMatchingLayer(selected.properties)
const nameOptions = [
selected?.properties?.name,
@ -987,7 +987,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
}
/**
* Searches the appropriate layer - will first try if a special layer matches; if not, a normal layer will be used by delegating to the layout
* Searches the appropriate layer - will first try if a special layer matches; if not, a normal layer will be used by delegating to the theme
*/
public getMatchingLayer(properties: Record<string, string>) {
@ -1002,15 +1002,15 @@ export default class ThemeViewState implements SpecialVisualizationState {
return UserRelatedState.usersettingsConfig
}
if (id.startsWith(LastClickFeatureSource.newPointElementId)) {
return this.layout.layers.find((l) => l.id === "last_click")
return this.theme.layers.find((l) => l.id === "last_click")
}
if (id.startsWith("search_result")) {
return GeocodingUtils.searchLayer
}
if (id === "location_track") {
return this.layout.layers.find((l) => l.id === "gps_track")
return this.theme.layers.find((l) => l.id === "gps_track")
}
return this.layout.getMatchingLayer(properties)
return this.theme.getMatchingLayer(properties)
}
public async reportError(message: string | Error | XMLHttpRequest, extramessage: string = "") {
@ -1059,7 +1059,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
body: JSON.stringify({
stacktrace,
message: "" + message,
layout: this.layout.id,
theme: this.theme.id,
version: Constants.vNumber,
language: this.userRelatedState.language.data,
username: this.osmConnection.userDetails.data?.name,