chore: automated housekeeping...

This commit is contained in:
Pieter Vander Vennet 2025-01-28 15:42:34 +01:00
parent 6bc8760adf
commit 0ad881316b
359 changed files with 2049 additions and 938 deletions

View file

@ -14,7 +14,6 @@ export type PageType = (typeof MenuState.pageNames)[number]
* Some convenience methods are provided for this as well
*/
export class MenuState {
public static readonly pageNames = [
"copyright",
"copyright_icons",
@ -28,14 +27,16 @@ export class MenuState {
"favourites",
"usersettings",
"share",
"menu"
"menu",
] as const
/**
* Contains the 'providedImage' which is currently displayed on top of the UI
* This object merely acts as lock or as means to signal the need to close
*/
public static readonly previewedImage: UIEventSource<object> = new UIEventSource<object>(undefined)
public static readonly previewedImage: UIEventSource<object> = new UIEventSource<object>(
undefined
)
public readonly pageStates: Record<PageType, UIEventSource<boolean>>
@ -152,6 +153,5 @@ export class MenuState {
this._selectedElement.setData(undefined)
return true
}
}
}

View file

@ -32,22 +32,26 @@ export class PruneFilters extends DesugaringStep<LayerConfigJson> {
filter: FilterConfigJson,
context: ConversionContext
): FilterConfigJson {
if (filter.options.length === 1) {
const option = filter.options[0]
const tags = TagUtils.Tag(option.osmTags)
const optimized = TagUtils.removeKnownParts(tags, sourceTags, true)
if (optimized === true) {
context.warn("Removing filter as always known: ", new Translation(option.question).textFor("en"))
context.warn(
"Removing filter as always known: ",
new Translation(option.question).textFor("en")
)
return undefined
}
if (optimized === false) {
context.warn("Removing filter as not possible: ", new Translation(option.question).textFor("en"))
context.warn(
"Removing filter as not possible: ",
new Translation(option.question).textFor("en")
)
return undefined
}
}
if (!filter.strict) {
return filter
}
@ -85,7 +89,6 @@ export class PruneFilters extends DesugaringStep<LayerConfigJson> {
)
}
return { ...filter, options: newOptions, strict: undefined }
}
@ -99,9 +102,9 @@ export class PruneFilters extends DesugaringStep<LayerConfigJson> {
const sourceTags = TagUtils.Tag(json.source["osmTags"])
return {
...json,
filter: Utils.NoNull(json.filter?.map((obj) =>
this.prune(sourceTags, <FilterConfigJson>obj, context)
)),
filter: Utils.NoNull(
json.filter?.map((obj) => this.prune(sourceTags, <FilterConfigJson>obj, context))
),
}
}
}

View file

@ -59,10 +59,9 @@ export class ExpandTagRendering extends Conversion<
}
public convert(
spec: string | { "builtin": string | string[] } | (TagRenderingConfigJson),
spec: string | { builtin: string | string[] } | TagRenderingConfigJson,
ctx: ConversionContext
): QuestionableTagRenderingConfigJson[] {
const trs = this.convertOnce(<any>spec, ctx)?.map((tr) =>
this.pruneMappings<TagRenderingConfigJson & { id: string }>(tr, ctx)
)
@ -124,7 +123,7 @@ export class ExpandTagRendering extends Conversion<
}
return {
...mapping,
if: newIf.asJson()
if: newIf.asJson(),
}
})
const after = newMappings?.length ?? 0
@ -137,7 +136,7 @@ export class ExpandTagRendering extends Conversion<
}
const tr = {
...tagRendering,
mappings: newMappings
mappings: newMappings,
}
delete tr["strict"]
return tr
@ -249,7 +248,7 @@ export class ExpandTagRendering extends Conversion<
}
private convertOnce(
tr: string | { "builtin": string } | TagRenderingConfigJson,
tr: string | { builtin: string } | TagRenderingConfigJson,
ctx: ConversionContext
): TagRenderingConfigJson[] {
const state = this._state
@ -273,25 +272,25 @@ export class ExpandTagRendering extends Conversion<
ctx.warn(
`A literal rendering was detected: ${tr}
Did you perhaps forgot to add a layer name as 'layername.${tr}'? ` +
Array.from(state.sharedLayers.keys()).join(", ")
Array.from(state.sharedLayers.keys()).join(", ")
)
}
if (this._options?.noHardcodedStrings && this._state?.sharedLayers?.size > 0) {
ctx.err(
"Detected an invocation to a builtin tagRendering, but this tagrendering was not found: " +
tr +
" \n Did you perhaps forget to add the layer as prefix, such as `icons." +
tr +
"`? "
tr +
" \n Did you perhaps forget to add the layer as prefix, such as `icons." +
tr +
"`? "
)
}
return [
<TagRenderingConfigJson & { id: string }>{
render: tr,
id: tr.replace(/[^a-zA-Z0-9]/g, "")
}
id: tr.replace(/[^a-zA-Z0-9]/g, ""),
},
]
}
@ -316,9 +315,9 @@ export class ExpandTagRendering extends Conversion<
}
ctx.err(
"An object calling a builtin can only have keys `builtin` or `override`, but a key with name `" +
key +
"` was found. This won't be picked up! The full object is: " +
JSON.stringify(tr)
key +
"` was found. This won't be picked up! The full object is: " +
JSON.stringify(tr)
)
}
@ -345,19 +344,19 @@ export class ExpandTagRendering extends Conversion<
if (state.sharedLayers.size === 0) {
ctx.warn(
"BOOTSTRAPPING. Rerun generate layeroverview. While reusing tagrendering: " +
name +
": layer " +
layerName +
" not found for now, but ignoring as this is a bootstrapping run. "
name +
": layer " +
layerName +
" not found for now, but ignoring as this is a bootstrapping run. "
)
} else {
ctx.err(
": While reusing tagrendering: " +
name +
": layer " +
layerName +
" not found. Maybe you meant one of " +
candidates.slice(0, 3).join(", ")
name +
": layer " +
layerName +
" not found. Maybe you meant one of " +
candidates.slice(0, 3).join(", ")
)
}
continue
@ -369,10 +368,10 @@ export class ExpandTagRendering extends Conversion<
candidates = Utils.sortedByLevenshteinDistance(name, candidates, (i) => i)
ctx.err(
"The tagRendering with identifier " +
name +
" was not found.\n\tDid you mean one of " +
candidates.join(", ") +
"?\n(Hint: did you add a new label and are you trying to use this label at the same time? Run 'reset:layeroverview' first"
name +
" was not found.\n\tDid you mean one of " +
candidates.join(", ") +
"?\n(Hint: did you add a new label and are you trying to use this label at the same time? Run 'reset:layeroverview' first"
)
continue
}

