Fix: see #2212: actually save custom themes as visited
This commit is contained in:
parent
91f5c8f166
commit
9427083939
19 changed files with 129 additions and 75 deletions
|
@ -183,7 +183,7 @@ export default class GeoLocationHandler {
|
|||
}
|
||||
|
||||
private initUserLocationTrail() {
|
||||
const features = LocalStorageSource.GetParsed<Feature[]>("gps_location_history", [])
|
||||
const features = LocalStorageSource.getParsed<Feature[]>("gps_location_history", [])
|
||||
const now = new Date().getTime()
|
||||
features.data = features.data.filter((ff) => {
|
||||
if (ff.properties === undefined) {
|
||||
|
|
|
@ -31,7 +31,7 @@ export default class InitialMapPositioning {
|
|||
deflt: number,
|
||||
docs: string
|
||||
): UIEventSource<number> {
|
||||
const localStorage = LocalStorageSource.Get(key)
|
||||
const localStorage = LocalStorageSource.get(key)
|
||||
const previousValue = localStorage.data
|
||||
const src = UIEventSource.asFloat(
|
||||
QueryParameters.GetQueryParameter(key, "" + deflt, docs).syncWith(localStorage)
|
||||
|
|
|
@ -132,14 +132,14 @@ export default class DetermineLayout {
|
|||
let json: any
|
||||
|
||||
// layoutFromBase64 contains the name of the theme. This is partly to do tracking with goat counter
|
||||
const dedicatedHashFromLocalStorage = LocalStorageSource.Get(
|
||||
const dedicatedHashFromLocalStorage = LocalStorageSource.get(
|
||||
"user-layout-" + userLayoutParam.data?.replace(" ", "_")
|
||||
)
|
||||
if (dedicatedHashFromLocalStorage.data?.length < 10) {
|
||||
dedicatedHashFromLocalStorage.setData(undefined)
|
||||
}
|
||||
|
||||
const hashFromLocalStorage = LocalStorageSource.Get("last-loaded-user-layout")
|
||||
const hashFromLocalStorage = LocalStorageSource.get("last-loaded-user-layout")
|
||||
if (hash.length < 10) {
|
||||
hash = dedicatedHashFromLocalStorage.data ?? hashFromLocalStorage.data
|
||||
} else {
|
||||
|
|
|
@ -24,7 +24,7 @@ import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesSto
|
|||
*/
|
||||
export class Changes {
|
||||
public readonly pendingChanges: UIEventSource<ChangeDescription[]> =
|
||||
LocalStorageSource.GetParsed<ChangeDescription[]>("pending-changes", [])
|
||||
LocalStorageSource.getParsed<ChangeDescription[]>("pending-changes", [])
|
||||
public readonly allChanges = new UIEventSource<ChangeDescription[]>(undefined)
|
||||
public readonly state: {
|
||||
allElements?: IndexedFeatureSource
|
||||
|
|
|
@ -210,7 +210,7 @@ export class OsmConnection {
|
|||
console.log("Trying to log in...")
|
||||
this.updateAuthObject()
|
||||
|
||||
LocalStorageSource.Get("location_before_login").setData(
|
||||
LocalStorageSource.get("location_before_login").setData(
|
||||
Utils.runningFromConsole ? undefined : window.location.href
|
||||
)
|
||||
this.auth.xhr(
|
||||
|
@ -521,7 +521,7 @@ export class OsmConnection {
|
|||
this.auth.authenticate(function () {
|
||||
// Fully authed at this point
|
||||
console.log("Authentication successful!")
|
||||
const previousLocation = LocalStorageSource.Get("location_before_login")
|
||||
const previousLocation = LocalStorageSource.get("location_before_login")
|
||||
callback(previousLocation.data)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,7 +6,11 @@ import { Utils } from "../../Utils"
|
|||
|
||||
export class OsmPreferences {
|
||||
|
||||
private preferences: Record<string, UIEventSource<string>> = {}
|
||||
/**
|
||||
* A 'cache' of all the preference stores
|
||||
* @private
|
||||
*/
|
||||
private readonly preferences: Record<string, UIEventSource<string>> = {}
|
||||
|
||||
private localStorageInited: Set<string> = new Set()
|
||||
/**
|
||||
|
@ -15,6 +19,10 @@ export class OsmPreferences {
|
|||
*/
|
||||
private seenKeys: string[] = []
|
||||
|
||||
/**
|
||||
* Contains a dictionary which has all preferences
|
||||
* @private
|
||||
*/
|
||||
private readonly _allPreferences: UIEventSource<Record<string, string>> = new UIEventSource({})
|
||||
public readonly allPreferences: Store<Readonly<Record<string, string>>> = this._allPreferences
|
||||
private readonly _fakeUser: boolean
|
||||
|
@ -51,6 +59,7 @@ export class OsmPreferences {
|
|||
this.setPreferencesAll(key, value)
|
||||
}
|
||||
pref.addCallback(v => {
|
||||
console.log("Got an update:", key, "--->", v)
|
||||
this.uploadKvSplit(key, v)
|
||||
this.setPreferencesAll(key, v)
|
||||
})
|
||||
|
@ -101,11 +110,11 @@ export class OsmPreferences {
|
|||
key = key.replace(/[:/"' {}.%\\]/g, "")
|
||||
|
||||
|
||||
const localStorage = LocalStorageSource.Get(key)
|
||||
const localStorage = LocalStorageSource.get(key) // cached
|
||||
if (localStorage.data === "null" || localStorage.data === "undefined") {
|
||||
localStorage.set(undefined)
|
||||
}
|
||||
const pref: UIEventSource<string> = this.initPreference(key, localStorage.data ?? defaultValue)
|
||||
const pref: UIEventSource<string> = this.initPreference(key, localStorage.data ?? defaultValue) // cached
|
||||
if (this.localStorageInited.has(key)) {
|
||||
return pref
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ export class GeoLocationState {
|
|||
* @private
|
||||
*/
|
||||
private readonly _previousLocationGrant: UIEventSource<boolean> =
|
||||
LocalStorageSource.GetParsed<boolean>("geolocation-permissions", false)
|
||||
LocalStorageSource.getParsed<boolean>("geolocation-permissions", false)
|
||||
|
||||
/**
|
||||
* Used to detect a permission retraction
|
||||
|
|
|
@ -43,8 +43,8 @@ export class OptionallySyncedHistory<T> {
|
|||
"sync",
|
||||
)
|
||||
const synced = this.synced = UIEventSource.asObject<T[]>(osmconnection.getPreference(key + "-history"), [])
|
||||
const local = this.local = LocalStorageSource.GetParsed<T[]>(key + "-history", [])
|
||||
const thisSession = this.thisSession = new UIEventSource<T[]>([], "optionally-synced:"+key+"(session only)")
|
||||
const local = this.local = LocalStorageSource.getParsed<T[]>(key + "-history", [])
|
||||
const thisSession = this.thisSession = new UIEventSource<T[]>([], "optionally-synced:" + key + "(session only)")
|
||||
this.syncPreference.addCallback(syncmode => {
|
||||
if (syncmode === "sync") {
|
||||
let list = [...thisSession.data, ...synced.data].slice(0, maxHistory)
|
||||
|
@ -164,7 +164,7 @@ export default class UserRelatedState {
|
|||
"button" | "button_click_right" | "button_click" | "click" | "click_right"
|
||||
>("button_click_right")
|
||||
|
||||
public readonly showScale : UIEventSource<boolean>
|
||||
public readonly showScale: UIEventSource<boolean>
|
||||
|
||||
/**
|
||||
* Preferences as tags exposes many preferences and state properties as record.
|
||||
|
@ -202,8 +202,8 @@ export default class UserRelatedState {
|
|||
this.a11y = this.osmConnection.getPreference("a11y")
|
||||
|
||||
this.mangroveIdentity = new MangroveIdentity(
|
||||
this.osmConnection.getPreference("identity", undefined,"mangrove"),
|
||||
this.osmConnection.getPreference("identity-creation-date", undefined,"mangrove"),
|
||||
this.osmConnection.getPreference("identity", undefined, "mangrove"),
|
||||
this.osmConnection.getPreference("identity-creation-date", undefined, "mangrove"),
|
||||
)
|
||||
this.preferredBackgroundLayer = this.osmConnection.getPreference("preferred-background-layer")
|
||||
|
||||
|
@ -211,7 +211,7 @@ export default class UserRelatedState {
|
|||
"preferences-add-new-mode",
|
||||
"button_click_right",
|
||||
)
|
||||
this.showScale = UIEventSource.asBoolean(this.osmConnection.GetPreference("preference-show-scale","false"))
|
||||
this.showScale = UIEventSource.asBoolean(this.osmConnection.GetPreference("preference-show-scale", "false"))
|
||||
|
||||
this.imageLicense = this.osmConnection.getPreference("pictures-license", "CC0")
|
||||
this.installedUserThemes = UserRelatedState.initInstalledUserThemes(osmConnection)
|
||||
|
@ -272,7 +272,19 @@ export default class UserRelatedState {
|
|||
}
|
||||
}
|
||||
|
||||
public getUnofficialTheme(id: string): (MinimalLayoutInformation & { definition }) | undefined {
|
||||
/**
|
||||
* Adds a newly visited unofficial theme (or update the info).
|
||||
*
|
||||
* @param themeInfo note that themeInfo.id should be the URL where it was found
|
||||
*/
|
||||
public addUnofficialTheme(themeInfo: MinimalLayoutInformation) {
|
||||
const pref = this.osmConnection.getPreference("unofficial-theme-" + themeInfo.id)
|
||||
this.osmConnection.isLoggedIn.when(
|
||||
() => pref.set(JSON.stringify(themeInfo))
|
||||
)
|
||||
}
|
||||
|
||||
public getUnofficialTheme(id: string): MinimalLayoutInformation | undefined {
|
||||
const pref = this.osmConnection.getPreference("unofficial-theme-" + id)
|
||||
const str = pref.data
|
||||
|
||||
|
@ -282,7 +294,7 @@ export default class UserRelatedState {
|
|||
}
|
||||
|
||||
try {
|
||||
return <MinimalLayoutInformation & { definition: string }>JSON.parse(str)
|
||||
return JSON.parse(str)
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
"Removing theme " +
|
||||
|
@ -516,10 +528,10 @@ export default class UserRelatedState {
|
|||
// Language is managed separately
|
||||
continue
|
||||
}
|
||||
if(tags[key] === null){
|
||||
if (tags[key] === null) {
|
||||
continue
|
||||
}
|
||||
let pref = this.osmConnection.GetPreference(key, undefined, {prefix: ""})
|
||||
let pref = this.osmConnection.GetPreference(key, undefined, { prefix: "" })
|
||||
|
||||
pref.set(tags[key])
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ export class Stores {
|
|||
}
|
||||
|
||||
public static FromPromiseWithErr<T>(
|
||||
promise: Promise<T>
|
||||
promise: Promise<T>,
|
||||
): Store<{ success: T } | { error: any }> {
|
||||
return UIEventSource.FromPromiseWithErr(promise)
|
||||
}
|
||||
|
@ -133,13 +133,13 @@ export abstract class Store<T> implements Readable<T> {
|
|||
abstract map<J>(
|
||||
f: (t: T) => J,
|
||||
extraStoresToWatch: Store<any>[],
|
||||
callbackDestroyFunction: (f: () => void) => void
|
||||
callbackDestroyFunction: (f: () => void) => void,
|
||||
): Store<J>
|
||||
|
||||
public mapD<J>(
|
||||
f: (t: Exclude<T, undefined | null>) => J,
|
||||
extraStoresToWatch?: Store<any>[],
|
||||
callbackDestroyFunction?: (f: () => void) => void
|
||||
callbackDestroyFunction?: (f: () => void) => void,
|
||||
): Store<J> {
|
||||
return this.map((t) => {
|
||||
if (t === undefined) {
|
||||
|
@ -176,7 +176,7 @@ export abstract class Store<T> implements Readable<T> {
|
|||
abstract addCallbackAndRun(callback: (data: T) => void): () => void
|
||||
|
||||
public withEqualityStabilized(
|
||||
comparator: (t: T | undefined, t1: T | undefined) => boolean
|
||||
comparator: (t: T | undefined, t1: T | undefined) => boolean,
|
||||
): Store<T> {
|
||||
let oldValue = undefined
|
||||
return this.map((v) => {
|
||||
|
@ -342,6 +342,16 @@ export abstract class Store<T> implements Readable<T> {
|
|||
}
|
||||
|
||||
public abstract destroy()
|
||||
|
||||
when(callback: () => void, condition?: (v:T) => boolean) {
|
||||
condition ??= v => v === true
|
||||
this.addCallbackAndRunD(v => {
|
||||
if ( condition(v)) {
|
||||
callback()
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class ImmutableStore<T> extends Store<T> {
|
||||
|
@ -384,7 +394,7 @@ export class ImmutableStore<T> extends Store<T> {
|
|||
map<J>(
|
||||
f: (t: T) => J,
|
||||
extraStores: Store<any>[] = undefined,
|
||||
ondestroyCallback?: (f: () => void) => void
|
||||
ondestroyCallback?: (f: () => void) => void,
|
||||
): ImmutableStore<J> {
|
||||
if (extraStores?.length > 0) {
|
||||
return new MappedStore(this, f, extraStores, undefined, f(this.data), ondestroyCallback)
|
||||
|
@ -454,7 +464,7 @@ class ListenerTracker<T> {
|
|||
let endTime = new Date().getTime() / 1000
|
||||
if (endTime - startTime > 500) {
|
||||
console.trace(
|
||||
"Warning: a ping took more then 500ms; this is probably a performance issue"
|
||||
"Warning: a ping took more then 500ms; this is probably a performance issue",
|
||||
)
|
||||
}
|
||||
if (toDelete !== undefined) {
|
||||
|
@ -496,7 +506,7 @@ class MappedStore<TIn, T> extends Store<T> {
|
|||
extraStores: Store<any>[],
|
||||
upstreamListenerHandler: ListenerTracker<TIn> | undefined,
|
||||
initialState: T,
|
||||
onDestroy?: (f: () => void) => void
|
||||
onDestroy?: (f: () => void) => void,
|
||||
) {
|
||||
super()
|
||||
this._upstream = upstream
|
||||
|
@ -536,7 +546,7 @@ class MappedStore<TIn, T> extends Store<T> {
|
|||
map<J>(
|
||||
f: (t: T) => J,
|
||||
extraStores: Store<any>[] = undefined,
|
||||
ondestroyCallback?: (f: () => void) => void
|
||||
ondestroyCallback?: (f: () => void) => void,
|
||||
): Store<J> {
|
||||
let stores: Store<any>[] = undefined
|
||||
if (extraStores?.length > 0 || this._extraStores?.length > 0) {
|
||||
|
@ -558,7 +568,7 @@ class MappedStore<TIn, T> extends Store<T> {
|
|||
stores,
|
||||
this._callbacks,
|
||||
f(this.data),
|
||||
ondestroyCallback
|
||||
ondestroyCallback,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -614,7 +624,7 @@ class MappedStore<TIn, T> extends Store<T> {
|
|||
|
||||
this._unregisterFromUpstream = this._upstream.addCallback((_) => self.update())
|
||||
this._unregisterFromExtraStores = this._extraStores?.map((store) =>
|
||||
store?.addCallback((_) => self.update())
|
||||
store?.addCallback((_) => self.update()),
|
||||
)
|
||||
this._callbacksAreRegistered = true
|
||||
}
|
||||
|
@ -651,7 +661,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
|
||||
public static flatten<X>(
|
||||
source: Store<Store<X>>,
|
||||
possibleSources?: Store<object>[]
|
||||
possibleSources?: Store<object>[],
|
||||
): UIEventSource<X> {
|
||||
const sink = new UIEventSource<X>(source.data?.data)
|
||||
|
||||
|
@ -680,7 +690,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
*/
|
||||
public static FromPromise<T>(
|
||||
promise: Promise<T>,
|
||||
onError: (e) => void = undefined
|
||||
onError: (e) => void = undefined,
|
||||
): UIEventSource<T> {
|
||||
const src = new UIEventSource<T>(undefined)
|
||||
promise?.then((d) => src.setData(d))
|
||||
|
@ -701,7 +711,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
* @constructor
|
||||
*/
|
||||
public static FromPromiseWithErr<T>(
|
||||
promise: Promise<T>
|
||||
promise: Promise<T>,
|
||||
): UIEventSource<{ success: T } | { error: any } | undefined> {
|
||||
const src = new UIEventSource<{ success: T } | { error: any }>(undefined)
|
||||
promise
|
||||
|
@ -733,7 +743,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
return undefined
|
||||
}
|
||||
return "" + fl
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -764,7 +774,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
return undefined
|
||||
}
|
||||
return "" + fl
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -772,7 +782,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
return stringUIEventSource.sync(
|
||||
(str) => str === "true",
|
||||
[],
|
||||
(b) => "" + b
|
||||
(b) => "" + b,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -790,7 +800,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
}
|
||||
},
|
||||
[],
|
||||
(b) => JSON.stringify(b) ?? ""
|
||||
(b) => JSON.stringify(b) ?? "",
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -880,7 +890,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
public map<J>(
|
||||
f: (t: T) => J,
|
||||
extraSources: Store<any>[] = [],
|
||||
onDestroy?: (f: () => void) => void
|
||||
onDestroy?: (f: () => void) => void,
|
||||
): Store<J> {
|
||||
return new MappedStore(this, f, extraSources, this._callbacks, f(this.data), onDestroy)
|
||||
}
|
||||
|
@ -892,7 +902,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
public mapD<J>(
|
||||
f: (t: Exclude<T, undefined | null>) => J,
|
||||
extraSources: Store<any>[] = [],
|
||||
callbackDestroyFunction?: (f: () => void) => void
|
||||
callbackDestroyFunction?: (f: () => void) => void,
|
||||
): Store<J | undefined> {
|
||||
return new MappedStore(
|
||||
this,
|
||||
|
@ -910,7 +920,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
this.data === undefined || this.data === null
|
||||
? <undefined | null>this.data
|
||||
: f(<any>this.data),
|
||||
callbackDestroyFunction
|
||||
callbackDestroyFunction,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -930,7 +940,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
|||
f: (t: T) => J,
|
||||
extraSources: Store<any>[],
|
||||
g: (j: J, t: T) => T,
|
||||
allowUnregister = false
|
||||
allowUnregister = false,
|
||||
): UIEventSource<J> {
|
||||
const self = this
|
||||
|
||||
|
|
|
@ -4,8 +4,11 @@ import { UIEventSource } from "../UIEventSource"
|
|||
* UIEventsource-wrapper around localStorage
|
||||
*/
|
||||
export class LocalStorageSource {
|
||||
static GetParsed<T>(key: string, defaultValue: T): UIEventSource<T> {
|
||||
return LocalStorageSource.Get(key).sync(
|
||||
|
||||
private static readonly _cache: Record<string, UIEventSource<string>> = {}
|
||||
|
||||
static getParsed<T>(key: string, defaultValue: T): UIEventSource<T> {
|
||||
return LocalStorageSource.get(key).sync(
|
||||
(str) => {
|
||||
if (str === undefined) {
|
||||
return defaultValue
|
||||
|
@ -17,34 +20,40 @@ export class LocalStorageSource {
|
|||
}
|
||||
},
|
||||
[],
|
||||
(value) => JSON.stringify(value)
|
||||
(value) => JSON.stringify(value),
|
||||
)
|
||||
}
|
||||
|
||||
static Get(key: string, defaultValue: string = undefined): UIEventSource<string> {
|
||||
static get(key: string, defaultValue: string = undefined): UIEventSource<string> {
|
||||
const cached = LocalStorageSource._cache[key]
|
||||
if (cached) {
|
||||
return cached
|
||||
}
|
||||
let saved = defaultValue
|
||||
try {
|
||||
let saved = localStorage.getItem(key)
|
||||
saved = localStorage.getItem(key)
|
||||
if (saved === "undefined") {
|
||||
saved = undefined
|
||||
}
|
||||
const source = new UIEventSource<string>(saved ?? defaultValue, "localstorage:" + key)
|
||||
|
||||
source.addCallback((data) => {
|
||||
if(data === undefined || data === "" || data === null){
|
||||
localStorage.removeItem(key)
|
||||
return
|
||||
}
|
||||
try {
|
||||
localStorage.setItem(key, data)
|
||||
} catch (e) {
|
||||
// Probably exceeded the quota with this item!
|
||||
// Lets nuke everything
|
||||
localStorage.clear()
|
||||
}
|
||||
})
|
||||
return source
|
||||
} catch (e) {
|
||||
return new UIEventSource<string>(defaultValue)
|
||||
console.error("Could not get value", key, "from local storage")
|
||||
}
|
||||
const source = new UIEventSource<string>(saved ?? defaultValue, "localstorage:" + key)
|
||||
|
||||
source.addCallback((data) => {
|
||||
if (data === undefined || data === "" || data === null) {
|
||||
localStorage.removeItem(key)
|
||||
return
|
||||
}
|
||||
try {
|
||||
localStorage.setItem(key, data)
|
||||
} catch (e) {
|
||||
// Probably exceeded the quota with this item!
|
||||
// Let's nuke everything
|
||||
localStorage.clear()
|
||||
}
|
||||
})
|
||||
LocalStorageSource._cache[key] = source
|
||||
return source
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ export default class FilteredLayer {
|
|||
) {
|
||||
let isDisplayed: UIEventSource<boolean>
|
||||
if (layer.syncSelection === "local") {
|
||||
isDisplayed = LocalStorageSource.GetParsed(
|
||||
isDisplayed = LocalStorageSource.getParsed(
|
||||
context + "-layer-" + layer.id + "-enabled",
|
||||
layer.shownByDefault,
|
||||
)
|
||||
|
|
|
@ -57,7 +57,7 @@ export class MenuState {
|
|||
})
|
||||
}
|
||||
|
||||
const visitedBefore = LocalStorageSource.GetParsed<boolean>(
|
||||
const visitedBefore = LocalStorageSource.getParsed<boolean>(
|
||||
themeid + "thememenuisopened",
|
||||
false
|
||||
)
|
||||
|
|
|
@ -370,7 +370,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
this.changes,
|
||||
this.geolocation.geolocationState.currentGPSLocation,
|
||||
this.indexedFeatures,
|
||||
this.reportError
|
||||
this.reportError,
|
||||
)
|
||||
this.favourites = new FavouritesFeatureSource(this)
|
||||
const longAgo = new Date()
|
||||
|
@ -532,7 +532,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
* Selects the feature that is 'i' closest to the map center
|
||||
*/
|
||||
private selectClosestAtCenter(i: number = 0) {
|
||||
console.log("Selecting closest",i)
|
||||
console.log("Selecting closest", i)
|
||||
if (this.userRelatedState.a11y.data !== "never") {
|
||||
this.visualFeedback.setData(true)
|
||||
}
|
||||
|
@ -908,6 +908,21 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
* Setup various services for which no reference are needed
|
||||
*/
|
||||
private initActors() {
|
||||
|
||||
if (!this.layout.official) {
|
||||
// Add custom themes to the "visited custom themes"
|
||||
const th = this.layout
|
||||
this.userRelatedState.addUnofficialTheme({
|
||||
id: th.id,
|
||||
icon: th.icon,
|
||||
title: th.title.translations,
|
||||
shortDescription: th.shortDescription.translations ,
|
||||
layers: th.layers.filter(l => l.isNormal()).map(l => l.id)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
this.selectedElement.addCallback((selected) => {
|
||||
if (selected === undefined) {
|
||||
this.focusOnMap()
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
|
||||
const customThemes: Store<MinimalLayoutInformation[]> = Stores.ListStabilized<string>(state.installedUserThemes)
|
||||
.mapD(stableIds => Utils.NoNullInplace(stableIds.map(id => state.getUnofficialTheme(id))))
|
||||
|
||||
function filtered(themes: Store<MinimalLayoutInformation[]>): Store<MinimalLayoutInformation[]> {
|
||||
return searchStable.map(search => {
|
||||
if (!search) {
|
||||
|
|
|
@ -42,8 +42,8 @@
|
|||
})
|
||||
}
|
||||
|
||||
let customWidth = LocalStorageSource.Get("custom-png-width", "20")
|
||||
let customHeight = LocalStorageSource.Get("custom-png-height", "20")
|
||||
let customWidth = LocalStorageSource.get("custom-png-width", "20")
|
||||
let customHeight = LocalStorageSource.get("custom-png-height", "20")
|
||||
|
||||
async function offerCustomPng(): Promise<Blob> {
|
||||
console.log(
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
export let coordinate: UIEventSource<{ lon: number; lat: number }>
|
||||
export let state: SpecialVisualizationState
|
||||
|
||||
let comment: UIEventSource<string> = LocalStorageSource.Get("note-text")
|
||||
let comment: UIEventSource<string> = LocalStorageSource.get("note-text")
|
||||
let created = false
|
||||
|
||||
let notelayer: FilteredLayer = state.layerState.filteredLayers.get("note")
|
||||
|
|
|
@ -37,7 +37,7 @@ export abstract class EditJsonState<T> {
|
|||
public readonly osmConnection: OsmConnection
|
||||
|
||||
public readonly showIntro: UIEventSource<"no" | "intro" | "tagrenderings"> = <any>(
|
||||
LocalStorageSource.Get("studio-show-intro", "intro")
|
||||
LocalStorageSource.get("studio-show-intro", "intro")
|
||||
)
|
||||
|
||||
public readonly expertMode: UIEventSource<boolean>
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
const store = state.getStoreFor(path)
|
||||
let value = store.data
|
||||
let hasSeenIntro = UIEventSource.asBoolean(
|
||||
LocalStorageSource.Get("studio-seen-tagrendering-tutorial", "false")
|
||||
LocalStorageSource.get("studio-seen-tagrendering-tutorial", "false")
|
||||
)
|
||||
onMount(() => {
|
||||
if (!hasSeenIntro.data) {
|
||||
|
|
|
@ -74,7 +74,7 @@ export default class Locale {
|
|||
if (typeof navigator !== "undefined") {
|
||||
browserLanguage = Locale.getBestSupportedLanguage()
|
||||
}
|
||||
source = LocalStorageSource.Get("language", browserLanguage)
|
||||
source = LocalStorageSource.get("language", browserLanguage)
|
||||
}
|
||||
|
||||
if (!Utils.runningFromConsole && typeof document !== undefined) {
|
||||
|
|
Loading…
Reference in a new issue