diff --git a/assets/layers/icons/icons.json b/assets/layers/icons/icons.json index a5fb70601d..0ff0226424 100644 --- a/assets/layers/icons/icons.json +++ b/assets/layers/icons/icons.json @@ -356,9 +356,32 @@ } } } + }, + { + "#": "ignore-image-in-then", + "if": "osm_id~*", + "then": { + "special": { + "type": "link", + "text": "on osm", + "href": "https://www.openstreetmap.org/{osm_id}", + "arialabel": { + "en": "Open on openstreetmap.org", + "nl": "Bekijk op openstreetmap.org", + "de": "Auf openstreetmap.org öffnen", + "pl": "Otwórz na openstreetmap.org", + "da": "Åbn på openstreetmap.org" + } + } + } } ], - "condition": "id~(node|way|relation)/[0-9]*" + "condition": { + "or": [ + "id~(node|way|relation)/[0-9]*", + "osm_id~*" + ] + } }, { "id": "rating", diff --git a/assets/layers/search/search.json b/assets/layers/search/search.json new file mode 100644 index 0000000000..7e0e08e009 --- /dev/null +++ b/assets/layers/search/search.json @@ -0,0 +1,66 @@ +{ + "id": "search", + "description": { + "en": "Priviliged layer showing the search results" + }, + "source": "special", + "title": "{display_name}", + "tagRenderings": [ + { + "id": "intro", + "render": { + "en": "Search result" + } + }, + { + "id": "osm", + "render": { + "*": "On OpenStreetMap" + } + }, + "all_tags" + ], + "pointRendering": [ + { + "location": [ + "point", + "centroid" + ], + "marker": [ + { + "icon": "circle", + "color": "white" + }, + { + "icon": { + "render": "globe_alt", + "mappings": [ + { + "if": "category~city|locality|county", + "then": "building_office_2" + }, + { + "if": "category=train_station", + "then": "train" + }, + { + "if": "category=airport", + "then": "airport" + }, + { + "if": "category=house", + "then": "house" + }, + { + "if": "category=shop", + "then": "building_storefront" + } + ] + } + } + ], + "label": "{display_name}", + "labelCssClasses": "bg-white rounded p-2 no-wrap" + } + ] +} diff --git a/package.json b/package.json index 925e2c13bd..e33d139a84 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "generate:contributor-list": "vite-node scripts/generateContributors.ts", "generate:service-worker": "tsc src/service-worker.ts --outFile public/service-worker.js && git_hash=$(git rev-parse HEAD) && sed -i.bak \"s/GITHUB-COMMIT/$git_hash/\" public/service-worker.js && rm public/service-worker.js.bak", "reset:layeroverview": "npm run prep:layeroverview && npm run generate:layeroverview && npm run refresh:layeroverview", - "prep:layeroverview": "mkdir -p ./src/assets/generated/layers; echo {\\\"themes\\\":[]} > ./src/assets/generated/known_themes.json && echo {\\\"layers\\\": []} > ./src/assets/generated/known_layers.json && rm -f ./src/assets/generated/layers/*.json && rm -f ./src/assets/generated/themes/*.json && cp ./assets/layers/usersettings/usersettings.json ./src/assets/generated/layers/usersettings.json && echo '{}' > ./src/assets/generated/layers/favourite.json && echo '{}' > ./src/assets/generated/layers/summary.json && echo '{}' > ./src/assets/generated/layers/last_click.json && echo '[]' > ./src/assets/generated/theme_overview.json", + "prep:layeroverview": "mkdir -p ./src/assets/generated/layers; echo {\\\"themes\\\":[]} > ./src/assets/generated/known_themes.json && echo {\\\"layers\\\": []} > ./src/assets/generated/known_layers.json && rm -f ./src/assets/generated/layers/*.json && rm -f ./src/assets/generated/themes/*.json && cp ./assets/layers/usersettings/usersettings.json ./src/assets/generated/layers/usersettings.json && echo '{}' > ./src/assets/generated/layers/favourite.json && echo '{}' > ./src/assets/generated/layers/summary.json && echo '{}' > ./src/assets/generated/layers/last_click.json && echo '[]' > ./src/assets/generated/theme_overview.json && echo '{}' > ./src/assets/generated/layers/search.json", "generate": "npm run generate:licenses && npm run generate:images && npm run generate:charging-stations && npm run generate:translations && npm run refresh:layeroverview && npm run generate:service-worker", "generate:charging-stations": "cd ./assets/layers/charging_station && vite-node csvToJson.ts && cd -", "clean:tests": "find . -type f -name \"*.doctest.ts\" | xargs -r rm", diff --git a/src/Logic/Actors/TitleHandler.ts b/src/Logic/Actors/TitleHandler.ts index 9f6be82b37..2e56d02dc5 100644 --- a/src/Logic/Actors/TitleHandler.ts +++ b/src/Logic/Actors/TitleHandler.ts @@ -21,7 +21,7 @@ export default class TitleHandler { if (selected === undefined) { return defaultTitle } - const layer = state.layout.getMatchingLayer(selected.properties) + const layer = state.getMatchingLayer(selected.properties) if (layer === undefined) { return defaultTitle } diff --git a/src/Logic/Geocoding/GeocodingFeatureSource.ts b/src/Logic/Geocoding/GeocodingFeatureSource.ts new file mode 100644 index 0000000000..dab08d8531 --- /dev/null +++ b/src/Logic/Geocoding/GeocodingFeatureSource.ts @@ -0,0 +1,41 @@ +import { GeoCodeResult } from "./GeocodingProvider" +import { Store } from "../UIEventSource" +import { FeatureSource } from "../FeatureSource/FeatureSource" +import { Feature, Geometry } from "geojson" + +export default class GeocodingFeatureSource implements FeatureSource { + public features: Store>[]> + + constructor(provider: Store) { + this.features = provider.mapD(geocoded => { + const features: Feature[] = [] + + for (const gc of geocoded) { + if (gc.lat === undefined || gc.lon === undefined) { + continue + } + + features.push({ + type: "Feature", + properties: { + id: "search_result_" + gc.osm_type + "/" + gc.osm_id, + category: gc.category, + description: gc.description, + display_name: gc.display_name, + osm_id: gc.osm_type + "/" + gc.osm_id, + osm_key: gc.feature?.properties?.osm_key, + osm_value: gc.feature?.properties?.osm_value + }, + geometry: { + type: "Point", + coordinates: [gc.lon, gc.lat] + } + }) + + } + + return features + }) + } + +} diff --git a/src/Logic/Geocoding/GeocodingProvider.ts b/src/Logic/Geocoding/GeocodingProvider.ts index 56f9c9b606..243e95ed0f 100644 --- a/src/Logic/Geocoding/GeocodingProvider.ts +++ b/src/Logic/Geocoding/GeocodingProvider.ts @@ -2,8 +2,10 @@ import { BBox } from "../BBox" import { Feature, Geometry } from "geojson" import { DefaultPinIcon } from "../../Models/Constants" import { Store } from "../UIEventSource" - -export type GeocodingCategory = "coordinate" | "city" | "house" | "street" | "locality" | "country" | "train_station" | "county" | "airport" +import * as search from "../../assets/generated/layers/search.json" +import LayerConfig from "../../Models/ThemeConfig/LayerConfig" +import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson" +export type GeocodingCategory = "coordinate" | "city" | "house" | "street" | "locality" | "country" | "train_station" | "county" | "airport" | "shop" export type GeoCodeResult = { /** @@ -66,6 +68,8 @@ export interface ReverseGeocodingProvider { export class GeocodingUtils { + public static searchLayer= new LayerConfig( search, "search") + public static categoryToZoomLevel: Record = { city: 12, county: 10, @@ -75,7 +79,8 @@ export class GeocodingUtils { locality: 14, street: 15, train_station: 14, - airport: 13 + airport: 13, + shop:16 } @@ -89,7 +94,8 @@ export class GeocodingUtils { street: "globe_alt", train_station: "train", county: "building_office_2", - airport: "airport" + airport: "airport", + shop: "building_storefront" } diff --git a/src/Logic/Geocoding/PhotonSearch.ts b/src/Logic/Geocoding/PhotonSearch.ts index 286fecb4e7..69c2876972 100644 --- a/src/Logic/Geocoding/PhotonSearch.ts +++ b/src/Logic/Geocoding/PhotonSearch.ts @@ -95,6 +95,9 @@ export default class PhotonSearch implements GeocodingProvider, ReverseGeocoding private getCategory(entry: Feature) { const p = entry.properties + if(p.osm_key === "shop"){ + return "shop" + } if (p.osm_value === "train_station" || p.osm_key === "railway") { return "train_station" } diff --git a/src/Logic/Geocoding/RecentSearch.ts b/src/Logic/Geocoding/RecentSearch.ts index ab738c9d2a..d3830691c2 100644 --- a/src/Logic/Geocoding/RecentSearch.ts +++ b/src/Logic/Geocoding/RecentSearch.ts @@ -12,10 +12,41 @@ export class RecentSearch { public readonly seenThisSession: Store constructor(state: { layout: LayoutConfig, osmConnection: OsmConnection, selectedElement: Store }) { - // const prefs = state.osmConnection.preferencesHandler.GetLongPreference("previous-searches") + const prefs = state.osmConnection.preferencesHandler.GetLongPreference("previous-searches") + prefs.addCallbackAndRunD(prev => console.trace("Previous searches are:", prev)) + prefs.set(null) this._seenThisSession = new UIEventSource([])//UIEventSource.asObject(prefs, []) this.seenThisSession = this._seenThisSession + prefs.addCallbackAndRunD(prefs => { + if(prefs === ""){ + return + } + const simpleArr = JSON.parse(prefs) + if(simpleArr.length > 0){ + this._seenThisSession.set(simpleArr) + return true + } + }) + + this.seenThisSession.stabilized(2500).addCallbackAndRunD(seen => { + const results= [] + for (let i = 0; i < Math.min(3, seen.length); i++) { + const gc = seen[i] + const simple = { + category: gc.category, + description: gc.description, + display_name: gc.display_name, + lat: gc.lat, lon: gc.lon, + osm_id: gc.osm_id, + osm_type: gc.osm_type + } + results.push(simple) + } + console.log("Setting", results) + prefs.setData(JSON.stringify(results)) + + }) state.selectedElement.addCallbackAndRunD(selected => { @@ -23,6 +54,10 @@ export class RecentSearch { if(!osm_id){ return } + console.log("Selected element is", selected) + if(["node","way","relation"].indexOf(osm_type) < 0){ + return + } const [lon, lat] = GeoOperations.centerpointCoordinates(selected) const entry = { feature: selected, @@ -46,6 +81,7 @@ export class RecentSearch { seenIds.add(id) } } + console.log(">>>",arr) this._seenThisSession.set(arr) } } diff --git a/src/Logic/Osm/OsmPreferences.ts b/src/Logic/Osm/OsmPreferences.ts index 6ac95d8c8a..e634e499a3 100644 --- a/src/Logic/Osm/OsmPreferences.ts +++ b/src/Logic/Osm/OsmPreferences.ts @@ -2,9 +2,7 @@ import { UIEventSource } from "../UIEventSource" import UserDetails, { OsmConnection } from "./OsmConnection" import { Utils } from "../../Utils" import { LocalStorageSource } from "../Web/LocalStorageSource" -// @ts-ignore -import { osmAuth } from "osm-auth" -import OSMAuthInstance = OSMAuth.OSMAuthInstance +import OSMAuthInstance = OSMAuth.osmAuth export class OsmPreferences { /** @@ -53,7 +51,7 @@ export class OsmPreferences { const subOptions = { prefix: "" } // Gives the number of combined preferences const length = this.GetPreference(allStartWith + "-length", "", subOptions) - + const preferences = this.preferences if ((allStartWith + "-length").length > 255) { throw ( "This preference key is too long, it has " + @@ -64,7 +62,6 @@ export class OsmPreferences { ) } - const self = this source.addCallback((str) => { if (str === undefined || str === "") { return @@ -74,9 +71,9 @@ export class OsmPreferences { const count = parseInt(length.data) for (let i = 0; i < count; i++) { // Delete all the preferences - self.GetPreference(allStartWith + "-" + i, "", subOptions).setData("") + this.GetPreference(allStartWith + "-" + i, "", subOptions).setData("") } - self.GetPreference(allStartWith + "-length", "", subOptions).setData("") + this.GetPreference(allStartWith + "-length", "", subOptions).setData("") return } @@ -99,7 +96,7 @@ export class OsmPreferences { if (i > 100) { throw "This long preference is getting very long... " } - self.GetPreference(allStartWith + "-" + i, "", subOptions).setData( + this.GetPreference(allStartWith + "-" + i, "", subOptions).setData( str.substr(0, 255) ) str = str.substr(255) @@ -108,8 +105,9 @@ export class OsmPreferences { length.setData("" + i) // We use I, the number of preference fields used }) + function updateData(l: number) { - if (Object.keys(self.preferences.data).length === 0) { + if (Object.keys(preferences.data).length === 0) { // The preferences are still empty - they are not yet updated, so we delay updating for now return } @@ -120,15 +118,21 @@ export class OsmPreferences { let str = "" for (let i = 0; i < prefsCount; i++) { const key = allStartWith + "-" + i - if (self.preferences.data[key] === undefined) { + if (preferences.data[key] === undefined) { console.warn( "Detected a broken combined preference:", key, "is undefined", - self.preferences + preferences ) + continue } - str += self.preferences.data[key] ?? "" + const v = preferences.data[key] + if(v === "undefined"){ + delete preferences.data[key] + continue + } + str += preferences.data[key] ?? "" } source.setData(str) @@ -137,7 +141,7 @@ export class OsmPreferences { length.addCallback((l) => { updateData(Number(l)) }) - this.preferences.addCallbackAndRun((_) => { + this.preferences.addCallbackAndRun(() => { updateData(Number(length.data)) }) @@ -159,7 +163,7 @@ export class OsmPreferences { ) } key = prefix + key - key = key.replace(/[:\\\/"' {}.%]/g, "") + key = key.replace(/[:/"' {}.%\\]/g, "") if (key.length >= 255) { throw "Preferences: key length to big" } @@ -193,7 +197,6 @@ export class OsmPreferences { public ClearPreferences() { let isRunning = false - const self = this this.preferences.addCallback((prefs) => { console.log("Cleaning preferences...") if (Object.keys(prefs).length == 0) { @@ -208,7 +211,7 @@ export class OsmPreferences { const matches = prefixes.some((prefix) => key.startsWith(prefix)) if (matches) { console.log("Clearing ", key) - self.GetPreference(key, "", { prefix: "" }).setData("") + this.GetPreference(key, "", { prefix: "" }).setData("") } } isRunning = false @@ -227,7 +230,6 @@ export class OsmPreferences { } private UpdatePreferences(forceUpdate?: boolean) { - const self = this if (this._fakeUser) { return } @@ -236,7 +238,7 @@ export class OsmPreferences { method: "GET", path: "/api/0.6/user/preferences", }, - function (error, value: XMLDocument) { + (error, value: XMLDocument) => { if (error) { console.log("Could not load preferences", error) return @@ -246,34 +248,33 @@ export class OsmPreferences { for (let i = 0; i < prefs.length; i++) { const pref = prefs[i] const k = pref.getAttribute("k") - const v = pref.getAttribute("v") - self.preferences.data[k] = v + this.preferences.data[k] = pref.getAttribute("v") seenKeys.add(k) } if (forceUpdate) { - for (let key in self.preferences.data) { + for (const key in this.preferences.data) { if (seenKeys.has(key)) { continue } console.log("Deleting key", key, "as we didn't find it upstream") - delete self.preferences.data[key] + delete this.preferences.data[key] } } // We merge all the preferences: new keys are uploaded // For differing values, the server overrides local changes - self.preferenceSources.forEach((preference, key) => { - const osmValue = self.preferences.data[key] + this.preferenceSources.forEach((preference, key) => { + const osmValue = this.preferences.data[key] if (osmValue === undefined && preference.data !== undefined) { // OSM doesn't know this value yet - self.UploadPreference(key, preference.data) + this.UploadPreference(key, preference.data) } else { // OSM does have a value - set it preference.setData(osmValue) } }) - self.preferences.ping() + this.preferences.ping() } ) } @@ -287,7 +288,6 @@ export class OsmPreferences { if (this.preferences.data[k] === v) { return } - const self = this console.debug("Updating preference", k, " to ", Utils.EllipsesAfter(v, 15)) if (this._fakeUser) { return @@ -299,13 +299,13 @@ export class OsmPreferences { path: "/api/0.6/user/preferences/" + encodeURIComponent(k), headers: { "Content-Type": "text/plain" }, }, - function (error) { + (error) => { if (error) { console.warn("Could not remove preference", error) return } - delete self.preferences.data[k] - self.preferences.ping() + delete this.preferences.data[k] + this.preferences.ping() console.debug("Preference ", k, "removed!") } ) @@ -319,13 +319,13 @@ export class OsmPreferences { headers: { "Content-Type": "text/plain" }, content: v, }, - function (error) { + (error)=> { if (error) { console.warn(`Could not set preference "${k}"'`, error) return } - self.preferences.data[k] = v - self.preferences.ping() + this.preferences.data[k] = v + this.preferences.ping() console.debug(`Preference ${k} written!`) } ) diff --git a/src/Logic/State/UserRelatedState.ts b/src/Logic/State/UserRelatedState.ts index c367657d9f..3ad5b523e5 100644 --- a/src/Logic/State/UserRelatedState.ts +++ b/src/Logic/State/UserRelatedState.ts @@ -351,8 +351,10 @@ export default class UserRelatedState { const key = k.substring(0, k.length - "length".length) let combined = "" for (let i = 0; i < l; i++) { - combined += newPrefs[key + i] + console.log("Building preference:",key,i,">>>", newPrefs[key + i], "<<<", newPrefs, ) + combined += (newPrefs[key + i]) } + console.log("Combined",key,">>>",combined) amendedPrefs.data[key.substring(0, key.length - "-combined-".length)] = combined } else { amendedPrefs.data[k] = newPrefs[k] @@ -456,11 +458,15 @@ export default class UserRelatedState { amendedPrefs.addCallbackD((tags) => { for (const key in tags) { if (key.startsWith("_") || key === "mapcomplete-language") { - // Language is managed seperately + // Language is managed separately continue } if (tags[key + "-combined-0"]) { // A combined value exists + if(tags[key].startsWith("undefined")){ + // Sometimes, a long string of 'undefined' will show up, we ignore them + continue + } this.osmConnection.GetLongPreference(key, "").setData(tags[key]) } else { this.osmConnection diff --git a/src/Logic/UIEventSource.ts b/src/Logic/UIEventSource.ts index 38f1a2f044..f79201f54b 100644 --- a/src/Logic/UIEventSource.ts +++ b/src/Logic/UIEventSource.ts @@ -91,6 +91,20 @@ export class Stores { }) return stable } + + /** + * + * Constructs a new store, but tries to keep the value 'defined' + * If a defined value was in the stream once, a defined value will be returned + * @param store + */ + static holdDefined(store: Store): Store { + const newStore = new UIEventSource(store.data) + store.addCallbackD(t => { + newStore.setData(t) + }) + return newStore + } } export abstract class Store implements Readable { diff --git a/src/Models/Constants.ts b/src/Models/Constants.ts index 4cada3e191..0b2ce00073 100644 --- a/src/Models/Constants.ts +++ b/src/Models/Constants.ts @@ -26,6 +26,7 @@ export default class Constants { "last_click", "favourite", "summary", + "search" ] as const /** * Special layers which are not included in a theme by default @@ -38,7 +39,7 @@ export default class Constants { "import_candidate", "usersettings", "icons", - "filters", + "filters" ] as const /** * Layer IDs of layers which have special properties through built-in hooks @@ -126,6 +127,7 @@ export default class Constants { "brick_wall_round", "brick_wall_square", "building_office_2", + "building_storefront", "bug", "checkmark", "checkmark", diff --git a/src/Models/ThemeConfig/LayoutConfig.ts b/src/Models/ThemeConfig/LayoutConfig.ts index f2617049f4..7c1ec9104c 100644 --- a/src/Models/ThemeConfig/LayoutConfig.ts +++ b/src/Models/ThemeConfig/LayoutConfig.ts @@ -340,7 +340,7 @@ export default class LayoutConfig implements LayoutInformation { } } } - console.log("Fallthrough", this, tags) + console.trace("Fallthrough: could not find the appropraite layer for an object with tags", tags, "within layout", this) return undefined } @@ -354,7 +354,7 @@ export default class LayoutConfig implements LayoutInformation { ...json, layers: json.layers.filter((l) => l["id"] !== "favourite"), } - const usedImages = json._usedImages + const usedImages = jsonNoFavourites._usedImages usedImages.sort() this.usedImages = Utils.Dedup(usedImages) diff --git a/src/Models/ThemeViewState.ts b/src/Models/ThemeViewState.ts index b94d0a3124..778a7ad94b 100644 --- a/src/Models/ThemeViewState.ts +++ b/src/Models/ThemeViewState.ts @@ -68,7 +68,7 @@ import Locale from "../UI/i18n/Locale" import Hash from "../Logic/Web/Hash" import { GeoOperations } from "../Logic/GeoOperations" import { CombinedFetcher } from "../Logic/Web/NearbyImagesSearch" -import GeocodingProvider from "../Logic/Geocoding/GeocodingProvider" +import GeocodingProvider, { GeocodingUtils } from "../Logic/Geocoding/GeocodingProvider" import CombinedSearcher from "../Logic/Geocoding/CombinedSearcher" import CoordinateSearch from "../Logic/Geocoding/CoordinateSearch" import LocalElementSearch from "../Logic/Geocoding/LocalElementSearch" @@ -774,6 +774,7 @@ export default class ThemeViewState implements SpecialVisualizationState { favourite: this.favourites, summary: this.featureSummary, last_click: this.lastClickObject, + search: undefined } this.closestFeatures.registerSource(specialLayers.favourite, "favourite") @@ -910,6 +911,34 @@ export default class ThemeViewState implements SpecialVisualizationState { this.selectedElement.setData(this.currentView.features?.data?.[0]) } + /** + * 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 + * @param tags + */ + public getMatchingLayer(properties: Record){ + + const id = properties.id + + if (id.startsWith("summary_")) { + // We don't select 'summary'-objects + return undefined + } + + if (id === "settings") { + return UserRelatedState.usersettingsConfig + } + if (id.startsWith(LastClickFeatureSource.newPointElementId)) { + return this.layout.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.layout.getMatchingLayer(properties) + } + public async reportError(message: string | Error | XMLHttpRequest) { const isTesting = this.featureSwitchIsTesting.data console.log( diff --git a/src/UI/Base/SelectedElementPanel.svelte b/src/UI/Base/SelectedElementPanel.svelte index 33d91eaec1..db274f649c 100644 --- a/src/UI/Base/SelectedElementPanel.svelte +++ b/src/UI/Base/SelectedElementPanel.svelte @@ -7,23 +7,17 @@ import { LastClickFeatureSource } from "../../Logic/FeatureSource/Sources/LastClickFeatureSource" import Loading from "./Loading.svelte" import { onDestroy } from "svelte" + import LayerConfig from "../../Models/ThemeConfig/LayerConfig" + import { GeocodingUtils } from "../../Logic/Geocoding/GeocodingProvider" + import ThemeViewState from "../../Models/ThemeViewState" export let state: SpecialVisualizationState export let selected: Feature let tags = state.featureProperties.getStore(selected.properties.id) export let absolute = true - function getLayer(properties: Record) { - if (properties.id === "settings") { - return UserRelatedState.usersettingsConfig - } - if (properties.id.startsWith(LastClickFeatureSource.newPointElementId)) { - return state.layout.layers.find((l) => l.id === "last_click") - } - if (properties.id === "location_track") { - return state.layout.layers.find((l) => l.id === "gps_track") - } - return state.layout.getMatchingLayer(properties) + function getLayer(properties: Record): LayerConfig { + return state.getMatchingLayer(properties) } let layer = getLayer(selected.properties) diff --git a/src/UI/BigComponents/Geosearch.svelte b/src/UI/BigComponents/Geosearch.svelte index 89c5886575..c32c6212c2 100644 --- a/src/UI/BigComponents/Geosearch.svelte +++ b/src/UI/BigComponents/Geosearch.svelte @@ -1,5 +1,5 @@
diff --git a/src/UI/Map/Icon.svelte b/src/UI/Map/Icon.svelte index c81b599698..d9c16f6ca7 100644 --- a/src/UI/Map/Icon.svelte +++ b/src/UI/Map/Icon.svelte @@ -42,6 +42,7 @@ import BuildingOffice2 from "@babeard/svelte-heroicons/outline/BuildingOffice2" import Train from "../../assets/svg/Train.svelte" import Airport from "../../assets/svg/Airport.svelte" + import BuildingStorefront from "@babeard/svelte-heroicons/outline/BuildingStorefront" /** * Renders a single icon. @@ -159,6 +160,8 @@ {:else if icon === "airport"} + {:else if icon === "building_storefront"} + {:else if Utils.isEmoji(icon)} {icon} diff --git a/src/UI/SpecialVisualization.ts b/src/UI/SpecialVisualization.ts index 74f484426b..6f08ee4a85 100644 --- a/src/UI/SpecialVisualization.ts +++ b/src/UI/SpecialVisualization.ts @@ -4,7 +4,7 @@ import LayoutConfig, { MinimalLayoutInformation } from "../Models/ThemeConfig/La import { FeatureSource, IndexedFeatureSource, - WritableFeatureSource, + WritableFeatureSource } from "../Logic/FeatureSource/FeatureSource" import { OsmConnection } from "../Logic/Osm/OsmConnection" import { Changes } from "../Logic/Osm/Changes" @@ -97,8 +97,10 @@ export interface SpecialVisualizationState { readonly geolocation: GeoLocationHandler readonly recentlySearched: RecentSearch + getMatchingLayer(properties: Record); showCurrentLocationOn(map: Store): ShowDataLayer + reportError(message: string): Promise } @@ -134,7 +136,7 @@ export interface SpecialVisualization { export type RenderingSpecification = | string | { - func: SpecialVisualization - args: string[] - style: string - } + func: SpecialVisualization + args: string[] + style: string +} diff --git a/src/UI/ThemeViewGUI.svelte b/src/UI/ThemeViewGUI.svelte index ae0b55cd94..75d0c24019 100644 --- a/src/UI/ThemeViewGUI.svelte +++ b/src/UI/ThemeViewGUI.svelte @@ -19,7 +19,7 @@ EyeIcon, HeartIcon, MenuIcon, - XCircleIcon, + XCircleIcon } from "@rgossiaux/svelte-heroicons/solid" import Tr from "./Base/Tr.svelte" import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte" @@ -72,6 +72,7 @@ import HotkeyTable from "./BigComponents/HotkeyTable.svelte" import SelectedElementPanel from "./Base/SelectedElementPanel.svelte" import type { LayerConfigJson } from "../Models/ThemeConfig/Json/LayerConfigJson" + import { GeocodingUtils } from "../Logic/Geocoding/GeocodingProvider" export let state: ThemeViewState let layout = state.layout @@ -98,22 +99,10 @@ }) let selectedLayer: Store = state.selectedElement.mapD((element) => { - const id = element.properties.id - if (id.startsWith("current_view")) { + if (element.properties.id.startsWith("current_view")) { return currentViewLayer } - if (id.startsWith("summary_")) { - console.log("Not selecting a summary object. The summary object is", element) - return undefined - } - if (id.startsWith(LastClickFeatureSource.newPointElementId)) { - return layout.layers.find((l) => l.id === "last_click") - } - if (id === "location_track") { - return layout.layers.find((l) => l.id === "gps_track") - } - - return state.layout.getMatchingLayer(element.properties) + return state.getMatchingLayer(element.properties) }) let currentZoom = state.mapProperties.zoom let showCrosshair = state.userRelatedState.showCrosshair @@ -144,7 +133,7 @@ const bottomRight = mlmap.unproject([rect.right, rect.bottom]) const bbox = new BBox([ [topLeft.lng, topLeft.lat], - [bottomRight.lng, bottomRight.lat], + [bottomRight.lng, bottomRight.lat] ]) state.visualFeedbackViewportBounds.setData(bbox) }