View file

@ -1,6 +1,18 @@
import { Concat, DesugaringContext, DesugaringStep, Each, FirstOf, Fuse, On, SetDefault } from "./Conversion"
import {
Concat,
DesugaringContext,
DesugaringStep,
Each,
FirstOf,
Fuse,
On,
SetDefault,
} from "./Conversion"
import { LayerConfigJson } from "../Json/LayerConfigJson"
import { MinimalTagRenderingConfigJson, TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"
import {
MinimalTagRenderingConfigJson,
TagRenderingConfigJson,
} from "../Json/TagRenderingConfigJson"
import { Utils } from "../../../Utils"
import RewritableConfigJson from "../Json/RewritableConfigJson"
import SpecialVisualizations from "../../../UI/SpecialVisualizations"
@ -24,7 +36,7 @@ import { ExpandTagRendering } from "./ExpandTagRendering"
class AddFiltersFromTagRenderings extends DesugaringStep<LayerConfigJson> {
constructor() {
super(
"Inspects all the tagRenderings. If some tagRenderings have the `filter` attribute set, introduce those filters. This step might introduce shorthand filter names, thus 'ExpandFilter' should be run afterwards. Can be disabled with \"#filter\":\"no-auto\"",
'Inspects all the tagRenderings. If some tagRenderings have the `filter` attribute set, introduce those filters. This step might introduce shorthand filter names, thus \'ExpandFilter\' should be run afterwards. Can be disabled with "#filter":"no-auto"',
["filter"],
"AddFiltersFromTagRenderings"
)
@ -127,7 +139,7 @@ class DetectInline extends DesugaringStep<QuestionableTagRenderingConfigJson> {
if (json.freeform.inline === true) {
context.err(
"'inline' is set, but the rendering contains a special visualisation...\n " +
spec[key]
spec[key]
)
}
json = JSON.parse(JSON.stringify(json))
@ -226,20 +238,20 @@ export class AddQuestionBox extends DesugaringStep<LayerConfigJson> {
if (blacklisted?.length > 0 && used?.length > 0) {
context.err(
"The {questions()}-special rendering only supports either a blacklist OR a whitelist, but not both." +
"\n Whitelisted: " +
used.join(", ") +
"\n Blacklisted: " +
blacklisted.join(", ")
"\n Whitelisted: " +
used.join(", ") +
"\n Blacklisted: " +
blacklisted.join(", ")
)
}
for (const usedLabel of used) {
if (!allLabels.has(usedLabel)) {
context.err(
"This layers specifies a special question element for label `" +
usedLabel +
"`, but this label doesn't exist.\n" +
" Available labels are " +
Array.from(allLabels).join(", ")
usedLabel +
"`, but this label doesn't exist.\n" +
" Available labels are " +
Array.from(allLabels).join(", ")
)
}
seen.add(usedLabel)
@ -253,8 +265,8 @@ export class AddQuestionBox extends DesugaringStep<LayerConfigJson> {
const question: QuestionableTagRenderingConfigJson = {
id: "leftover-questions",
render: {
"*": `{questions( ,${Array.from(seen).join(";")})}`
}
"*": `{questions( ,${Array.from(seen).join(";")})}`,
},
}
json.tagRenderings.push(question)
}
@ -336,13 +348,13 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
if (json.allowMove && !usedSpecialFunctions.has("move_button")) {
json.tagRenderings.push({
id: "move-button",
render: { "*": "{move_button()}" }
render: { "*": "{move_button()}" },
})
}
if (json.deletion && !usedSpecialFunctions.has("delete_button")) {
json.tagRenderings.push({
id: "delete-button",
render: { "*": "{delete_button()}" }
render: { "*": "{delete_button()}" },
})
}
@ -357,9 +369,9 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
or: [
"__featureSwitchIsDebugging=true",
"mapcomplete-show_tags=full",
"mapcomplete-show_debug=yes"
]
}
"mapcomplete-show_debug=yes",
],
},
}
json.tagRenderings?.push(trc)
}
@ -467,10 +479,10 @@ export class RewriteSpecial extends DesugaringStep<TagRenderingConfigJson> {
private static convertIfNeeded(
input:
| (object & {
special: {
type: string
}
})
special: {
type: string
}
})
| any,
context: ConversionContext
): any {
@ -568,7 +580,7 @@ export class RewriteSpecial extends DesugaringStep<TagRenderingConfigJson> {
.map((nm) => RewriteSpecial.escapeStr(special[nm] ?? "", context))
.join(",")
return {
"*": `{${type}(${args})${clss}}`
"*": `{${type}(${args})${clss}}`,
}
}
@ -666,14 +678,14 @@ class ExpandIconBadges extends DesugaringStep<PointRenderingConfigJson> {
}[] = []
for (let i = 0; i < badgesJson.length; i++) {
const iconBadge: string | ({
if: TagConfigJson
then: string | MinimalTagRenderingConfigJson
}) = badgesJson[i]
const iconBadge:
| string
| {
if: TagConfigJson
then: string | MinimalTagRenderingConfigJson
} = badgesJson[i]
if (typeof iconBadge === "string") {
const expanded: QuestionableTagRenderingConfigJson[] = this._expand.convert(
iconBadge,
context.enters("iconBadges", i)
@ -683,16 +695,18 @@ class ExpandIconBadges extends DesugaringStep<PointRenderingConfigJson> {
const condition = tr.condition
for (const trElement of tr.mappings) {
const showIf = TagUtils.optimzeJson({
and: Utils.NoNull([condition,
and: Utils.NoNull([
condition,
{
or: Utils.NoNull([
trElement.alsoShowIf, trElement.if
])
}
])
or: Utils.NoNull([trElement.alsoShowIf, trElement.if]),
},
]),
})
if (showIf === true) {
context.warn("Dropping iconBadge that would be _always_ shown: " + (trElement.icon ?? trElement.then))
context.warn(
"Dropping iconBadge that would be _always_ shown: " +
(trElement.icon ?? trElement.then)
)
continue
}
if (showIf === false) {
@ -700,11 +714,9 @@ class ExpandIconBadges extends DesugaringStep<PointRenderingConfigJson> {
}
iconBadges.push({
if: showIf,
then: trElement.icon ?? trElement.then
then: trElement.icon ?? trElement.then,
})
}
}
continue
}
@ -721,7 +733,7 @@ class ExpandIconBadges extends DesugaringStep<PointRenderingConfigJson> {
iconBadges.push(
...expanded.map((resolved) => ({
if: iconBadge.if,
then: <MinimalTagRenderingConfigJson>resolved
then: <MinimalTagRenderingConfigJson>resolved,
}))
)
}
@ -734,7 +746,7 @@ class PreparePointRendering extends Fuse<PointRenderingConfigJson> {
constructor(state: DesugaringContext, layer: LayerConfigJson) {
super(
"Prepares point renderings by expanding 'icon' and 'iconBadges'." +
" A tagRendering from the host tagRenderings will be substituted in",
" A tagRendering from the host tagRenderings will be substituted in",
new On(
"marker",
new Each(
@ -861,7 +873,7 @@ export class AddRatingBadge extends DesugaringStep<LayerConfigJson> {
const specialVis: Exclude<RenderingSpecification, string>[] = <
Exclude<RenderingSpecification, string>[]
>ValidationUtils.getAllSpecialVisualisations(<any>json.tagRenderings).filter(
>ValidationUtils.getAllSpecialVisualisations(<any>json.tagRenderings).filter(
(rs) => typeof rs !== "string"
)
const funcs = new Set<string>(specialVis.map((rs) => rs.func.funcName))
@ -897,7 +909,7 @@ export class AutoTitleIcon extends DesugaringStep<LayerConfigJson> {
}
return <TagRenderingConfigJson>{
id: "title_icon_auto_" + tr.id,
mappings
mappings,
}
}
@ -942,8 +954,8 @@ export class AutoTitleIcon extends DesugaringStep<LayerConfigJson> {
.enters("titleIcons", i)
.warn(
"TagRendering with id " +
trId +
" does not have any icons, not generating an icon for this"
trId +
" does not have any icons, not generating an icon for this"
)
continue
}
@ -1006,7 +1018,7 @@ export class PrepareLayer extends Fuse<LayerConfigJson> {
(layer) =>
new Concat(
new ExpandTagRendering(state, layer, {
addToContext: options?.addTagRenderingsToContext ?? false
addToContext: options?.addTagRenderingsToContext ?? false,
})
)
),

View file

@ -1,4 +1,14 @@
import { Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, Pass, SetDefault } from "./Conversion"
import {
Concat,
Conversion,
DesugaringContext,
DesugaringStep,
Each,
Fuse,
On,
Pass,
SetDefault,
} from "./Conversion"
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import { PrepareLayer } from "./PrepareLayer"
import { LayerConfigJson } from "../Json/LayerConfigJson"

View file

@ -75,14 +75,17 @@ export default interface PointRenderingConfigJson {
* See ExpandIconBadges on how this is handled
* group: hidden
*/
iconBadges?: (string | {
if: TagConfigJson
/**
* Badge to show
* Type: icon
*/
then: string | MinimalTagRenderingConfigJson
})[]
iconBadges?: (
| string
| {
if: TagConfigJson
/**
* Badge to show
* Type: icon
*/
then: string | MinimalTagRenderingConfigJson
}
)[]
/**
* question: What size should the marker be on the map?

View file

@ -5,7 +5,10 @@ import { TagUtils } from "../../Logic/Tags/TagUtils"
import { And } from "../../Logic/Tags/And"
import { Utils } from "../../Utils"
import { Tag } from "../../Logic/Tags/Tag"
import { MappingConfigJson, QuestionableTagRenderingConfigJson } from "./Json/QuestionableTagRenderingConfigJson"
import {
MappingConfigJson,
QuestionableTagRenderingConfigJson,
} from "./Json/QuestionableTagRenderingConfigJson"
import Validators, { ValidatorType } from "../../UI/InputElement/Validators"
import { TagRenderingConfigJson } from "./Json/TagRenderingConfigJson"
import { RegexTag } from "../../Logic/Tags/RegexTag"

View file

@ -35,10 +35,8 @@ import ShowDataLayer from "../../UI/Map/ShowDataLayer"
*/
export class UserMapFeatureswitchState extends WithUserRelatedState {
readonly map: UIEventSource<MlMap>
readonly mapProperties: MapLibreAdaptor & MapProperties & ExportableMap
readonly lastClickObject: LastClickFeatureSource
@ -47,19 +45,22 @@ export class UserMapFeatureswitchState extends WithUserRelatedState {
readonly geolocationControl: GeolocationControlState
readonly historicalUserLocations: WritableFeatureSource<Feature<Point>>
readonly availableLayers: { store: Store<RasterLayerPolygon[]> }
readonly currentView: FeatureSource<Feature<Polygon>>
readonly fullNodeDatabase?: FullNodeDatabaseSource
constructor(theme: ThemeConfig, selectedElement: Store<object>) {
const rasterLayer: UIEventSource<RasterLayerPolygon> = new UIEventSource<RasterLayerPolygon>(undefined)
const rasterLayer: UIEventSource<RasterLayerPolygon> =
new UIEventSource<RasterLayerPolygon>(undefined)
super(theme, rasterLayer)
this.geolocationState = new GeoLocationState()
const initial = new InitialMapPositioning(theme, this.geolocationState, this.osmConnection)
this.map = new UIEventSource<MlMap>(undefined)
this.mapProperties = new MapLibreAdaptor(this.map, { rasterLayer, ...initial }, { correctClick: 20 })
this.mapProperties = new MapLibreAdaptor(
this.map,
{ rasterLayer, ...initial },
{ correctClick: 20 }
)
this.geolocation = new GeoLocationHandler(
this.geolocationState,
@ -70,7 +71,6 @@ export class UserMapFeatureswitchState extends WithUserRelatedState {
this.geolocationControl = new GeolocationControlState(this.geolocation, this.mapProperties)
this.historicalUserLocations = this.geolocation.historicalUserLocations
this.userRelatedState.fixateNorth.addCallbackAndRunD((fixated) => {
this.mapProperties.allowRotating.setData(fixated !== "yes")
})
@ -100,8 +100,8 @@ export class UserMapFeatureswitchState extends WithUserRelatedState {
bbox.asGeoJson({
zoom: this.mapProperties.zoom.data,
...this.mapProperties.location.data,
id: "current_view_" + currentViewIndex
})
id: "current_view_" + currentViewIndex,
}),
]
})
)
@ -111,12 +111,10 @@ export class UserMapFeatureswitchState extends WithUserRelatedState {
this.fullNodeDatabase = new FullNodeDatabaseSource()
}
///////// Actors ///////////////
new BackgroundLayerResetter(this.mapProperties.rasterLayer, this.availableLayers)
this.userRelatedState.showScale.addCallbackAndRun((showScale) => {
this.mapProperties.showScale.set(showScale)
})
@ -127,14 +125,11 @@ export class UserMapFeatureswitchState extends WithUserRelatedState {
this.userRelatedState.preferredBackgroundLayer
)
this.initHotkeys()
this.drawOverlayLayers()
this.drawLock()
}
/**
* If the map is locked to a certain area _and_ we are in test mode, draw this on the map
* @private
@ -159,7 +154,6 @@ export class UserMapFeatureswitchState extends WithUserRelatedState {
}
}
/* By focussing on the map, the keyboard panning and zoom with '+' and '+' works */
public focusOnMap() {
if (this.map.data) {
@ -205,55 +199,35 @@ export class UserMapFeatureswitchState extends WithUserRelatedState {
})
}
Hotkeys.RegisterHotkey(
{ nomod: "O" },
docs.selectOsmbasedmap,
() => setLayerCategory("osmbasedmap")
Hotkeys.RegisterHotkey({ nomod: "O" }, docs.selectOsmbasedmap, () =>
setLayerCategory("osmbasedmap")
)
Hotkeys.RegisterHotkey(
{ nomod: "M" },
docs.selectMap,
() => setLayerCategory("map")
Hotkeys.RegisterHotkey({ nomod: "M" }, docs.selectMap, () => setLayerCategory("map"))
Hotkeys.RegisterHotkey({ nomod: "P" }, docs.selectAerial, () =>
setLayerCategory("photo")
)
Hotkeys.RegisterHotkey({ shift: "O" }, docs.selectOsmbasedmap, () =>
setLayerCategory("osmbasedmap", 2)
)
Hotkeys.RegisterHotkey(
{ nomod: "P" },
docs.selectAerial,
() => setLayerCategory("photo")
)
Hotkeys.RegisterHotkey(
{ shift: "O" },
docs.selectOsmbasedmap,
() => setLayerCategory("osmbasedmap", 2)
)
Hotkeys.RegisterHotkey({ shift: "M" }, docs.selectMap, () => setLayerCategory("map", 2))
Hotkeys.RegisterHotkey(
{ shift: "M" },
docs.selectMap,
() => setLayerCategory("map", 2)
)
Hotkeys.RegisterHotkey(
{ shift: "P" },
docs.selectAerial,
() => setLayerCategory("photo", 2)
Hotkeys.RegisterHotkey({ shift: "P" }, docs.selectAerial, () =>
setLayerCategory("photo", 2)
)
return true
})
Hotkeys.RegisterHotkey(
{ nomod: "L" },
Translations.t.hotkeyDocumentation.geolocate,
() => {
this.geolocationControl.handleClick()
}
)
Hotkeys.RegisterHotkey({ nomod: "L" }, Translations.t.hotkeyDocumentation.geolocate, () => {
this.geolocationControl.handleClick()
})
Hotkeys.RegisterHotkey(
{
shift: "T"
shift: "T",
},
docs.translationMode,
() => {
@ -286,7 +260,7 @@ export class UserMapFeatureswitchState extends WithUserRelatedState {
return new ShowDataLayer(map, {
features,
layer,
metaTags: this.userRelatedState.preferencesAsTags
metaTags: this.userRelatedState.preferencesAsTags,
})
}
}

View file

@ -1,7 +1,5 @@
import { Changes } from "../../Logic/Osm/Changes"
import {
NewGeometryFromChangesFeatureSource
} from "../../Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource"
import { NewGeometryFromChangesFeatureSource } from "../../Logic/FeatureSource/Sources/NewGeometryFromChangesFeatureSource"
import { WithLayoutSourceState } from "./WithLayoutSourceState"
import ThemeConfig from "../ThemeConfig/ThemeConfig"
import { Utils } from "../../Utils"
@ -20,10 +18,11 @@ import { Map as MlMap } from "maplibre-gl"
import FilteringFeatureSource from "../../Logic/FeatureSource/Sources/FilteringFeatureSource"
import ShowDataLayer from "../../UI/Map/ShowDataLayer"
import SelectedElementTagsUpdater from "../../Logic/Actors/SelectedElementTagsUpdater"
import NoElementsInViewDetector, { FeatureViewState } from "../../Logic/Actors/NoElementsInViewDetector"
import NoElementsInViewDetector, {
FeatureViewState,
} from "../../Logic/Actors/NoElementsInViewDetector"
export class WithChangesState extends WithLayoutSourceState {
readonly changes: Changes
readonly newFeatures: WritableFeatureSource
readonly osmObjectDownloader: OsmObjectDownloader
@ -44,7 +43,7 @@ export class WithChangesState extends WithLayoutSourceState {
osmConnection: this.osmConnection,
featureProperties: this.featureProperties,
historicalUserLocations: this.historicalUserLocations,
reportError: this.reportError
reportError: this.reportError,
},
theme?.isLeftRightSensitive() ?? false
)
@ -66,8 +65,7 @@ export class WithChangesState extends WithLayoutSourceState {
),
new ChangeGeometryApplicator(this.indexedFeatures, this.changes),
{
constructStore: (features, layer) =>
new GeoIndexedStoreForLayer(features, layer),
constructStore: (features, layer) => new GeoIndexedStoreForLayer(features, layer),
handleLeftovers: (features) => {
console.warn(
"Got ",
@ -75,7 +73,7 @@ export class WithChangesState extends WithLayoutSourceState {
"leftover features, such as",
features[0].properties
)
}
},
}
)
this.perLayer = perLayer.perLayer
@ -85,7 +83,6 @@ export class WithChangesState extends WithLayoutSourceState {
this.toCacheSavers = theme.enableCache ? this.initSaveToLocalStorage() : undefined
////// ACTORS ////////
new ChangeToElementsActor(this.changes, this.featureProperties)
@ -97,7 +94,7 @@ export class WithChangesState extends WithLayoutSourceState {
featureProperties: this.featureProperties,
indexedFeatures: this.indexedFeatures,
osmObjectDownloader: this.osmObjectDownloader,
perLayer: this.perLayer
perLayer: this.perLayer,
})
}
@ -154,8 +151,8 @@ export class WithChangesState extends WithLayoutSourceState {
userid: this.osmConnection.userDetails.data?.uid,
pendingChanges: this.changes.pendingChanges.data,
previousChanges: this.changes.allChanges.data,
changeRewrites: Utils.MapToObj(this.changes._changesetHandler._remappings)
})
changeRewrites: Utils.MapToObj(this.changes._changesetHandler._remappings),
}),
})
} catch (e) {
console.error("Could not upload an error report")
@ -227,10 +224,9 @@ export class WithChangesState extends WithLayoutSourceState {
doShowLayer,
metaTags: this.userRelatedState.preferencesAsTags,
selectedElement: this.selectedElement,
fetchStore: (id) => this.featureProperties.getStore(id)
fetchStore: (id) => this.featureProperties.getStore(id),
})
})
return filteringFeatureSource
}
}

