forked from MapComplete/MapComplete
UX: fix #2089, improve background selection hotkeys and add emoji to indicate categories of background layers
This commit is contained in:
parent
5b67ccc9e2
commit
2dc386fd9a
15 changed files with 600 additions and 525 deletions
|
@ -90,11 +90,11 @@
|
|||
"minzoom": 6,
|
||||
"title": {
|
||||
"render": {
|
||||
"en": "Cycle highway",
|
||||
"en": "cycle highway",
|
||||
"de": "Radschnellweg",
|
||||
"ca": "Via ciclista",
|
||||
"ca": "via ciclista",
|
||||
"fr": "Aménagement cyclable",
|
||||
"nl": "Fietssnelweg",
|
||||
"nl": "fietssnelweg",
|
||||
"es": "autovía ciclista",
|
||||
"nb_NO": "sykkelmotorvei",
|
||||
"da": "cykelmotorvej",
|
||||
|
|
|
@ -374,11 +374,15 @@
|
|||
"fr": "Quel fond souhaitez-vous utiliser par défaut ?",
|
||||
"da": "Hvilket baggrundslag skal vises som standard?"
|
||||
},
|
||||
"questionHint":{
|
||||
"en": "To set a specific background as default, select it in the background menu first after which it will appear here."
|
||||
},
|
||||
"condition": "_theme:backgroundLayer=",
|
||||
"mappings": [
|
||||
{
|
||||
"if": "mapcomplete-preferred-background-layer=default",
|
||||
"alsoShowIf": "mapcomplete-preferred-background-layer=",
|
||||
"icon": "./assets/svg/generic_map.svg",
|
||||
"then": {
|
||||
"en": "Use the default background layer",
|
||||
"ca": "Utilitzeu la capa de fons predeterminada",
|
||||
|
@ -391,6 +395,9 @@
|
|||
},
|
||||
{
|
||||
"if": "mapcomplete-preferred-background-layer=osm",
|
||||
"icon": {
|
||||
"path":"./assets/svg/osm-logo.svg"
|
||||
},
|
||||
"then": {
|
||||
"en": "Use OpenStreetMap-carto as default layer",
|
||||
"ca": "Utilitzeu OpenStreetMap-carto com a capa predeterminada",
|
||||
|
@ -403,6 +410,7 @@
|
|||
},
|
||||
{
|
||||
"if": "mapcomplete-preferred-background-layer=photo",
|
||||
"icon": "\uD83D\uDEF0\uFE0F",
|
||||
"then": {
|
||||
"en": "Use aerial imagery as default background",
|
||||
"ca": "Utilitzeu imatges aèries com a fons predeterminat",
|
||||
|
@ -415,6 +423,7 @@
|
|||
},
|
||||
{
|
||||
"if": "mapcomplete-preferred-background-layer=map",
|
||||
"icon": "./assets/svg/generic_map.svg",
|
||||
"then": {
|
||||
"en": "Use a non-openstreetmap based map as default background",
|
||||
"ca": "Utilitzeu un mapa que no sigui openstreetmap com a fons predeterminat",
|
||||
|
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 128 KiB |
|
@ -74,7 +74,6 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
|
||||
"cycle_highways"
|
||||
],
|
||||
"overpassTimeout": 60,
|
||||
|
|
|
@ -39,10 +39,10 @@
|
|||
|
||||
.mapping-icon-small {
|
||||
/* A mapping icon type */
|
||||
width: 1.5rem;
|
||||
width: 2rem;
|
||||
height: fit-content;
|
||||
|
||||
max-height: 1.5rem;
|
||||
max-height: 2rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,13 +19,14 @@ export default class BackgroundLayerResetter {
|
|||
return
|
||||
}
|
||||
|
||||
currentBackgroundLayer.addCallbackAndRunD((l) => {
|
||||
currentBackgroundLayer.addCallbackAndRunD(async (l) => {
|
||||
if (
|
||||
l.geometry !== undefined &&
|
||||
AvailableRasterLayers.globalLayers.find(
|
||||
(global) => global.properties.id !== l.properties.id
|
||||
)
|
||||
) {
|
||||
await AvailableRasterLayers.editorLayerIndex()
|
||||
BackgroundLayerResetter.installHandler(
|
||||
currentBackgroundLayer,
|
||||
availableLayers.store
|
||||
|
|
|
@ -61,9 +61,9 @@ export class PreferredRasterLayerSelector {
|
|||
* Returns 'true' if the target layer is set or is the current layer
|
||||
* @private
|
||||
*/
|
||||
private updateLayer() {
|
||||
private async updateLayer() {
|
||||
// What is the ID of the layer we have to (try to) load?
|
||||
const targetLayerId = this._queryParameter.data ?? this._preferredBackgroundLayer.data
|
||||
const targetLayerId = (this._queryParameter.data ?? this._preferredBackgroundLayer.data)?.toLowerCase()
|
||||
if (targetLayerId === undefined || targetLayerId === "default") {
|
||||
return
|
||||
}
|
||||
|
@ -74,12 +74,13 @@ export class PreferredRasterLayerSelector {
|
|||
this._rasterLayerSetting.setData(global)
|
||||
return
|
||||
}
|
||||
await AvailableRasterLayers.editorLayerIndex()
|
||||
const isCategory =
|
||||
targetLayerId === "photo" || targetLayerId === "osmbasedmap" || targetLayerId === "map"
|
||||
const available = this._availableLayers.store.data
|
||||
const foundLayer = isCategory
|
||||
? available.find((l) => l.properties.category === targetLayerId)
|
||||
: available.find((l) => l.properties.id === targetLayerId)
|
||||
: available.find((l) => l.properties.id.toLowerCase() === targetLayerId)
|
||||
console.debug("Updating background layer to", foundLayer?.id, {
|
||||
targetLayerId,
|
||||
queryParam: this._queryParameter?.data,
|
||||
|
|
|
@ -28,7 +28,7 @@ export class AvailableRasterLayers {
|
|||
return this._editorLayerIndex
|
||||
}
|
||||
|
||||
public static globalLayers: RasterLayerPolygon[] = globallayers.layers
|
||||
public static globalLayers: ReadonlyArray<RasterLayerPolygon> = globallayers.layers
|
||||
.filter(
|
||||
(properties) =>
|
||||
properties.id !== "osm.carto" && properties.id !== "Bing" /*Added separately*/
|
||||
|
@ -140,28 +140,24 @@ export class RasterLayerUtils {
|
|||
* @param available
|
||||
* @param preferredCategory
|
||||
* @param ignoreLayer
|
||||
* @param skipLayers Skip the first N layers
|
||||
*/
|
||||
public static SelectBestLayerAccordingTo(
|
||||
available: RasterLayerPolygon[],
|
||||
preferredCategory: string,
|
||||
ignoreLayer?: RasterLayerPolygon
|
||||
ignoreLayer?: RasterLayerPolygon,
|
||||
skipLayers: number = 0
|
||||
): RasterLayerPolygon {
|
||||
let secondBest: RasterLayerPolygon = undefined
|
||||
for (const rasterLayer of available) {
|
||||
if (rasterLayer === ignoreLayer) {
|
||||
continue
|
||||
}
|
||||
const p = rasterLayer.properties
|
||||
if (p.category === preferredCategory) {
|
||||
if (p.best) {
|
||||
return rasterLayer
|
||||
}
|
||||
if (!secondBest) {
|
||||
secondBest = rasterLayer
|
||||
}
|
||||
}
|
||||
const inCategory = available.filter(l => l.properties.category === preferredCategory)
|
||||
const best : RasterLayerPolygon[] = inCategory.filter(l => l.properties.best)
|
||||
const others : RasterLayerPolygon[] = inCategory.filter(l => !l.properties.best)
|
||||
let all = best.concat(others)
|
||||
console.log("Selected layers are:", all.map(l => l.properties.id))
|
||||
if(others.length > skipLayers){
|
||||
all = all.slice(skipLayers)
|
||||
}
|
||||
return secondBest
|
||||
|
||||
return all.find(l => l !== ignoreLayer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
this.featureSwitches = new FeatureSwitchState(layout)
|
||||
this.guistate = new MenuState(
|
||||
this.featureSwitches.featureSwitchWelcomeMessage.data,
|
||||
layout.id
|
||||
layout.id,
|
||||
)
|
||||
this.map = new UIEventSource<MlMap>(undefined)
|
||||
const geolocationState = new GeoLocationState()
|
||||
|
@ -177,14 +177,14 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
oauth_token: QueryParameters.GetQueryParameter(
|
||||
"oauth_token",
|
||||
undefined,
|
||||
"Used to complete the login"
|
||||
"Used to complete the login",
|
||||
),
|
||||
})
|
||||
this.userRelatedState = new UserRelatedState(
|
||||
this.osmConnection,
|
||||
layout,
|
||||
this.featureSwitches,
|
||||
this.mapProperties
|
||||
this.mapProperties,
|
||||
)
|
||||
this.userRelatedState.fixateNorth.addCallbackAndRunD((fixated) => {
|
||||
this.mapProperties.allowRotating.setData(fixated !== "yes")
|
||||
|
@ -195,20 +195,20 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
geolocationState,
|
||||
this.selectedElement,
|
||||
this.mapProperties,
|
||||
this.userRelatedState.gpsLocationHistoryRetentionTime
|
||||
this.userRelatedState.gpsLocationHistoryRetentionTime,
|
||||
)
|
||||
this.geolocationControl = new GeolocationControlState(this.geolocation, this.mapProperties)
|
||||
|
||||
this.availableLayers = AvailableRasterLayers.layersAvailableAt(
|
||||
this.mapProperties.location,
|
||||
this.osmConnection.isLoggedIn
|
||||
this.osmConnection.isLoggedIn,
|
||||
)
|
||||
|
||||
this.layerState = new LayerState(
|
||||
this.osmConnection,
|
||||
layout.layers,
|
||||
layout.id,
|
||||
this.featureSwitches.featureSwitchLayerDefault
|
||||
this.featureSwitches.featureSwitchLayerDefault,
|
||||
)
|
||||
|
||||
{
|
||||
|
@ -217,7 +217,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
const isDisplayed = QueryParameters.GetBooleanQueryParameter(
|
||||
"overlay-" + rasterInfo.id,
|
||||
rasterInfo.defaultState ?? true,
|
||||
"Whether or not overlay layer " + rasterInfo.id + " is shown"
|
||||
"Whether or not overlay layer " + rasterInfo.id + " is shown",
|
||||
)
|
||||
const state = { isDisplayed }
|
||||
overlayLayerStates.set(rasterInfo.id, state)
|
||||
|
@ -242,7 +242,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
this.osmConnection.Backend(),
|
||||
(id) => this.layerState.filteredLayers.get(id).isDisplayed,
|
||||
mvtAvailableLayers,
|
||||
this.fullNodeDatabase
|
||||
this.fullNodeDatabase,
|
||||
)
|
||||
|
||||
let currentViewIndex = 0
|
||||
|
@ -260,7 +260,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
id: "current_view_" + currentViewIndex,
|
||||
}),
|
||||
]
|
||||
})
|
||||
}),
|
||||
)
|
||||
this.featuresInView = new BBoxFeatureSource(layoutSource, this.mapProperties.bounds)
|
||||
|
||||
|
@ -278,19 +278,19 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
featureSwitches: this.featureSwitches,
|
||||
},
|
||||
layout?.isLeftRightSensitive() ?? false,
|
||||
(e) => this.reportError(e)
|
||||
(e) => this.reportError(e),
|
||||
)
|
||||
this.historicalUserLocations = this.geolocation.historicalUserLocations
|
||||
this.newFeatures = new NewGeometryFromChangesFeatureSource(
|
||||
this.changes,
|
||||
layoutSource,
|
||||
this.featureProperties
|
||||
this.featureProperties,
|
||||
)
|
||||
layoutSource.addSource(this.newFeatures)
|
||||
|
||||
const perLayer = new PerLayerFeatureSourceSplitter(
|
||||
Array.from(this.layerState.filteredLayers.values()).filter(
|
||||
(l) => l.layerDef?.source !== null
|
||||
(l) => l.layerDef?.source !== null,
|
||||
),
|
||||
new ChangeGeometryApplicator(this.indexedFeatures, this.changes),
|
||||
{
|
||||
|
@ -301,10 +301,10 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
"Got ",
|
||||
features.length,
|
||||
"leftover features, such as",
|
||||
features[0].properties
|
||||
features[0].properties,
|
||||
)
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
this.perLayer = perLayer.perLayer
|
||||
}
|
||||
|
@ -344,12 +344,12 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
this.lastClickObject = new LastClickFeatureSource(
|
||||
this.layout,
|
||||
this.mapProperties.lastClickLocation,
|
||||
this.userRelatedState.addNewFeatureMode
|
||||
this.userRelatedState.addNewFeatureMode,
|
||||
)
|
||||
|
||||
this.osmObjectDownloader = new OsmObjectDownloader(
|
||||
this.osmConnection.Backend(),
|
||||
this.changes
|
||||
this.changes,
|
||||
)
|
||||
|
||||
this.perLayerFiltered = this.showNormalDataOn(this.map)
|
||||
|
@ -360,7 +360,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
currentZoom: this.mapProperties.zoom,
|
||||
layerState: this.layerState,
|
||||
bounds: this.visualFeedbackViewportBounds,
|
||||
}
|
||||
},
|
||||
)
|
||||
this.hasDataInView = new NoElementsInViewDetector(this).hasFeatureInView
|
||||
this.imageUploadManager = new ImageUploadManager(
|
||||
|
@ -368,7 +368,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
Imgur.singleton,
|
||||
this.featureProperties,
|
||||
this.osmConnection,
|
||||
this.changes
|
||||
this.changes,
|
||||
)
|
||||
this.favourites = new FavouritesFeatureSource(this)
|
||||
const longAgo = new Date()
|
||||
|
@ -414,7 +414,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
LayoutSource.fromCacheZoomLevel,
|
||||
fs,
|
||||
this.featureProperties,
|
||||
fs.layer.layerDef.maxAgeOfCache
|
||||
fs.layer.layerDef.maxAgeOfCache,
|
||||
)
|
||||
toLocalStorage.set(layerId, storage)
|
||||
})
|
||||
|
@ -427,7 +427,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
const doShowLayer = this.mapProperties.zoom.map(
|
||||
(z) =>
|
||||
(fs.layer.isDisplayed?.data ?? true) && z >= (fs.layer.layerDef?.minzoom ?? 0),
|
||||
[fs.layer.isDisplayed]
|
||||
[fs.layer.isDisplayed],
|
||||
)
|
||||
|
||||
if (!doShowLayer.data && this.featureSwitches.featureSwitchFilter.data === false) {
|
||||
|
@ -444,7 +444,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
fs.layer,
|
||||
fs,
|
||||
(id) => this.featureProperties.getStore(id),
|
||||
this.layerState.globalFilters
|
||||
this.layerState.globalFilters,
|
||||
)
|
||||
filteringFeatureSource.set(layerName, filtered)
|
||||
|
||||
|
@ -588,7 +588,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
return
|
||||
}
|
||||
this.selectClosestAtCenter(0)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
for (let i = 1; i < 9; i++) {
|
||||
|
@ -606,7 +606,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
onUp: true,
|
||||
},
|
||||
doc,
|
||||
() => this.selectClosestAtCenter(i - 1)
|
||||
() => this.selectClosestAtCenter(i - 1),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -623,7 +623,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
if (this.featureSwitches.featureSwitchBackgroundSelection.data) {
|
||||
this.guistate.backgroundLayerSelectionIsOpened.setData(true)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
Hotkeys.RegisterHotkey(
|
||||
{
|
||||
|
@ -635,18 +635,11 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
if (this.featureSwitches.featureSwitchFilter.data) {
|
||||
this.guistate.openFilterView()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
Hotkeys.RegisterHotkey(
|
||||
{ shift: "O" },
|
||||
Translations.t.hotkeyDocumentation.selectMapnik,
|
||||
() => {
|
||||
this.mapProperties.rasterLayer.setData(AvailableRasterLayers.osmCarto)
|
||||
}
|
||||
)
|
||||
const setLayerCategory = (category: EliCategory) => {
|
||||
const setLayerCategory = (category: EliCategory, skipLayers: number = 0) => {
|
||||
const timeOfCall = new Date()
|
||||
const available = this.availableLayers.store.addCallbackAndRunD((available) => {
|
||||
this.availableLayers.store.addCallbackAndRunD((available) => {
|
||||
const now = new Date()
|
||||
const timeDiff = (now.getTime() - timeOfCall.getTime()) / 1000
|
||||
if (timeDiff > 3) {
|
||||
|
@ -656,9 +649,13 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
const best = RasterLayerUtils.SelectBestLayerAccordingTo(
|
||||
available,
|
||||
category,
|
||||
current.data
|
||||
current.data,
|
||||
skipLayers
|
||||
)
|
||||
console.log("Best layer for category", category, "is", best.properties.id)
|
||||
if(!best){
|
||||
return
|
||||
}
|
||||
console.log("Best layer for category", category, "is", best?.properties?.id)
|
||||
current.setData(best)
|
||||
})
|
||||
}
|
||||
|
@ -666,26 +663,43 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
Hotkeys.RegisterHotkey(
|
||||
{ nomod: "O" },
|
||||
Translations.t.hotkeyDocumentation.selectOsmbasedmap,
|
||||
() => setLayerCategory("osmbasedmap")
|
||||
() => setLayerCategory("osmbasedmap"),
|
||||
)
|
||||
|
||||
Hotkeys.RegisterHotkey(
|
||||
{ nomod: "M" },
|
||||
Translations.t.hotkeyDocumentation.selectMap,
|
||||
() => setLayerCategory("map")
|
||||
() => setLayerCategory("map"),
|
||||
)
|
||||
|
||||
Hotkeys.RegisterHotkey(
|
||||
{ nomod: "P" },
|
||||
Translations.t.hotkeyDocumentation.selectAerial,
|
||||
() => setLayerCategory("photo")
|
||||
() => setLayerCategory("photo"),
|
||||
)
|
||||
Hotkeys.RegisterHotkey(
|
||||
{ shift: "O" },
|
||||
Translations.t.hotkeyDocumentation.selectOsmbasedmap,
|
||||
() => setLayerCategory("osmbasedmap",2),
|
||||
)
|
||||
|
||||
Hotkeys.RegisterHotkey(
|
||||
{ shift: "M" },
|
||||
Translations.t.hotkeyDocumentation.selectMap,
|
||||
() => setLayerCategory("map",2),
|
||||
)
|
||||
|
||||
Hotkeys.RegisterHotkey(
|
||||
{ shift: "P" },
|
||||
Translations.t.hotkeyDocumentation.selectAerial,
|
||||
() => setLayerCategory("photo",2),
|
||||
)
|
||||
Hotkeys.RegisterHotkey(
|
||||
{ nomod: "L" },
|
||||
Translations.t.hotkeyDocumentation.geolocate,
|
||||
() => {
|
||||
this.geolocationControl.handleClick()
|
||||
}
|
||||
},
|
||||
)
|
||||
return true
|
||||
})
|
||||
|
@ -697,7 +711,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
Translations.t.hotkeyDocumentation.translationMode,
|
||||
() => {
|
||||
Locale.showLinkToWeblate.setData(!Locale.showLinkToWeblate.data)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -708,7 +722,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
const normalLayers = this.layout.layers.filter(
|
||||
(l) =>
|
||||
Constants.priviliged_layers.indexOf(<any>l.id) < 0 &&
|
||||
!l.id.startsWith("note_import")
|
||||
!l.id.startsWith("note_import"),
|
||||
)
|
||||
const maxzoom = Math.min(...normalLayers.map((l) => l.minzoom))
|
||||
|
||||
|
@ -716,7 +730,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
(l) =>
|
||||
Constants.priviliged_layers.indexOf(<any>l.id) < 0 &&
|
||||
l.source.geojsonSource === undefined &&
|
||||
l.doCount
|
||||
l.doCount,
|
||||
)
|
||||
const summaryTileSource = new SummaryTileSource(
|
||||
Constants.SummaryServer,
|
||||
|
@ -725,7 +739,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
this.mapProperties,
|
||||
{
|
||||
isActive: this.mapProperties.zoom.map((z) => z < maxzoom),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
return new SummaryTileSourceRewriter(summaryTileSource, this.layerState.filteredLayers)
|
||||
|
@ -746,12 +760,12 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
gps_location_history: this.geolocation.historicalUserLocations,
|
||||
gps_track: this.geolocation.historicalUserLocationsTrack,
|
||||
selected_element: new StaticFeatureSource(
|
||||
this.selectedElement.map((f) => (f === undefined ? empty : [f]))
|
||||
this.selectedElement.map((f) => (f === undefined ? empty : [f])),
|
||||
),
|
||||
range: new StaticFeatureSource(
|
||||
this.mapProperties.maxbounds.map((bbox) =>
|
||||
bbox === undefined ? empty : <Feature[]>[bbox.asGeoJson({ id: "range" })]
|
||||
)
|
||||
bbox === undefined ? empty : <Feature[]>[bbox.asGeoJson({ id: "range" })],
|
||||
),
|
||||
),
|
||||
current_view: this.currentView,
|
||||
favourite: this.favourites,
|
||||
|
@ -766,7 +780,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
ShowDataLayer.showRange(
|
||||
this.map,
|
||||
new StaticFeatureSource([bbox.asGeoJson({ id: "range" })]),
|
||||
this.featureSwitches.featureSwitchIsTesting
|
||||
this.featureSwitches.featureSwitchIsTesting,
|
||||
)
|
||||
}
|
||||
const currentViewLayer = this.layout.layers.find((l) => l.id === "current_view")
|
||||
|
@ -780,7 +794,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
currentViewLayer,
|
||||
this.layout,
|
||||
this.osmObjectDownloader,
|
||||
this.featureProperties
|
||||
this.featureProperties,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -824,20 +838,20 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
|
||||
const lastClickLayerConfig = new LayerConfig(
|
||||
<LayerConfigJson>last_click_layerconfig,
|
||||
"last_click"
|
||||
"last_click",
|
||||
)
|
||||
const lastClickFiltered =
|
||||
lastClickLayerConfig.isShown === undefined
|
||||
? specialLayers.last_click
|
||||
: specialLayers.last_click.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
|
||||
}),
|
||||
)
|
||||
new ShowDataLayer(this.map, {
|
||||
features: new StaticFeatureSource(lastClickFiltered),
|
||||
layer: lastClickLayerConfig,
|
||||
|
@ -884,7 +898,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
this.mapProperties.rasterLayer,
|
||||
this.availableLayers,
|
||||
this.featureSwitches.backgroundLayerId,
|
||||
this.userRelatedState.preferredBackgroundLayer
|
||||
this.userRelatedState.preferredBackgroundLayer,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -900,7 +914,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
? ">>> _Not_ reporting error to report server as testmode is on"
|
||||
: ">>> Reporting error to",
|
||||
Constants.ErrorReportServer,
|
||||
message
|
||||
message,
|
||||
)
|
||||
if (isTesting) {
|
||||
return
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
export let color: string | undefined = undefined
|
||||
export let clss: string | undefined = ""
|
||||
clss ??= ""
|
||||
export let emojiHeight = 40
|
||||
export let emojiHeight = "40px"
|
||||
</script>
|
||||
|
||||
{#if icon}
|
||||
|
@ -147,7 +147,7 @@
|
|||
{:else if icon === "user_circle"}
|
||||
<UserCircleIcon class={clss} {color} />
|
||||
{:else if Utils.isEmoji(icon)}
|
||||
<span style={`font-size: ${emojiHeight}px; line-height: ${emojiHeight}px`}>
|
||||
<span style= {`font-size: ${emojiHeight}; line-height: ${emojiHeight}`}>
|
||||
{icon}
|
||||
</span>
|
||||
{:else}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
* Class which is applied onto the individual icons
|
||||
*/
|
||||
export let clss = ""
|
||||
export let emojiHeight : string = "40px"
|
||||
|
||||
/**
|
||||
* Class applied onto the entire element
|
||||
|
@ -41,7 +42,7 @@
|
|||
<div class={twMerge("relative", size)}>
|
||||
{#each iconsParsed as icon}
|
||||
<div class="absolute top-0 left-0 flex h-full w-full items-center">
|
||||
<Icon icon={icon.icon} color={icon.color} {clss} />
|
||||
<Icon icon={icon.icon} color={icon.color} {clss} {emojiHeight} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
let rasterLayerId = rasterLayer.sync(
|
||||
(l) => l?.properties?.id,
|
||||
[],
|
||||
(id) => availableLayers.find((l) => l.properties.id === id)
|
||||
(id) => availableLayers.find((l) => l.properties.id === id),
|
||||
)
|
||||
rasterLayer.setData(availableLayers[0])
|
||||
$: rasterLayer.setData(availableLayers[0])
|
||||
|
@ -36,13 +36,13 @@
|
|||
return
|
||||
}
|
||||
rasterLayer.setData(fav)
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
onDestroy(
|
||||
rasterLayer.addCallbackAndRunD((selected) => {
|
||||
favourite?.setData(selected.properties.id)
|
||||
})
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@
|
|||
} else {
|
||||
rasterLayerOnMap.setData(undefined)
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,15 @@
|
|||
{#each availableLayers as availableLayer}
|
||||
<option value={availableLayer.properties.id}>
|
||||
{availableLayer.properties.name}
|
||||
{#if availableLayer.properties.category.startsWith("historic")}
|
||||
⏱️
|
||||
{/if}
|
||||
{#if availableLayer.properties.category.endsWith("elevation")}
|
||||
⛰
|
||||
{/if}
|
||||
{#if availableLayer.properties.best}
|
||||
⭐
|
||||
{/if}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
|
|
@ -30,6 +30,12 @@
|
|||
| "large-height"
|
||||
| string
|
||||
}
|
||||
|
||||
const emojiHeights = {
|
||||
"small":"2rem",
|
||||
"medium":"3rem",
|
||||
"large":"5rem"
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if mapping.icon !== undefined}
|
||||
|
@ -42,6 +48,9 @@
|
|||
}-width`,
|
||||
"shrink-0"
|
||||
)}
|
||||
|
||||
emojiHeight={ emojiHeights[mapping.iconClass] ?? "2rem"}
|
||||
|
||||
clss={`mapping-icon-${mapping.iconClass ?? "small"}`}
|
||||
/>
|
||||
<SpecialTranslation t={mapping.then} {tags} {state} {layer} feature={selectedElement} {clss} />
|
||||
|
|
|
@ -1727,11 +1727,12 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
|||
}
|
||||
}
|
||||
|
||||
private static emojiRegex = /^\p{Extended_Pictographic}+$/u
|
||||
private static emojiRegex = /[\p{Extended_Pictographic}🛰️]$/u
|
||||
|
||||
/**
|
||||
* Returns 'true' if the given string contains at least one and only emoji characters
|
||||
* @param string
|
||||
*
|
||||
* Utils.isEmoji("⛰\uFE0F") // => true
|
||||
*/
|
||||
public static isEmoji(string: string) {
|
||||
return Utils.emojiRegex.test(string)
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
{
|
||||
"layers": [
|
||||
{
|
||||
"url": "pmtiles://https://api.protomaps.com/tiles/v3.json?key=2af8b969a9e8b692",
|
||||
"style": "assets/sunny.json",
|
||||
"connect-src": [
|
||||
"https://protomaps.github.io"
|
||||
],
|
||||
"best": true,
|
||||
"id": "protomaps.sunny",
|
||||
"name": "Protomaps Sunny",
|
||||
"type": "vector",
|
||||
"category": "osmbasedmap",
|
||||
"attribution": {
|
||||
"text": "Protomaps",
|
||||
"url": "https://protomaps.com/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "OpenStreetMap Carto",
|
||||
"url": "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
|
@ -87,21 +103,6 @@
|
|||
"url": "https://protomaps.com/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "pmtiles://https://api.protomaps.com/tiles/v3.json?key=2af8b969a9e8b692",
|
||||
"style": "assets/sunny.json",
|
||||
"connect-src": [
|
||||
"https://protomaps.github.io"
|
||||
],
|
||||
"id": "protomaps.sunny",
|
||||
"name": "Protomaps Sunny",
|
||||
"type": "vector",
|
||||
"category": "osmbasedmap",
|
||||
"attribution": {
|
||||
"text": "Protomaps",
|
||||
"url": "https://protomaps.com/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "pmtiles://https://api.protomaps.com/tiles/v3.json?key=2af8b969a9e8b692",
|
||||
"style": "assets/sunny-unlabeled.json",
|
||||
|
|
Loading…
Reference in a new issue