forked from MapComplete/MapComplete
		
	Merge develop
This commit is contained in:
		
							parent
							
								
									c62705c1dd
								
							
						
					
					
						commit
						c167094b65
					
				
					 12 changed files with 251 additions and 139 deletions
				
			
		| 
						 | 
				
			
			@ -1465,13 +1465,51 @@
 | 
			
		|||
      "#force-save-button": "yes"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "id": "debug-gps",
 | 
			
		||||
      "id": "debug-gps-group",
 | 
			
		||||
      "condition": "mapcomplete-show_debug=yes",
 | 
			
		||||
      "render": {
 | 
			
		||||
        "special": {
 | 
			
		||||
          "type": "group",
 | 
			
		||||
          "header": "debug-gps-title",
 | 
			
		||||
          "labels": "debug-gps"
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "id": "debug-gps-title",
 | 
			
		||||
      "labels": ["hidden"],
 | 
			
		||||
      "render": {
 | 
			
		||||
        "en": "GPS info"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "id": "debug-gps",
 | 
			
		||||
      "labels": ["hidden"],
 | 
			
		||||
      "render": "{gps_all_tags()}"
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
      "id": "debug-info-group",
 | 
			
		||||
      "condition": "mapcomplete-show_debug=yes",
 | 
			
		||||
 | 
			
		||||
      "render": {
 | 
			
		||||
        "special": {
 | 
			
		||||
          "type": "group",
 | 
			
		||||
          "header": "debug-tags-title",
 | 
			
		||||
          "labels": "debug"
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "id": "debug-tags-title",
 | 
			
		||||
      "labels": ["hidden"],
 | 
			
		||||
      "render": {
 | 
			
		||||
        "en": "Debug info"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "id": "debug",
 | 
			
		||||
      "condition": "mapcomplete-show_debug=yes",
 | 
			
		||||
      "labels": ["hidden"],
 | 
			
		||||
      "render": "{all_tags()}"
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ export interface GeoLocationPointProperties extends GeolocationCoordinates {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * An abstract representation of the current state of the geolocation.
 | 
			
		||||
 * An abstract representation of the current state of the geolocation, keeping track of permissions and if a location is known.
 | 
			
		||||
 */
 | 
			
		||||
export class GeoLocationState {
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -167,8 +167,16 @@ export class GeoLocationState {
 | 
			
		|||
 | 
			
		||||
        if(AndroidPolyfill.inAndroid.data){
 | 
			
		||||
            this.permission.setData("requested")
 | 
			
		||||
            AndroidPolyfill.geolocationPermission.addCallbackAndRunD(state => this.permission.set(state))
 | 
			
		||||
            this.permission.addCallbackAndRunD(p => {
 | 
			
		||||
                if(p === "granted"){
 | 
			
		||||
                    this.startWatching()
 | 
			
		||||
                    return true
 | 
			
		||||
                }
 | 
			
		||||
            })
 | 
			
		||||
            AndroidPolyfill.requestGeoPermission().then(state => {
 | 
			
		||||
                const granted = state.value === "true"
 | 
			
		||||
                this.permission.set(granted ? "granted" : "denied")
 | 
			
		||||
            })
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -210,6 +218,13 @@ export class GeoLocationState {
 | 
			
		|||
     * @private
 | 
			
		||||
     */
 | 
			
		||||
    private async startWatching() {
 | 
			
		||||
 | 
			
		||||
        if(AndroidPolyfill.inAndroid.data){
 | 
			
		||||
            AndroidPolyfill.watchLocation( this.currentGPSLocation, location => {
 | 
			
		||||
                console.log(JSON.stringify(location))
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        navigator.geolocation.watchPosition(
 | 
			
		||||
             (position: GeolocationPosition) => {
 | 
			
		||||
                this._gpsAvailable.set(true)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -416,6 +416,10 @@ export default class UserRelatedState {
 | 
			
		|||
                typeof window === "undefined" ? "no" : window.navigator.share ? "yes" : "no",
 | 
			
		||||
            _iframe: Utils.isIframe ? "yes" : "no",
 | 
			
		||||
        })
 | 
			
		||||
        if(!Utils.runningFromConsole){
 | 
			
		||||
            amendedPrefs.data["_host"] = window.location.host
 | 
			
		||||
            amendedPrefs.data["_path"] = window.location.pathname
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (const key in Constants.userJourney) {
 | 
			
		||||
            amendedPrefs.data["__userjourney_" + key] = Constants.userJourney[key]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,9 +19,9 @@ const DatabridgePluginSingleton = registerPlugin<DatabridgePlugin>("Databridge",
 | 
			
		|||
                    return { value: "web" }
 | 
			
		||||
                }
 | 
			
		||||
                return null
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    },
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export class AndroidPolyfill {
 | 
			
		||||
| 
						 | 
				
			
			@ -36,12 +36,18 @@ export class AndroidPolyfill {
 | 
			
		|||
     * @private
 | 
			
		||||
     */
 | 
			
		||||
    private backfillGeolocation(databridgePlugin: DatabridgePlugin) {
 | 
			
		||||
        const src = UIEventSource.FromPromise(databridgePlugin.request({ key: "location:request-permission" }))
 | 
			
		||||
        const src = UIEventSource.FromPromise(databridgePlugin.request({ key: "location:has-permission" }))
 | 
			
		||||
        src.addCallbackAndRunD(permission => {
 | 
			
		||||
            AndroidPolyfill._geolocationPermission.set(<"granted" | "denied">permission.value)
 | 
			
		||||
            console.log("> Checking geopermission gave: ", JSON.stringify(permission), permission.value)
 | 
			
		||||
            const granted = permission.value === "true"
 | 
			
		||||
            AndroidPolyfill._geolocationPermission.set(granted ? "granted" : "denied")
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static async requestGeoPermission(): Promise<{ value: string | object }> {
 | 
			
		||||
        return DatabridgePluginSingleton.request({ key: "location:request-permission" })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async init() {
 | 
			
		||||
        console.log("Sniffing shell version")
 | 
			
		||||
        const shell = await this.databridgePlugin.request({ key: "meta" })
 | 
			
		||||
| 
						 | 
				
			
			@ -55,9 +61,9 @@ export class AndroidPolyfill {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    public static async requestLoginCodes() {
 | 
			
		||||
        const result = await DatabridgePluginSingleton.request<{oauth_token: string}>({ key: "request:login" })
 | 
			
		||||
        const result = await DatabridgePluginSingleton.request<{ oauth_token: string }>({ key: "request:login" })
 | 
			
		||||
        const token: string = result.value.oauth_token
 | 
			
		||||
        console.log("AndroidPolyfill: received oauth_token; trying to pass them to the oauth lib",token)
 | 
			
		||||
        console.log("AndroidPolyfill: received oauth_token; trying to pass them to the oauth lib", token)
 | 
			
		||||
        return token
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +73,7 @@ export class AndroidPolyfill {
 | 
			
		|||
        console.log("Registering back button callback", callback)
 | 
			
		||||
        DatabridgePluginSingleton.request({ key: "backbutton" }).then(ev => {
 | 
			
		||||
            console.log("AndroidPolyfill: received backbutton: ", ev)
 | 
			
		||||
            if(ev === null){
 | 
			
		||||
            if (ev === null) {
 | 
			
		||||
                // Probably in web environment
 | 
			
		||||
                return
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -84,5 +90,26 @@ export class AndroidPolyfill {
 | 
			
		|||
        })
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static watchLocation(writeInto: UIEventSource<GeolocationCoordinates>, callback: (location) => void) {
 | 
			
		||||
        DatabridgePluginSingleton.request({
 | 
			
		||||
            key: "location:watch",
 | 
			
		||||
        }).then((l: {
 | 
			
		||||
            value: { latitude: number, longitude: number, accuraccy: number, altidude: number, heading: number, speed:number }
 | 
			
		||||
        }) => {
 | 
			
		||||
            // example l: {"value":{"latitude":51.0618627,"longitude":3.730468566666667,"accuracy":2.0393495559692383,"altitude":46.408,"heading":168.2969970703125}}
 | 
			
		||||
            console.log("Received location from Android:", JSON.stringify(l))
 | 
			
		||||
            const loc = l.value
 | 
			
		||||
            writeInto.set({
 | 
			
		||||
                latitude: loc.latitude,
 | 
			
		||||
                longitude: loc.longitude,
 | 
			
		||||
                heading: loc.heading,
 | 
			
		||||
                accuracy: loc.accuraccy,
 | 
			
		||||
                altitude: loc.altidude,
 | 
			
		||||
                altitudeAccuracy: undefined,
 | 
			
		||||
                speed: loc.speed,
 | 
			
		||||
            })
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -126,6 +126,9 @@ export default class TagRenderingConfig {
 | 
			
		|||
                this.id
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        if(json.labels && !Array.isArray( json.labels)){
 | 
			
		||||
            throw (`Invalid labels at ${context}: labels should be a list of strings, but got a ${typeof json.labels}`)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.labels = json.labels ?? []
 | 
			
		||||
        if (typeof json.classes === "string") {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
  import { ariaLabel } from "../../Utils/ariaLabel"
 | 
			
		||||
  import { Translation } from "../i18n/Translation"
 | 
			
		||||
  import Backspace from "@babeard/svelte-heroicons/outline/Backspace"
 | 
			
		||||
  import { AndroidPolyfill } from "../../Logic/Web/AndroidPolyfill"
 | 
			
		||||
 | 
			
		||||
  export let value: UIEventSource<string>
 | 
			
		||||
  let _value = value.data ?? ""
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +37,7 @@
 | 
			
		|||
  if (autofocus) {
 | 
			
		||||
    isFocused.set(true)
 | 
			
		||||
  }
 | 
			
		||||
  let isAndroid = AndroidPolyfill.inAndroid
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<form class="w-full" on:submit|preventDefault={() => dispatch("search")}>
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +64,8 @@
 | 
			
		|||
      use:set_placeholder={placeholder}
 | 
			
		||||
      use:ariaLabel={placeholder}
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
    {#if !isAndroid}
 | 
			
		||||
      <!-- Show a 'clear field' icon in the searchbar. The android-build already provides this for us, hence the outer if -->
 | 
			
		||||
      {#if $value.length > 0}
 | 
			
		||||
        <Backspace
 | 
			
		||||
          on:click={(e) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -75,5 +78,6 @@
 | 
			
		|||
      {:else}
 | 
			
		||||
        <div class="mr-3 w-6" />
 | 
			
		||||
      {/if}
 | 
			
		||||
    {/if}
 | 
			
		||||
  </label>
 | 
			
		||||
</form>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@
 | 
			
		|||
  import Location_locked from "../../assets/svg/Location_locked.svelte"
 | 
			
		||||
  import Location_unlocked from "../../assets/svg/Location_unlocked.svelte"
 | 
			
		||||
  import Location from "../../assets/svg/Location.svelte"
 | 
			
		||||
  import Location_empty from "../../assets/svg/Location_empty.svelte"
 | 
			
		||||
 | 
			
		||||
  export let state: ThemeViewState
 | 
			
		||||
  let geolocationstate = state.geolocation.geolocationState
 | 
			
		||||
| 
						 | 
				
			
			@ -31,10 +32,10 @@
 | 
			
		|||
{:else if $geopermission === "denied" || !$isAvailable}
 | 
			
		||||
  <Location_refused class={clss} />
 | 
			
		||||
{:else if $geopermission === "prompt"}
 | 
			
		||||
  <Location class={clss} />
 | 
			
		||||
  <Location_empty class={clss} />
 | 
			
		||||
{:else if $geopermission === "requested"}
 | 
			
		||||
  <!-- Even though disabled, when clicking we request the location again in case the contributor dismissed the location popup -->
 | 
			
		||||
  <Location class={clss} style="animation: 3s linear 0s infinite normal none running spin;" />
 | 
			
		||||
  <Location_empty class={clss} style="animation: 3s linear 0s infinite normal none running spin;" />
 | 
			
		||||
{:else}
 | 
			
		||||
  <Location class={clss} style="animation: 3s linear 0s infinite normal none running spin;" />
 | 
			
		||||
{/if}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -319,7 +319,7 @@
 | 
			
		|||
  if (state?.osmConnection) {
 | 
			
		||||
    onDestroy(
 | 
			
		||||
      state.osmConnection?.userDetails?.addCallbackAndRun((ud) => {
 | 
			
		||||
        numberOfCs = ud.csCount
 | 
			
		||||
        numberOfCs = ud?.csCount
 | 
			
		||||
      })
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -122,7 +122,7 @@ class NearbyImageVis implements SpecialVisualization {
 | 
			
		|||
        tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
        args: string[],
 | 
			
		||||
        feature: Feature,
 | 
			
		||||
        layer: LayerConfig
 | 
			
		||||
        layer: LayerConfig,
 | 
			
		||||
    ): SvelteUIElement {
 | 
			
		||||
        const isOpen = args[0] === "open"
 | 
			
		||||
        const readonly = args[1] === "readonly" || args[1] === "yes"
 | 
			
		||||
| 
						 | 
				
			
			@ -189,7 +189,7 @@ class StealViz implements SpecialVisualization {
 | 
			
		|||
                                selectedElement: otherFeature,
 | 
			
		||||
                                state,
 | 
			
		||||
                                layer,
 | 
			
		||||
                            })
 | 
			
		||||
                            }),
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                    if (elements.length === 1) {
 | 
			
		||||
| 
						 | 
				
			
			@ -197,8 +197,8 @@ class StealViz implements SpecialVisualization {
 | 
			
		|||
                    }
 | 
			
		||||
                    return new Combine(elements).SetClass("flex flex-col")
 | 
			
		||||
                },
 | 
			
		||||
                [state.indexedFeatures.featuresById]
 | 
			
		||||
            )
 | 
			
		||||
                [state.indexedFeatures.featuresById],
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -250,11 +250,11 @@ class CloseNoteViz implements SpecialVisualization {
 | 
			
		|||
    public constr(
 | 
			
		||||
        state: SpecialVisualizationState,
 | 
			
		||||
        tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
        args: string[]
 | 
			
		||||
        args: string[],
 | 
			
		||||
    ): SvelteUIElement {
 | 
			
		||||
        const { text, icon, idkey, comment, minZoom, zoomButton } = Utils.ParseVisArgs(
 | 
			
		||||
            this.args,
 | 
			
		||||
            args
 | 
			
		||||
            args,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        return new SvelteUIElement(CloseNoteButton, {
 | 
			
		||||
| 
						 | 
				
			
			@ -295,7 +295,7 @@ export class QuestionViz implements SpecialVisualization {
 | 
			
		|||
        tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
        args: string[],
 | 
			
		||||
        feature: Feature,
 | 
			
		||||
        layer: LayerConfig
 | 
			
		||||
        layer: LayerConfig,
 | 
			
		||||
    ): SvelteUIElement {
 | 
			
		||||
        const labels = args[0]
 | 
			
		||||
            ?.split(";")
 | 
			
		||||
| 
						 | 
				
			
			@ -327,7 +327,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
        for (const specialVisualization of SpecialVisualizations.specialVisualizations) {
 | 
			
		||||
            SpecialVisualizations.specialVisualisationsDict.set(
 | 
			
		||||
                specialVisualization.funcName,
 | 
			
		||||
                specialVisualization
 | 
			
		||||
                specialVisualization,
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -354,7 +354,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                            defaultArg = "_empty string_"
 | 
			
		||||
                        }
 | 
			
		||||
                        return [arg.name, defaultArg, arg.doc]
 | 
			
		||||
                      })
 | 
			
		||||
                    }),
 | 
			
		||||
                )
 | 
			
		||||
                : undefined,
 | 
			
		||||
            "#### Example usage of " + viz.funcName,
 | 
			
		||||
| 
						 | 
				
			
			@ -364,18 +364,18 @@ export default class SpecialVisualizations {
 | 
			
		|||
 | 
			
		||||
    public static constructSpecification(
 | 
			
		||||
        template: string,
 | 
			
		||||
        extraMappings: SpecialVisualization[] = []
 | 
			
		||||
        extraMappings: SpecialVisualization[] = [],
 | 
			
		||||
    ): RenderingSpecification[] {
 | 
			
		||||
        return SpecialVisualisationUtils.constructSpecification(
 | 
			
		||||
            template,
 | 
			
		||||
            SpecialVisualizations.specialVisualisationsDict,
 | 
			
		||||
            extraMappings
 | 
			
		||||
            extraMappings,
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static HelpMessage(): string {
 | 
			
		||||
        const helpTexts: string[] = SpecialVisualizations.specialVisualizations.map((viz) =>
 | 
			
		||||
            SpecialVisualizations.DocumentationFor(viz)
 | 
			
		||||
            SpecialVisualizations.DocumentationFor(viz),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        const firstPart = new Combine([
 | 
			
		||||
| 
						 | 
				
			
			@ -408,10 +408,10 @@ export default class SpecialVisualizations {
 | 
			
		|||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                    null,
 | 
			
		||||
                    "  "
 | 
			
		||||
                )
 | 
			
		||||
                    "  ",
 | 
			
		||||
                ),
 | 
			
		||||
            ).SetClass("code"),
 | 
			
		||||
            'In other words: use `{ "before": ..., "after": ..., "special": {"type": ..., "argname": ...argvalue...}`. The args are in the `special` block; an argvalue can be a string, a translation or another value. (Refer to class `RewriteSpecial` in case of problems)',
 | 
			
		||||
            "In other words: use `{ \"before\": ..., \"after\": ..., \"special\": {\"type\": ..., \"argname\": ...argvalue...}`. The args are in the `special` block; an argvalue can be a string, a translation or another value. (Refer to class `RewriteSpecial` in case of problems)",
 | 
			
		||||
        ])
 | 
			
		||||
            .SetClass("flex flex-col")
 | 
			
		||||
            .AsMarkdown()
 | 
			
		||||
| 
						 | 
				
			
			@ -452,7 +452,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                    (ud) => ud?.languages ?? []
 | 
			
		||||
                                ),
 | 
			
		||||
                            })
 | 
			
		||||
                        })
 | 
			
		||||
                        }),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -491,7 +491,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    state: SpecialVisualizationState,
 | 
			
		||||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    args: string[],
 | 
			
		||||
                    feature: Feature
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                ): SvelteUIElement {
 | 
			
		||||
                    return new SvelteUIElement(MinimapViz, { state, args, feature, tagSource })
 | 
			
		||||
                },
 | 
			
		||||
| 
						 | 
				
			
			@ -503,7 +503,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
 | 
			
		||||
                constr(
 | 
			
		||||
                    state: SpecialVisualizationState,
 | 
			
		||||
                    tagSource: UIEventSource<Record<string, string>>
 | 
			
		||||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    return new VariableUiElement(
 | 
			
		||||
                        tagSource
 | 
			
		||||
| 
						 | 
				
			
			@ -513,7 +513,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                    return new SvelteUIElement(SplitRoadWizard, { id, state })
 | 
			
		||||
                                }
 | 
			
		||||
                                return undefined
 | 
			
		||||
                            })
 | 
			
		||||
                            }),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -527,7 +527,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    if (feature.geometry.type !== "Point") {
 | 
			
		||||
                        return undefined
 | 
			
		||||
| 
						 | 
				
			
			@ -550,7 +550,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    if (!layer.deletion) {
 | 
			
		||||
                        return undefined
 | 
			
		||||
| 
						 | 
				
			
			@ -576,7 +576,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ) {
 | 
			
		||||
                    if (feature.geometry.type !== "LineString") {
 | 
			
		||||
                        return undefined
 | 
			
		||||
| 
						 | 
				
			
			@ -608,7 +608,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    state: SpecialVisualizationState,
 | 
			
		||||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const [lon, lat] = GeoOperations.centerpointCoordinates(feature)
 | 
			
		||||
                    return new SvelteUIElement(CreateNewNote, {
 | 
			
		||||
| 
						 | 
				
			
			@ -671,7 +671,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                            .map((tags) => tags[args[0]])
 | 
			
		||||
                            .map((wikidata) => {
 | 
			
		||||
                                wikidata = Utils.NoEmpty(
 | 
			
		||||
                                    wikidata?.split(";")?.map((wd) => wd.trim()) ?? []
 | 
			
		||||
                                    wikidata?.split(";")?.map((wd) => wd.trim()) ?? [],
 | 
			
		||||
                                )[0]
 | 
			
		||||
                                const entry = Wikidata.LoadWikidataEntry(wikidata)
 | 
			
		||||
                                return new VariableUiElement(
 | 
			
		||||
| 
						 | 
				
			
			@ -681,9 +681,9 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                        }
 | 
			
		||||
                                        const response = <WikidataResponse>e["success"]
 | 
			
		||||
                                        return Translation.fromMap(response.labels)
 | 
			
		||||
                                    })
 | 
			
		||||
                                    }),
 | 
			
		||||
                                )
 | 
			
		||||
                            })
 | 
			
		||||
                            }),
 | 
			
		||||
                    ),
 | 
			
		||||
            },
 | 
			
		||||
            new MapillaryLinkVis(),
 | 
			
		||||
| 
						 | 
				
			
			@ -697,7 +697,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    _,
 | 
			
		||||
                    __,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ) => new SvelteUIElement(AllTagsPanel, { tags, layer }),
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -782,7 +782,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                            nameKey: nameKey,
 | 
			
		||||
                            fallbackName,
 | 
			
		||||
                        },
 | 
			
		||||
                        state.featureSwitchIsTesting
 | 
			
		||||
                        state.featureSwitchIsTesting,
 | 
			
		||||
                    )
 | 
			
		||||
                    return new SvelteUIElement(StarsBarIcon, {
 | 
			
		||||
                        score: reviews.average,
 | 
			
		||||
| 
						 | 
				
			
			@ -821,7 +821,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                            nameKey: nameKey,
 | 
			
		||||
                            fallbackName,
 | 
			
		||||
                        },
 | 
			
		||||
                        state.featureSwitchIsTesting
 | 
			
		||||
                        state.featureSwitchIsTesting,
 | 
			
		||||
                    )
 | 
			
		||||
                    return new SvelteUIElement(ReviewForm, {
 | 
			
		||||
                        reviews,
 | 
			
		||||
| 
						 | 
				
			
			@ -859,7 +859,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                            nameKey: nameKey,
 | 
			
		||||
                            fallbackName,
 | 
			
		||||
                        },
 | 
			
		||||
                        state.featureSwitchIsTesting
 | 
			
		||||
                        state.featureSwitchIsTesting,
 | 
			
		||||
                    )
 | 
			
		||||
                    return new SvelteUIElement(AllReviews, { reviews, state, tags, feature, layer })
 | 
			
		||||
                },
 | 
			
		||||
| 
						 | 
				
			
			@ -889,7 +889,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    args: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    return new Combine([
 | 
			
		||||
                        SpecialVisualizations.specialVisualisationsDict
 | 
			
		||||
| 
						 | 
				
			
			@ -914,7 +914,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                constr(
 | 
			
		||||
                    state: SpecialVisualizationState,
 | 
			
		||||
                    _: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[]
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const [text] = argument
 | 
			
		||||
                    return new SvelteUIElement(ImportReviewIdentity, { state, text })
 | 
			
		||||
| 
						 | 
				
			
			@ -971,7 +971,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                constr(
 | 
			
		||||
                    state: SpecialVisualizationState,
 | 
			
		||||
                    tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    args: string[]
 | 
			
		||||
                    args: string[],
 | 
			
		||||
                ): SvelteUIElement {
 | 
			
		||||
                    const keyToUse = args[0]
 | 
			
		||||
                    const prefix = args[1]
 | 
			
		||||
| 
						 | 
				
			
			@ -1008,17 +1008,17 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                    return undefined
 | 
			
		||||
                                }
 | 
			
		||||
                                const allUnits: Unit[] = [].concat(
 | 
			
		||||
                                    ...(state?.theme?.layers?.map((lyr) => lyr.units) ?? [])
 | 
			
		||||
                                    ...(state?.theme?.layers?.map((lyr) => lyr.units) ?? []),
 | 
			
		||||
                                )
 | 
			
		||||
                                const unit = allUnits.filter((unit) =>
 | 
			
		||||
                                    unit.isApplicableToKey(key)
 | 
			
		||||
                                    unit.isApplicableToKey(key),
 | 
			
		||||
                                )[0]
 | 
			
		||||
                                if (unit === undefined) {
 | 
			
		||||
                                    return value
 | 
			
		||||
                                }
 | 
			
		||||
                                const getCountry = () => tagSource.data._country
 | 
			
		||||
                                return unit.asHumanLongValue(value, getCountry)
 | 
			
		||||
                            })
 | 
			
		||||
                            }),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -1072,7 +1072,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                constr: (state) => {
 | 
			
		||||
                    return new SubtleButton(
 | 
			
		||||
                        new SvelteUIElement(Trash),
 | 
			
		||||
                        Translations.t.general.removeLocationHistory
 | 
			
		||||
                        Translations.t.general.removeLocationHistory,
 | 
			
		||||
                    ).onClick(() => {
 | 
			
		||||
                        state.historicalUserLocations.features.setData([])
 | 
			
		||||
                        state.selectedElement.setData(undefined)
 | 
			
		||||
| 
						 | 
				
			
			@ -1113,10 +1113,10 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                                new SvelteUIElement(NoteCommentElement, {
 | 
			
		||||
                                                    comment,
 | 
			
		||||
                                                    state,
 | 
			
		||||
                                                })
 | 
			
		||||
                                        )
 | 
			
		||||
                                                }),
 | 
			
		||||
                                        ),
 | 
			
		||||
                                ).SetClass("flex flex-col")
 | 
			
		||||
                            })
 | 
			
		||||
                            }),
 | 
			
		||||
                    ),
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -1149,7 +1149,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    _: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ) => {
 | 
			
		||||
                    return new SvelteUIElement(FeatureTitle, { state, tags, feature, layer })
 | 
			
		||||
                },
 | 
			
		||||
| 
						 | 
				
			
			@ -1167,8 +1167,8 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    const challenge = Stores.FromPromise(
 | 
			
		||||
                        Utils.downloadJsonCached<MaprouletteTask>(
 | 
			
		||||
                            `${Maproulette.defaultEndpoint}/challenge/${parentId}`,
 | 
			
		||||
                            24 * 60 * 60 * 1000
 | 
			
		||||
                        )
 | 
			
		||||
                            24 * 60 * 60 * 1000,
 | 
			
		||||
                        ),
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
                    return new VariableUiElement(
 | 
			
		||||
| 
						 | 
				
			
			@ -1193,7 +1193,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                            } else {
 | 
			
		||||
                                return [title, new List(listItems)]
 | 
			
		||||
                            }
 | 
			
		||||
                        })
 | 
			
		||||
                        }),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
                docs: "Fetches the metadata of MapRoulette campaign that this task is part of and shows those details (namely `title`, `description` and `instruction`).\n\nThis reads the property `mr_challengeId` to detect the parent campaign.",
 | 
			
		||||
| 
						 | 
				
			
			@ -1207,15 +1207,15 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    "\n" +
 | 
			
		||||
                    "```json\n" +
 | 
			
		||||
                    "{\n" +
 | 
			
		||||
                    '   "id": "mark_duplicate",\n' +
 | 
			
		||||
                    '   "render": {\n' +
 | 
			
		||||
                    '      "special": {\n' +
 | 
			
		||||
                    '         "type": "maproulette_set_status",\n' +
 | 
			
		||||
                    '         "message": {\n' +
 | 
			
		||||
                    '            "en": "Mark as not found or false positive"\n' +
 | 
			
		||||
                    "   \"id\": \"mark_duplicate\",\n" +
 | 
			
		||||
                    "   \"render\": {\n" +
 | 
			
		||||
                    "      \"special\": {\n" +
 | 
			
		||||
                    "         \"type\": \"maproulette_set_status\",\n" +
 | 
			
		||||
                    "         \"message\": {\n" +
 | 
			
		||||
                    "            \"en\": \"Mark as not found or false positive\"\n" +
 | 
			
		||||
                    "         },\n" +
 | 
			
		||||
                    '         "status": "2",\n' +
 | 
			
		||||
                    '         "image": "close"\n' +
 | 
			
		||||
                    "         \"status\": \"2\",\n" +
 | 
			
		||||
                    "         \"image\": \"close\"\n" +
 | 
			
		||||
                    "      }\n" +
 | 
			
		||||
                    "   }\n" +
 | 
			
		||||
                    "}\n" +
 | 
			
		||||
| 
						 | 
				
			
			@ -1291,7 +1291,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                (l) =>
 | 
			
		||||
                                    l.name !== null &&
 | 
			
		||||
                                    l.title &&
 | 
			
		||||
                                    state.perLayer.get(l.id) !== undefined
 | 
			
		||||
                                    state.perLayer.get(l.id) !== undefined,
 | 
			
		||||
                            )
 | 
			
		||||
                            .map(
 | 
			
		||||
                                (l) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -1301,8 +1301,8 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                    const fsBboxed = new BBoxFeatureSourceForLayer(fs, bbox)
 | 
			
		||||
                                    return new StatisticsPanel(fsBboxed)
 | 
			
		||||
                                },
 | 
			
		||||
                                [state.mapProperties.bounds]
 | 
			
		||||
                            )
 | 
			
		||||
                                [state.mapProperties.bounds],
 | 
			
		||||
                            ),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -1372,7 +1372,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                constr(
 | 
			
		||||
                    state: SpecialVisualizationState,
 | 
			
		||||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    args: string[]
 | 
			
		||||
                    args: string[],
 | 
			
		||||
                ): SvelteUIElement {
 | 
			
		||||
                    let [text, href, classnames, download, ariaLabel, icon] = args
 | 
			
		||||
                    if (download === "") {
 | 
			
		||||
| 
						 | 
				
			
			@ -1410,7 +1410,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                            },
 | 
			
		||||
                        },
 | 
			
		||||
                        null,
 | 
			
		||||
                        "  "
 | 
			
		||||
                        "  ",
 | 
			
		||||
                    ) +
 | 
			
		||||
                    "\n```",
 | 
			
		||||
                args: [
 | 
			
		||||
| 
						 | 
				
			
			@ -1434,7 +1434,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    featureTags: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    args: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ) {
 | 
			
		||||
                    const [key, tr, classesRaw] = args
 | 
			
		||||
                    let classes = classesRaw ?? ""
 | 
			
		||||
| 
						 | 
				
			
			@ -1452,7 +1452,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                    "Could not create a special visualization for multi(",
 | 
			
		||||
                                    args.join(", ") + ")",
 | 
			
		||||
                                    "no properties found for object",
 | 
			
		||||
                                    feature.properties.id
 | 
			
		||||
                                    feature.properties.id,
 | 
			
		||||
                                )
 | 
			
		||||
                                return undefined
 | 
			
		||||
                            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1469,7 +1469,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                elements.push(subsTr)
 | 
			
		||||
                            }
 | 
			
		||||
                            return elements
 | 
			
		||||
                        })
 | 
			
		||||
                        }),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -1489,7 +1489,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    return new VariableUiElement(
 | 
			
		||||
                        tagSource.map((tags) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -1501,7 +1501,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                console.error("Cannot create a translation for", v, "due to", e)
 | 
			
		||||
                                return JSON.stringify(v)
 | 
			
		||||
                            }
 | 
			
		||||
                        })
 | 
			
		||||
                        }),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -1521,7 +1521,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const key = argument[0]
 | 
			
		||||
                    return new SvelteUIElement(FediverseLink, { key, tags, state })
 | 
			
		||||
