diff --git a/Logic/FeatureSource/FeaturePipeline.ts b/Logic/FeatureSource/FeaturePipeline.ts index 9e8a0afa7d..baed7e682b 100644 --- a/Logic/FeatureSource/FeaturePipeline.ts +++ b/Logic/FeatureSource/FeaturePipeline.ts @@ -152,6 +152,11 @@ export default class FeaturePipeline { handlePriviligedFeatureSource(state.homeLocation) continue } + + if (id === "current_view") { + handlePriviligedFeatureSource(state.currentView) + continue + } const localTileSaver = new SaveTileToLocalStorageActor(filteredLayer) this.localStorageSavers.set(filteredLayer.layerDef.id, localTileSaver) diff --git a/Logic/State/MapState.ts b/Logic/State/MapState.ts index 4627dad25b..7fc59e3948 100644 --- a/Logic/State/MapState.ts +++ b/Logic/State/MapState.ts @@ -45,7 +45,10 @@ export default class MapState extends UserRelatedState { lon: number; }> = new UIEventSource<{ lat: number; lon: number }>(undefined); - public currentView: FeatureSourceForLayer + /** + * The bounds of the current map view + */ + public currentView: FeatureSourceForLayer & Tiled; /** * The location as delivered by the GPS */ @@ -174,30 +177,43 @@ export default class MapState extends UserRelatedState { } private initCurrentView(){ + let currentViewLayer: FilteredLayer = this.filteredLayers.data.filter(l => l.layerDef.id === "current_view")[0] + + if(currentViewLayer === undefined){ + // This layer is not needed by the theme and thus unloaded + return; + } + + + let i = 0 const features : UIEventSource<{ feature: any, freshness: Date }[]>= this.currentBounds.map(bounds => { + if(bounds === undefined){ + return [] + } + i++ const feature = { freshness: new Date(), feature: { - type: "Polygon", + type: "Feature", properties:{ - id:"current_view" + id:"current_view-"+i, + "current_view":"yes" }, geometry:{ type:"Polygon", - coordinates:[ + coordinates:[[ [bounds.maxLon, bounds.maxLat], [bounds.minLon, bounds.maxLat], [bounds.minLon, bounds.minLat], [bounds.maxLon, bounds.minLat], [bounds.maxLon, bounds.maxLat], - ] + ]] } } } return [feature] }) - let currentViewLayer: FilteredLayer = this.filteredLayers.data.filter(l => l.layerDef.id === "current_view")[0] - + this.currentView = new SimpleFeatureSource(currentViewLayer,0,features) } diff --git a/Models/Constants.ts b/Models/Constants.ts index 7147d4af1f..d87e2873f7 100644 --- a/Models/Constants.ts +++ b/Models/Constants.ts @@ -2,7 +2,7 @@ import {Utils} from "../Utils"; export default class Constants { - public static vNumber = "0.13.0-alpha-5"; + public static vNumber = "0.13.0-alpha-6"; public static ImgurApiKey = '7070e7167f0a25a' public static readonly mapillary_client_token_v4 = "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85" diff --git a/UI/BigComponents/LeftControls.ts b/UI/BigComponents/LeftControls.ts index 0082f60c70..a0a5e215c7 100644 --- a/UI/BigComponents/LeftControls.ts +++ b/UI/BigComponents/LeftControls.ts @@ -15,10 +15,17 @@ import FilteredLayer from "../../Models/FilteredLayer"; import BaseLayer from "../../Models/BaseLayer"; import {OsmConnection} from "../../Logic/Osm/OsmConnection"; import BackgroundMapSwitch from "./BackgroundMapSwitch"; +import {FeatureSourceForLayer} from "../../Logic/FeatureSource/FeatureSource"; +import Lazy from "../Base/Lazy"; +import {VariableUiElement} from "../Base/VariableUIElement"; +import FeatureInfoBox from "../Popup/FeatureInfoBox"; +import {ElementStorage} from "../../Logic/ElementStorage"; export default class LeftControls extends Combine { constructor(state: { + allElements: ElementStorage; + currentView: FeatureSourceForLayer; featureSwitchBackgroundSelection: UIEventSource; layoutToUse: LayoutConfig, featurePipeline: FeaturePipeline, @@ -33,12 +40,56 @@ export default class LeftControls extends Combine { osmConnection: OsmConnection }, guiState: { + currentViewControlIsOpened: UIEventSource; downloadControlIsOpened: UIEventSource, filterViewIsOpened: UIEventSource, copyrightViewIsOpened: UIEventSource }) { + const currentViewFL = state.currentView?.layer + const currentViewAction = new Toggle( + new Lazy(() => { + const feature : UIEventSource = state.currentView.features.map(ffs => ffs[0]?.feature) + const icon = new VariableUiElement(feature.map(feature => { + const defaultIcon = Svg.checkbox_empty_svg() + if (feature === undefined) { + return defaultIcon; + } + const tags = {...feature.properties, button: "yes"} + const elem = currentViewFL.layerDef.mapRendering[0]?.GenerateLeafletStyle(tags, false, { + noSize: true + })?.html + if(elem === undefined){ + return defaultIcon + } + return elem + })) + + const featureBox = new VariableUiElement(feature.map(feature => { + if(feature === undefined){return undefined} + return new Lazy(() => { + const tagsSource= state.allElements.getEventSourceById(feature.properties.id) + return new FeatureInfoBox(tagsSource, currentViewFL.layerDef, "currentview", guiState.currentViewControlIsOpened) + }) + })) + + + return new Toggle( + featureBox, + new MapControlButton(icon), + guiState.currentViewControlIsOpened + ) + + }).SetClass("inline-block w-full").onClick(() => { + guiState.currentViewControlIsOpened.setData(true) + }), + + + undefined, + new UIEventSource(currentViewFL !== undefined && currentViewFL?.layerDef?.tagRenderings !== null) + ) + const toggledDownload = new Toggle( new AllDownloads( guiState.downloadControlIsOpened @@ -75,16 +126,18 @@ export default class LeftControls extends Combine { undefined, state.featureSwitchFilter ); - + const mapSwitch = new Toggle( new BackgroundMapSwitch(state, state.backgroundLayer), undefined, state.featureSwitchBackgroundSelection ) - super([filterButton, + super([ + currentViewAction, + filterButton, downloadButtonn, - mapSwitch + mapSwitch ]) this.SetClass("flex flex-col") diff --git a/UI/DefaultGuiState.ts b/UI/DefaultGuiState.ts index 1df1891db9..ab834bc269 100644 --- a/UI/DefaultGuiState.ts +++ b/UI/DefaultGuiState.ts @@ -9,6 +9,7 @@ export class DefaultGuiState { public readonly downloadControlIsOpened: UIEventSource; public readonly filterViewIsOpened: UIEventSource; public readonly copyrightViewIsOpened: UIEventSource; + public readonly currentViewControlIsOpened: UIEventSource; public readonly welcomeMessageOpenedTab: UIEventSource public readonly allFullScreenStates: UIEventSource[] = [] @@ -40,6 +41,11 @@ export class DefaultGuiState { "false", "Whether or not the copyright view is shown" ) + this.currentViewControlIsOpened = QueryParameters.GetBooleanQueryParameter( + "currentview-toggle", + "false", + "Whether or not the current view box is shown" + ) if (Hash.hash.data === "download") { this.downloadControlIsOpened.setData(true) } @@ -48,12 +54,14 @@ export class DefaultGuiState { } if (Hash.hash.data === "copyright") { this.copyrightViewIsOpened.setData(true) + }if (Hash.hash.data === "currentview") { + this.currentViewControlIsOpened.setData(true) } if (Hash.hash.data === "" || Hash.hash.data === undefined || Hash.hash.data === "welcome") { this.welcomeMessageIsOpened.setData(true) } - this.allFullScreenStates.push(this.downloadControlIsOpened, this.filterViewIsOpened, this.copyrightViewIsOpened, this.welcomeMessageIsOpened) + this.allFullScreenStates.push(this.downloadControlIsOpened, this.filterViewIsOpened, this.copyrightViewIsOpened, this.welcomeMessageIsOpened, this.currentViewControlIsOpened) for (let i = 0; i < this.allFullScreenStates.length; i++) { const fullScreenState = this.allFullScreenStates[i]; diff --git a/UI/Popup/FeatureInfoBox.ts b/UI/Popup/FeatureInfoBox.ts index b6d79abd59..4b6853cdfd 100644 --- a/UI/Popup/FeatureInfoBox.ts +++ b/UI/Popup/FeatureInfoBox.ts @@ -25,10 +25,13 @@ export default class FeatureInfoBox extends ScrollableFullScreen { public constructor( tags: UIEventSource, layerConfig: LayerConfig, + hashToShow?: string, + isShown?: UIEventSource ) { super(() => FeatureInfoBox.GenerateTitleBar(tags, layerConfig), () => FeatureInfoBox.GenerateContent(tags, layerConfig), - tags.data.id); + hashToShow ?? tags.data.id, + isShown); if (layerConfig === undefined) { throw "Undefined layerconfig"; diff --git a/assets/layers/charging_station/charging_station.json b/assets/layers/charging_station/charging_station.json index 62247c77d4..bf83ef528e 100644 --- a/assets/layers/charging_station/charging_station.json +++ b/assets/layers/charging_station/charging_station.json @@ -180,8 +180,7 @@ "if": { "and": [ "socket:schuko~*", - "socket:schuko!=1", - "" + "socket:schuko!=1" ] }, "then": { @@ -202,8 +201,7 @@ "if": { "and": [ "socket:typee~*", - "socket:typee!=1", - "" + "socket:typee!=1" ] }, "then": { @@ -250,8 +248,7 @@ "if": { "and": [ "socket:chademo~*", - "socket:chademo!=1", - "" + "socket:chademo!=1" ] }, "then": { @@ -298,8 +295,7 @@ "if": { "and": [ "socket:type1_cable~*", - "socket:type1_cable!=1", - "" + "socket:type1_cable!=1" ] }, "then": { @@ -346,8 +342,7 @@ "if": { "and": [ "socket:type1~*", - "socket:type1!=1", - "" + "socket:type1!=1" ] }, "then": { @@ -394,8 +389,7 @@ "if": { "and": [ "socket:type1_combo~*", - "socket:type1_combo!=1", - "" + "socket:type1_combo!=1" ] }, "then": { @@ -442,8 +436,7 @@ "if": { "and": [ "socket:tesla_supercharger~*", - "socket:tesla_supercharger!=1", - "" + "socket:tesla_supercharger!=1" ] }, "then": { @@ -490,8 +483,7 @@ "if": { "and": [ "socket:type2~*", - "socket:type2!=1", - "" + "socket:type2!=1" ] }, "then": { @@ -538,8 +530,7 @@ "if": { "and": [ "socket:type2_combo~*", - "socket:type2_combo!=1", - "" + "socket:type2_combo!=1" ] }, "then": { @@ -586,8 +577,7 @@ "if": { "and": [ "socket:type2_cable~*", - "socket:type2_cable!=1", - "" + "socket:type2_cable!=1" ] }, "then": { @@ -634,8 +624,7 @@ "if": { "and": [ "socket:tesla_supercharger_ccs~*", - "socket:tesla_supercharger_ccs!=1", - "" + "socket:tesla_supercharger_ccs!=1" ] }, "then": { @@ -762,8 +751,7 @@ "if": { "and": [ "socket:USB-A~*", - "socket:USB-A!=1", - "" + "socket:USB-A!=1" ] }, "then": { @@ -806,8 +794,7 @@ "if": { "and": [ "socket:bosch_3pin~*", - "socket:bosch_3pin!=1", - "" + "socket:bosch_3pin!=1" ] }, "then": { @@ -850,8 +837,7 @@ "if": { "and": [ "socket:bosch_5pin~*", - "socket:bosch_5pin!=1", - "" + "socket:bosch_5pin!=1" ] }, "then": { diff --git a/assets/layers/charging_station/csvToJson.ts b/assets/layers/charging_station/csvToJson.ts index 553f9806e1..32e14924df 100644 --- a/assets/layers/charging_station/csvToJson.ts +++ b/assets/layers/charging_station/csvToJson.ts @@ -3,7 +3,6 @@ import {Utils} from "../../../Utils"; import {TagRenderingConfigJson} from "../../../Models/ThemeConfig/Json/TagRenderingConfigJson"; import ScriptUtils from "../../../scripts/ScriptUtils"; import {LayerConfigJson} from "../../../Models/ThemeConfig/Json/LayerConfigJson"; -import {TagsFilter} from "../../../Logic/Tags/TagsFilter"; function colonSplit(value: string): string[] { @@ -122,7 +121,7 @@ function run(file, protojson) { // We add a second time for any amount to trigger a visualisation; but this is not an answer option const no_ask_json = { if: { - and:Utils.NoNull( [`${e.key}~*`, `${e.key}!=1`, ...e.extraVisualisationCondition.split(";")]) + and:Utils.NoEmpty( [`${e.key}~*`, `${e.key}!=1`, ...e.extraVisualisationCondition.split(";")]) }, then: txt, hideInAnswer: true diff --git a/assets/layers/current_view/current_view.json b/assets/layers/current_view/current_view.json index 5b4aacd37d..8d873863d4 100644 --- a/assets/layers/current_view/current_view.json +++ b/assets/layers/current_view/current_view.json @@ -1,9 +1,10 @@ { "id": "current_view", - "description": "A meta-layer which contains one single feature, namely the BBOX of the current map view. This can be used to trigger special actions. If a popup is defined for this layer, this popup will be accessible via an extra button on screen", + "description": "A meta-layer which contains one single feature, namely the BBOX of the current map view. This can be used to trigger special actions. If a popup is defined for this layer, this popup will be accessible via an extra button on screen.\n\nThe icon on the button is the default icon of the layer, but can be customized by detecting 'button=yes'.", "source": { - "osmTags": "id=currentView" + "osmTags": "current_view=yes" }, + "shownByDefault": false, "title": "Current View", "tagRenderings": [], "mapRendering": [