View file

@ -34,7 +34,6 @@ export class WithGuiState extends WithSpecialLayers {
this.initHotkeysGui()
}
private initHotkeysGui() {
const docs = Translations.t.hotkeyDocumentation
@ -44,7 +43,7 @@ export class WithGuiState extends WithSpecialLayers {
Hotkeys.RegisterHotkey(
{
nomod: "b"
nomod: "b",
},
docs.openLayersPanel,
() => {
@ -55,7 +54,7 @@ export class WithGuiState extends WithSpecialLayers {
)
Hotkeys.RegisterHotkey(
{
nomod: "s"
nomod: "s",
},
Translations.t.hotkeyDocumentation.openFilterPanel,
() => {
@ -70,5 +69,4 @@ export class WithGuiState extends WithSpecialLayers {
this.guistate.closeAll()
this.selectedElement.setData(this.currentView.features?.data?.[0])
}
}

View file

@ -12,12 +12,10 @@ import { WithGuiState } from "./WithGuiState"
import { SpecialVisualizationState } from "../../UI/SpecialVisualization"
export class WithImageState extends WithGuiState implements SpecialVisualizationState {
readonly imageUploadManager: ImageUploadManager
readonly previewedImage = new UIEventSource<ProvidedImage>(undefined)
readonly nearbyImageSearcher: CombinedFetcher
constructor(layout: ThemeConfig, mvtAvailableLayers: Store<Set<string>>) {
super(layout, mvtAvailableLayers)
this.imageUploadManager = new ImageUploadManager(
@ -40,28 +38,23 @@ export class WithImageState extends WithGuiState implements SpecialVisualization
longAgo.setTime(new Date().getTime() - 5 * 365 * 24 * 60 * 60 * 1000)
this.nearbyImageSearcher = new CombinedFetcher(50, longAgo, this.indexedFeatures)
this.initActors()
Hash.hash.addCallbackAndRunD((hash) => {
if (hash === "current_view" || hash.match(/current_view_[0-9]+/)) {
this.selectCurrentView()
}
})
}
/**
* Setup various services for which no reference are needed
*/
private initActors() {
new ThemeViewStateHashActor({
selectedElement: this.selectedElement,
indexedFeatures: this.indexedFeatures,
guistate: this.guistate
guistate: this.guistate,
})
new PendingChangesUploader(this.changes, this.selectedElement, this.imageUploadManager)
}
}

View file

@ -9,7 +9,6 @@ import { FeatureSource, IndexedFeatureSource } from "../../Logic/FeatureSource/F
import { Tag } from "../../Logic/Tags/Tag"
export class WithLayoutSourceState extends WithSelectedElementState {
readonly layerState: LayerState
readonly dataIsLoading: Store<boolean>
@ -21,7 +20,6 @@ export class WithLayoutSourceState extends WithSelectedElementState {
*/
readonly floors: Store<string[]>
constructor(theme: ThemeConfig, mvtAvailableLayers: Store<Set<string>>) {
super(theme)
/* Set up the layout source
@ -62,24 +60,23 @@ export class WithLayoutSourceState extends WithSelectedElementState {
this.layerState.filteredLayers
.get("favourite")
?.isDisplayed?.addCallbackAndRunD((favouritesShown) => {
const oldGlobal = this.layerState.globalFilters.data
const key = "show-favourite"
if (favouritesShown) {
this.layerState.globalFilters.set([
...oldGlobal,
{
forceShowOnMatch: true,
id: key,
osmTags: new Tag("_favourite", "yes"),
state: 0,
onNewPoint: undefined
}
])
} else {
this.layerState.globalFilters.set(oldGlobal.filter((gl) => gl.id !== key))
}
})
const oldGlobal = this.layerState.globalFilters.data
const key = "show-favourite"
if (favouritesShown) {
this.layerState.globalFilters.set([
...oldGlobal,
{
forceShowOnMatch: true,
id: key,
osmTags: new Tag("_favourite", "yes"),
state: 0,
onNewPoint: undefined,
},
])
} else {
this.layerState.globalFilters.set(oldGlobal.filter((gl) => gl.id !== key))
}
})
}
private static initFloors(features: FeatureSource): Store<string[]> {
@ -124,6 +121,4 @@ export class WithLayoutSourceState extends WithSelectedElementState {
this.featureProperties.trackFeature(feature)
this.selectedElement.setData(feature)
}
}

View file

@ -30,7 +30,7 @@ export class WithSearchState extends WithVisualFeedbackState {
metaTags: this.userRelatedState.preferencesAsTags,
onClick: (feature) => {
this.searchState.clickedOnMap(feature)
}
},
}
new ShowDataLayer(this.map, options)
}
@ -39,17 +39,12 @@ export class WithSearchState extends WithVisualFeedbackState {
private initHotkeysSearch() {
const docs = Translations.t.hotkeyDocumentation
Hotkeys.RegisterHotkey(
{ ctrl: "F" },
docs.selectSearch,
() => {
this.searchState.feedback.set(undefined)
this.searchState.searchIsFocused.set(true)
}
)
Hotkeys.RegisterHotkey({ ctrl: "F" }, docs.selectSearch, () => {
this.searchState.feedback.set(undefined)
this.searchState.searchIsFocused.set(true)
})
Hotkeys.RegisterHotkey({ nomod: "Escape", onUp: true }, docs.closeSidebar, () => {
if (this.guistate.closeAll()) {
return
}
@ -59,7 +54,5 @@ export class WithSearchState extends WithVisualFeedbackState {
Zoomcontrol.resetzoom()
this.focusOnMap()
})
}
}

View file

@ -13,12 +13,13 @@ import { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
* No GUI stuff
*/
export class WithSelectedElementState extends UserMapFeatureswitchState {
readonly selectedElement: UIEventSource<Feature>
constructor(theme: ThemeConfig) {
const selectedElement = new UIEventSource<Feature | undefined>(undefined, "Selected element")
const selectedElement = new UIEventSource<Feature | undefined>(
undefined,
"Selected element"
)
super(theme, selectedElement)
this.selectedElement = selectedElement
this.selectedElement.addCallback((selected) => {
@ -34,7 +35,6 @@ export class WithSelectedElementState extends UserMapFeatureswitchState {
this.setSelectedElement(lastClick.nearestFeature)
})
// Add the selected element to the recently visited history
this.selectedElement.addCallbackD((selected) => {
const [osm_type, osm_id] = selected.properties.id.split("/")
@ -47,7 +47,7 @@ export class WithSelectedElementState extends UserMapFeatureswitchState {
selected?.properties?.local_name,
layer?.title.GetRenderValue(selected?.properties ?? {}).txt,
selected.properties.display_name,
selected.properties.id
selected.properties.id,
]
const r = <GeocodeResult>{
feature: selected,
@ -55,11 +55,10 @@ export class WithSelectedElementState extends UserMapFeatureswitchState {
osm_id,
osm_type,
lon,
lat
lat,
}
this.userRelatedState.recentlyVisitedSearch.add(r)
})
}
protected setSelectedElement(feature: Feature) {
@ -73,6 +72,4 @@ export class WithSelectedElementState extends UserMapFeatureswitchState {
}
this.selectedElement.setData(feature)
}
}

View file

@ -18,12 +18,11 @@ import { Store, UIEventSource } from "../../Logic/UIEventSource"
import NearbyFeatureSource from "../../Logic/FeatureSource/Sources/NearbyFeatureSource"
import {
SummaryTileSource,
SummaryTileSourceRewriter
SummaryTileSourceRewriter,
} from "../../Logic/FeatureSource/TiledFeatureSource/SummaryTileSource"
import { ShowDataLayerOptions } from "../../UI/Map/ShowDataLayerOptions"
export class WithSpecialLayers extends WithChangesState {
readonly favourites: FavouritesFeatureSource
/**
* When hovering (in the popup) an image, the location of the image will be revealed on the main map.
@ -42,7 +41,6 @@ export class WithSpecialLayers extends WithChangesState {
*/
readonly visualFeedbackViewportBounds: UIEventSource<BBox> = new UIEventSource<BBox>(undefined)
constructor(theme: ThemeConfig, mvtAvailableLayers: Store<Set<string>>) {
super(theme, mvtAvailableLayers)
@ -57,7 +55,7 @@ export class WithSpecialLayers extends WithChangesState {
bounds: this.visualFeedbackViewportBounds.map(
(bounds) => bounds ?? this.mapProperties.bounds?.data,
[this.mapProperties.bounds]
)
),
}
)
this.closestFeatures.registerSource(this.favourites, "favourite")
@ -85,11 +83,8 @@ export class WithSpecialLayers extends WithChangesState {
})
}
}
}
private setupSummaryLayer(): SummaryTileSourceRewriter | undefined {
/**
* MaxZoom for the summary layer
@ -113,17 +108,20 @@ export class WithSpecialLayers extends WithChangesState {
this.mapProperties.zoom.map((z) => Math.max(Math.floor(z), 0)),
this.mapProperties,
{
isActive: this.mapProperties.zoom.map((z) => z < maxzoom)
isActive: this.mapProperties.zoom.map((z) => z < maxzoom),
}
)
const source = new SummaryTileSourceRewriter(summaryTileSource, this.layerState.filteredLayers)
const source = new SummaryTileSourceRewriter(
summaryTileSource,
this.layerState.filteredLayers
)
new ShowDataLayer(this.map, {
features: source,
layer: new LayerConfig(<LayerConfigJson>summaryLayer, "summaryLayer"),
// doShowLayer: this.mapProperties.zoom.map((z) => z < maxzoom),
selectedElement: this.selectedElement
selectedElement: this.selectedElement,
})
return source
}
@ -139,7 +137,7 @@ export class WithSpecialLayers extends WithChangesState {
doShowLayer: flayer.isDisplayed,
layer: flayer.layerDef,
metaTags: this.userRelatedState.preferencesAsTags,
selectedElement: this.selectedElement
selectedElement: this.selectedElement,
}
new ShowDataLayer(this.map, options)
}
@ -154,14 +152,14 @@ export class WithSpecialLayers extends WithChangesState {
lastClickLayerConfig.isShown === undefined
? source
: source.features.mapD((fs) =>
fs.filter((f) => {
const matches = lastClickLayerConfig.isShown.matchesProperties(
f.properties
)
console.debug("LastClick ", f, "matches", matches)
return matches
})
)
fs.filter((f) => {
const matches = lastClickLayerConfig.isShown.matchesProperties(
f.properties
)
console.debug("LastClick ", f, "matches", matches)
return matches
})
)
// show last click = new point/note marker
const features = new StaticFeatureSource(lastClickFiltered)
this.featureProperties.trackFeatureSource(features)
@ -175,9 +173,9 @@ export class WithSpecialLayers extends WithChangesState {
}
this.map.data.flyTo({
zoom: Constants.minZoomLevelToAddNewPoint,
center: GeoOperations.centerpointCoordinates(feature)
center: GeoOperations.centerpointCoordinates(feature),
})
}
},
})
}
@ -189,15 +187,17 @@ export class WithSpecialLayers extends WithChangesState {
}
private drawSpecialLayers() {
type AddedByDefaultTypes = (typeof Constants.added_by_default)[number]
type LayersToAdd = "current_view" | Exclude<AddedByDefaultTypes,
"search" // Handled by WithSearchState
| "last_click" // handled by this.drawLastClick()
| "summary" // handled by setupSummaryLayer
| "range" // handled by UserMapFeatureSwitchState
| "selected_element" // handled by this.drawSelectedElement
>
type LayersToAdd =
| "current_view"
| Exclude<
AddedByDefaultTypes,
| "search" // Handled by WithSearchState
| "last_click" // handled by this.drawLastClick()
| "summary" // handled by setupSummaryLayer
| "range" // handled by UserMapFeatureSwitchState
| "selected_element" // handled by this.drawSelectedElement
>
const empty = []
/**
* A listing which maps the layerId onto the featureSource
@ -209,15 +209,13 @@ export class WithSpecialLayers extends WithChangesState {
gps_track: this.geolocation.historicalUserLocationsTrack,
current_view: this.currentView,
favourite: this.favourites,
geocoded_image: new StaticFeatureSource(this.geocodedImages)
geocoded_image: new StaticFeatureSource(this.geocodedImages),
}
// enumerate all 'normal' layers and match them with the appropriate 'special' layer - if applicable
this.layerState.filteredLayers.forEach((flayer) => {
this.registerSpecialLayer(flayer, specialLayers[flayer.layerDef.id])
})
}
private initActorsSpecialLayers() {
@ -230,5 +228,4 @@ export class WithSpecialLayers extends WithChangesState {
}
})
}
}

View file

@ -27,7 +27,11 @@ export class WithUserRelatedState {
{
// Some weird setups
Utils.initDomPurify()
if (!Utils.runningFromConsole && theme.customCss !== undefined && window.location.pathname.indexOf("theme") >= 0) {
if (
!Utils.runningFromConsole &&
theme.customCss !== undefined &&
window.location.pathname.indexOf("theme") >= 0
) {
Utils.LoadCustomCss(theme.customCss)
}
}
@ -40,7 +44,7 @@ export class WithUserRelatedState {
"oauth_token",
undefined,
"Used to complete the login"
)
),
})
this.featureSwitchIsTesting = this.featureSwitches.featureSwitchIsTesting
@ -61,7 +65,7 @@ export class WithUserRelatedState {
icon: th.icon,
title: th.title.translations,
shortDescription: th.shortDescription.translations,
layers: th.layers.filter((l) => l.isNormal()).map((l) => l.id)
layers: th.layers.filter((l) => l.isNormal()).map((l) => l.id),
})
}
@ -103,5 +107,4 @@ export class WithUserRelatedState {
}
return this.theme.getMatchingLayer(properties)
}
}

View file

@ -35,7 +35,6 @@ export class WithVisualFeedbackState extends ThemeViewState {
})
}
/**
* Selects the feature that is 'i' closest to the map center
*/
@ -65,7 +64,7 @@ export class WithVisualFeedbackState extends ThemeViewState {
Hotkeys.RegisterHotkey(
{
nomod: " ",
onUp: true
onUp: true,
},
docs.selectItem,
() => {
@ -97,12 +96,11 @@ export class WithVisualFeedbackState extends ThemeViewState {
Hotkeys.RegisterHotkey(
{
nomod: "" + i,
onUp: true
onUp: true,
},
doc,
() => this.selectClosestAtCenter(i - 1)
)
}
}
}