From c167094b6536f5ec9be700d73c0987489f742b11 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet <pietervdvn@posteo.net> Date: Wed, 22 Jan 2025 01:26:12 +0100 Subject: [PATCH] Merge develop --- assets/layers/usersettings/usersettings.json | 42 +++- src/Logic/State/GeoLocationState.ts | 21 +- src/Logic/State/UserRelatedState.ts | 4 + src/Logic/Web/AndroidPolyfill.ts | 41 ++- src/Models/ThemeConfig/TagRenderingConfig.ts | 3 + src/UI/Base/Searchbar.svelte | 22 +- .../BigComponents/GeolocationIndicator.svelte | 5 +- .../TagRendering/TagRenderingQuestion.svelte | 2 +- src/UI/SpecialVisualizations.ts | 237 +++++++++--------- src/index_theme.ts.template | 1 + tsconfig.json | 2 +- vite.config.js | 10 + 12 files changed, 251 insertions(+), 139 deletions(-) diff --git a/assets/layers/usersettings/usersettings.json b/assets/layers/usersettings/usersettings.json index ed8d50057..fd6ef4d79 100644 --- a/assets/layers/usersettings/usersettings.json +++ b/assets/layers/usersettings/usersettings.json @@ -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()}" } ], diff --git a/src/Logic/State/GeoLocationState.ts b/src/Logic/State/GeoLocationState.ts index 4806762b0..34618905c 100644 --- a/src/Logic/State/GeoLocationState.ts +++ b/src/Logic/State/GeoLocationState.ts @@ -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.startWatching() + 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) diff --git a/src/Logic/State/UserRelatedState.ts b/src/Logic/State/UserRelatedState.ts index 27f03e99e..0b109e5ac 100644 --- a/src/Logic/State/UserRelatedState.ts +++ b/src/Logic/State/UserRelatedState.ts @@ -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] diff --git a/src/Logic/Web/AndroidPolyfill.ts b/src/Logic/Web/AndroidPolyfill.ts index 8b85ef411..e9944acd5 100644 --- a/src/Logic/Web/AndroidPolyfill.ts +++ b/src/Logic/Web/AndroidPolyfill.ts @@ -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, + }) + }) + } } diff --git a/src/Models/ThemeConfig/TagRenderingConfig.ts b/src/Models/ThemeConfig/TagRenderingConfig.ts index 7a763e346..84acfac09 100644 --- a/src/Models/ThemeConfig/TagRenderingConfig.ts +++ b/src/Models/ThemeConfig/TagRenderingConfig.ts @@ -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") { diff --git a/src/UI/Base/Searchbar.svelte b/src/UI/Base/Searchbar.svelte index 35d2b4879..6f4d401ea 100644 --- a/src/UI/Base/Searchbar.svelte +++ b/src/UI/Base/Searchbar.svelte @@ -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,18 +64,20 @@ use:set_placeholder={placeholder} use:ariaLabel={placeholder} /> - - {#if $value.length > 0} - <Backspace - on:click={(e) => { + {#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) => { value.set("") e.preventDefault() }} - color="var(--button-background)" - class="mr-3 h-6 w-6 cursor-pointer" - /> - {:else} - <div class="mr-3 w-6" /> + color="var(--button-background)" + class="mr-3 h-6 w-6 cursor-pointer" + /> + {:else} + <div class="mr-3 w-6" /> + {/if} {/if} </label> </form> diff --git a/src/UI/BigComponents/GeolocationIndicator.svelte b/src/UI/BigComponents/GeolocationIndicator.svelte index ef66911a7..69cacf5f7 100644 --- a/src/UI/BigComponents/GeolocationIndicator.svelte +++ b/src/UI/BigComponents/GeolocationIndicator.svelte @@ -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} diff --git a/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte b/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte index ea20fb8a7..fe72bdb85 100644 --- a/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte +++ b/src/UI/Popup/TagRendering/TagRenderingQuestion.svelte @@ -319,7 +319,7 @@ if (state?.osmConnection) { onDestroy( state.osmConnection?.userDetails?.addCallbackAndRun((ud) => { - numberOfCs = ud.csCount + numberOfCs = ud?.csCount }) ) } diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index 8844bedbf..8dbb6aab8 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -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, ) } } @@ -347,15 +347,15 @@ export default class SpecialVisualizations { viz.docs, viz.args.length > 0 ? MarkdownUtils.table( - ["name", "default", "description"], - viz.args.map((arg) => { - let defaultArg = arg.defaultValue ?? "_undefined_" - if (defaultArg == "") { - defaultArg = "_empty string_" - } - return [arg.name, defaultArg, arg.doc] - }) - ) + ["name", "default", "description"], + viz.args.map((arg) => { + let defaultArg = arg.defaultValue ?? "_undefined_" + if (defaultArg == "") { + defaultArg = "_empty string_" + } + return [arg.name, defaultArg, arg.doc] + }), + ) : undefined, "#### Example usage of " + viz.funcName, "<code>" + example + "</code>", @@ -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( @@ -1582,12 +1582,12 @@ export default class SpecialVisualizations { } catch (e) { return new FixedUiElement( "Could not parse this tag: " + - JSON.stringify(value) + - " due to " + - e + JSON.stringify(value) + + " due to " + + 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" ) } diff --git a/src/index_theme.ts.template b/src/index_theme.ts.template index 3c947bdd2..fbb362dca 100644 --- a/src/index_theme.ts.template +++ b/src/index_theme.ts.template @@ -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 { diff --git a/tsconfig.json b/tsconfig.json index e491c3572..80274e478 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,5 +19,5 @@ "esModuleInterop": true } }, - "exclude": ["node_modules", "test", "scripts"] + "exclude": ["node_modules", "test", "scripts","android","dist","dist-full"] } diff --git a/vite.config.js b/vite.config.js index f85973a7e..986daad5b 100644 --- a/vite.config.js +++ b/vite.config.js @@ -21,11 +21,21 @@ export default defineConfig({ build: { rollupOptions: { input, + external:[ + "android" + ] }, }, base: `${ASSET_URL}`, plugins , server: { port: 1234, + watch:{ + ignored: [ + "**/android/**", + '**/.git/**', + '**/dist/**' + ] + } }, })