| 
						 | 
				
			
			@ -1543,7 +1543,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    args: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    return new FixedUiElement("{" + args[0] + "}")
 | 
			
		||||
                },
 | 
			
		||||
| 
						 | 
				
			
			@ -1564,7 +1564,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const key = argument[0] ?? "value"
 | 
			
		||||
                    return new VariableUiElement(
 | 
			
		||||
| 
						 | 
				
			
			@ -1584,10 +1584,10 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                    "Could not parse this tag: " +
 | 
			
		||||
                                    JSON.stringify(value) +
 | 
			
		||||
                                    " due to " +
 | 
			
		||||
                                        e
 | 
			
		||||
                                    e,
 | 
			
		||||
                                ).SetClass("alert")
 | 
			
		||||
                            }
 | 
			
		||||
                        })
 | 
			
		||||
                        }),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -1608,7 +1608,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const giggityUrl = argument[0]
 | 
			
		||||
                    return new SvelteUIElement(Giggity, { tags: tagSource, state, giggityUrl })
 | 
			
		||||
| 
						 | 
				
			
			@ -1624,15 +1624,24 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    _: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const tags = (<ThemeViewState>(
 | 
			
		||||
                        state
 | 
			
		||||
                    )).geolocation.currentUserLocation.features.map(
 | 
			
		||||
                        (features) => features[0]?.properties
 | 
			
		||||
                    const geostate = (<ThemeViewState>(state)).geolocation.geolocationState
 | 
			
		||||
                    const tags = geostate.currentGPSLocation.map(
 | 
			
		||||
                        (geoloc) => {
 | 
			
		||||
                            const tags = { }
 | 
			
		||||
                            for (const k in geoloc ?? {}) {
 | 
			
		||||
                                tags[k] = geoloc[k]
 | 
			
		||||
                            }
 | 
			
		||||
                            tags["_permission"] = geostate.permission.data,
 | 
			
		||||
                            tags["_request_moment"] = geostate.requestMoment.data
 | 
			
		||||
                            return tags
 | 
			
		||||
                        },
 | 
			
		||||
                        [geostate.permission, geostate.requestMoment]
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
                    return new Combine([
 | 
			
		||||
                        new SvelteUIElement(OrientationDebugPanel, {}),
 | 
			
		||||
                        new SvelteUIElement(OrientationDebugPanel, {}), // compass and gyroscope info
 | 
			
		||||
                        new SvelteUIElement(AllTagsPanel, {
 | 
			
		||||
                            state,
 | 
			
		||||
                            tags,
 | 
			
		||||
| 
						 | 
				
			
			@ -1651,7 +1660,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    return new SvelteUIElement(MarkAsFavourite, {
 | 
			
		||||
                        tags: tagSource,
 | 
			
		||||
| 
						 | 
				
			
			@ -1671,7 +1680,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    return new SvelteUIElement(MarkAsFavouriteMini, {
 | 
			
		||||
                        tags: tagSource,
 | 
			
		||||
| 
						 | 
				
			
			@ -1691,7 +1700,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    return new SvelteUIElement(DirectionIndicator, { state, feature })
 | 
			
		||||
                },
 | 
			
		||||
| 
						 | 
				
			
			@ -1704,7 +1713,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    state: SpecialVisualizationState,
 | 
			
		||||
                    tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                ): SvelteUIElement {
 | 
			
		||||
                    return new SvelteUIElement(QrCode, { state, tags, feature })
 | 
			
		||||
                },
 | 
			
		||||
| 
						 | 
				
			
			@ -1723,7 +1732,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                constr(
 | 
			
		||||
                    state: SpecialVisualizationState,
 | 
			
		||||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    args: string[]
 | 
			
		||||
                    args: string[],
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const key = args[0] === "" ? "_direction:centerpoint" : args[0]
 | 
			
		||||
                    return new VariableUiElement(
 | 
			
		||||
| 
						 | 
				
			
			@ -1734,11 +1743,11 @@ export default class SpecialVisualizations {
 | 
			
		|||
                            })
 | 
			
		||||
                            .mapD((value) => {
 | 
			
		||||
                                const dir = GeoOperations.bearingToHuman(
 | 
			
		||||
                                    GeoOperations.parseBearing(value)
 | 
			
		||||
                                    GeoOperations.parseBearing(value),
 | 
			
		||||
                                )
 | 
			
		||||
                                console.log("Human dir", dir)
 | 
			
		||||
                                return Translations.t.general.visualFeedback.directionsAbsolute[dir]
 | 
			
		||||
                            })
 | 
			
		||||
                            }),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -1768,7 +1777,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    args: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const url = args[0]
 | 
			
		||||
                    const readonly = args[3] === "yes"
 | 
			
		||||
| 
						 | 
				
			
			@ -1794,12 +1803,12 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    args: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    return new Toggle(
 | 
			
		||||
                        undefined,
 | 
			
		||||
                        new SvelteUIElement(LoginButton, { osmConnection: state.osmConnection }),
 | 
			
		||||
                        state.osmConnection.isLoggedIn
 | 
			
		||||
                        state.osmConnection.isLoggedIn,
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -1837,7 +1846,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const key = argument[0] ?? "website"
 | 
			
		||||
                    const useProxy = argument[1] !== "no"
 | 
			
		||||
| 
						 | 
				
			
			@ -1845,7 +1854,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    const isClosed = (argument[4] ?? "yes") === "yes"
 | 
			
		||||
 | 
			
		||||
                    const countryStore: Store<string | undefined> = tags.mapD(
 | 
			
		||||
                        (tags) => tags._country
 | 
			
		||||
                        (tags) => tags._country,
 | 
			
		||||
                    )
 | 
			
		||||
                    const sourceUrl: Store<string | undefined> = tags.mapD((tags) => {
 | 
			
		||||
                        if (!tags[key] || tags[key] === "undefined") {
 | 
			
		||||
| 
						 | 
				
			
			@ -1867,24 +1876,24 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                                const features =
 | 
			
		||||
                                                    await LinkedDataLoader.fetchVeloparkEntry(
 | 
			
		||||
                                                        url,
 | 
			
		||||
                                                        loadAll
 | 
			
		||||
                                                        loadAll,
 | 
			
		||||
                                                    )
 | 
			
		||||
                                                const feature =
 | 
			
		||||
                                                    features.find(
 | 
			
		||||
                                                        (f) => f.properties["ref:velopark"] === url
 | 
			
		||||
                                                        (f) => f.properties["ref:velopark"] === url,
 | 
			
		||||
                                                    ) ?? features[0]
 | 
			
		||||
                                                const properties = feature.properties
 | 
			
		||||
                                                properties["ref:velopark"] = url
 | 
			
		||||
                                                console.log(
 | 
			
		||||
                                                    "Got properties from velopark:",
 | 
			
		||||
                                                    properties
 | 
			
		||||
                                                    properties,
 | 
			
		||||
                                                )
 | 
			
		||||
                                                return properties
 | 
			
		||||
                                            } catch (e) {
 | 
			
		||||
                                                console.error(e)
 | 
			
		||||
                                                throw e
 | 
			
		||||
                                            }
 | 
			
		||||
                                        })()
 | 
			
		||||
                                        })(),
 | 
			
		||||
                                    )
 | 
			
		||||
                                }
 | 
			
		||||
                                if (country === undefined) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1896,29 +1905,29 @@ export default class SpecialVisualizations {
 | 
			
		|||
                                            return await LinkedDataLoader.fetchJsonLd(
 | 
			
		||||
                                                url,
 | 
			
		||||
                                                { country },
 | 
			
		||||
                                                useProxy ? "proxy" : "fetch-lod"
 | 
			
		||||
                                                useProxy ? "proxy" : "fetch-lod",
 | 
			
		||||
                                            )
 | 
			
		||||
                                        } catch (e) {
 | 
			
		||||
                                            console.log(
 | 
			
		||||
                                                "Could not get with proxy/download LOD, attempting to download directly. Error for ",
 | 
			
		||||
                                                url,
 | 
			
		||||
                                                "is",
 | 
			
		||||
                                                e
 | 
			
		||||
                                                e,
 | 
			
		||||
                                            )
 | 
			
		||||
                                            return await LinkedDataLoader.fetchJsonLd(
 | 
			
		||||
                                                url,
 | 
			
		||||
                                                { country },
 | 
			
		||||
                                                "fetch-raw"
 | 
			
		||||
                                                "fetch-raw",
 | 
			
		||||
                                            )
 | 
			
		||||
                                        }
 | 
			
		||||
                                    })()
 | 
			
		||||
                                    })(),
 | 
			
		||||
                                )
 | 
			
		||||
                            },
 | 
			
		||||
                            [countryStore]
 | 
			
		||||
                            [countryStore],
 | 
			
		||||
                        )
 | 
			
		||||
 | 
			
		||||
                    externalData.addCallbackAndRunD((lod) =>
 | 
			
		||||
                        console.log("linked_data_from_website received the following data:", lod)
 | 
			
		||||
                        console.log("linked_data_from_website received the following data:", lod),
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
                    return new Toggle(
 | 
			
		||||
| 
						 | 
				
			
			@ -1933,7 +1942,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                            collapsed: isClosed,
 | 
			
		||||
                        }),
 | 
			
		||||
                        undefined,
 | 
			
		||||
                        sourceUrl.map((url) => !!url)
 | 
			
		||||
                        sourceUrl.map((url) => !!url),
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
| 
						 | 
				
			
			@ -1953,7 +1962,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const text = argument[0]
 | 
			
		||||
                    const cssClasses = argument[1]
 | 
			
		||||
