Merge develop

This commit is contained in:
Pieter Vander Vennet 2025-01-22 01:26:12 +01:00
parent c62705c1dd
commit c167094b65
12 changed files with 251 additions and 139 deletions

View file

@ -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()}"
}
],

View file

@ -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)

View file

@ -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]

View file

@ -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,
})
})
}
}

View file

@ -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") {

View file

@ -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>

View file

@ -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}

View file

@ -319,7 +319,7 @@
if (state?.osmConnection) {
onDestroy(
state.osmConnection?.userDetails?.addCallbackAndRun((ud) => {
numberOfCs = ud.csCount
numberOfCs = ud?.csCount
})
)
}

View file

@ -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"
)
}

View file

@ -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 {

View file

@ -19,5 +19,5 @@
"esModuleInterop": true
}
},
"exclude": ["node_modules", "test", "scripts"]
"exclude": ["node_modules", "test", "scripts","android","dist","dist-full"]
}

View file

@ -21,11 +21,21 @@ export default defineConfig({
build: {
rollupOptions: {
input,
external:[
"android"
]
},
},
base: `${ASSET_URL}`,
plugins ,
server: {
port: 1234,
watch:{
ignored: [
"**/android/**",
'**/.git/**',
'**/dist/**'
]
}
},
})