| 
						 | 
				
			
			@ -1975,7 +1984,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const translation = tagSource.map((tags) => {
 | 
			
		||||
                        const layer = state.theme.getMatchingLayer(tags)
 | 
			
		||||
| 
						 | 
				
			
			@ -2007,7 +2016,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): SvelteUIElement {
 | 
			
		||||
                    return new SvelteUIElement<any, any, any>(ClearCaches, {
 | 
			
		||||
                        msg: argument[0] ?? "Clear local caches",
 | 
			
		||||
| 
						 | 
				
			
			@ -2032,7 +2041,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    selectedElement: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): SvelteUIElement {
 | 
			
		||||
                    const [header, labelsStr] = argument
 | 
			
		||||
                    const labels = labelsStr.split(";").map((x) => x.trim())
 | 
			
		||||
| 
						 | 
				
			
			@ -2055,7 +2064,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tags: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    selectedElement: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): SvelteUIElement {
 | 
			
		||||
                    const t = Translations.t.preset_type
 | 
			
		||||
                    const question: QuestionableTagRenderingConfigJson = {
 | 
			
		||||
| 
						 | 
				
			
			@ -2095,7 +2104,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                    tagSource: UIEventSource<Record<string, string>>,
 | 
			
		||||
                    argument: string[],
 | 
			
		||||
                    feature: Feature,
 | 
			
		||||
                    layer: LayerConfig
 | 
			
		||||
                    layer: LayerConfig,
 | 
			
		||||
                ): BaseUIElement {
 | 
			
		||||
                    const text = argument[0]
 | 
			
		||||
                    return new SubtleButton(undefined, text).onClick(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -2126,7 +2135,7 @@ export default class SpecialVisualizations {
 | 
			
		|||
                "Invalid special visualisation found: funcName is undefined or doesn't match " +
 | 
			
		||||
                regex +
 | 
			
		||||
                invalid.map((sp) => sp.i).join(", ") +
 | 
			
		||||
                '. Did you perhaps type \n  funcName: "funcname" // type declaration uses COLON\ninstead of:\n  funcName = "funcName" // value definition uses EQUAL'
 | 
			
		||||
                ". Did you perhaps type \n  funcName: \"funcname\" // type declaration uses COLON\ninstead of:\n  funcName = \"funcName\" // value definition uses EQUAL"
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import MetaTagging from "./src/Logic/MetaTagging";
 | 
			
		|||
import { FixedUiElement } from "./src/UI/Base/FixedUiElement";
 | 
			
		||||
import { Utils } from "./src/Utils"
 | 
			
		||||
import Constants from "./src/Models/Constants"
 | 
			
		||||
import { AndroidPolyfill } from "./src/Logic/Web/AndroidPolyfill"
 | 
			
		||||
 | 
			
		||||
function webgl_support() {
 | 
			
		||||
    try {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,5 +19,5 @@
 | 
			
		|||
      "esModuleInterop": true
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "exclude": ["node_modules", "test", "scripts"]
 | 
			
		||||
  "exclude": ["node_modules", "test", "scripts","android","dist","dist-full"]
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,11 +21,21 @@ export default defineConfig({
 | 
			
		|||
  build: {
 | 
			
		||||
    rollupOptions: {
 | 
			
		||||
      input,
 | 
			
		||||
      external:[
 | 
			
		||||
        "android"
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  base: `${ASSET_URL}`,
 | 
			
		||||
  plugins ,
 | 
			
		||||
  server: {
 | 
			
		||||
    port: 1234,
 | 
			
		||||
    watch:{
 | 
			
		||||
      ignored: [
 | 
			
		||||
        "**/android/**",
 | 
			
		||||
        '**/.git/**',
 | 
			
		||||
        '**/dist/**'
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue