forked from MapComplete/MapComplete
Fix: change inner workings of how history is kept, should improve performance
This commit is contained in:
parent
27ae31afe7
commit
7c57047d30
3 changed files with 102 additions and 91 deletions
|
@ -21,10 +21,49 @@ import Showdown from "showdown"
|
|||
import { LocalStorageSource } from "../Web/LocalStorageSource"
|
||||
import { GeocodeResult } from "../Search/GeocodingProvider"
|
||||
|
||||
export class OptionallySyncedHistory<T> {
|
||||
class RoundRobinStore<T> {
|
||||
private readonly _store: UIEventSource<T[]>
|
||||
private readonly _index: UIEventSource<number>
|
||||
private readonly _value: UIEventSource<T[]>
|
||||
public readonly value: Store<T[]>
|
||||
|
||||
constructor(store: UIEventSource<T[]>, index: UIEventSource<number>) {
|
||||
this._store = store
|
||||
this._index = index
|
||||
this._value = new UIEventSource([])
|
||||
this.value = this._value
|
||||
this._store.addCallbackD(() => this.set())
|
||||
this.set()
|
||||
}
|
||||
|
||||
private set() {
|
||||
const v = this._store.data
|
||||
const i = this._index.data
|
||||
const newList = Utils.NoNull(v.slice(i + 1, v.length).concat(v.slice(0, i + 1)))
|
||||
this._value.set(newList)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a value to the underlying store
|
||||
* @param t
|
||||
*/
|
||||
public add(t: T) {
|
||||
const i = this._index.data
|
||||
this._index.set((i + 1) % this._store.data.length)
|
||||
this._store.data[i] = t
|
||||
console.trace(">>> Setting", i, this._store.data, t, "new index:", this._index.data)
|
||||
this._store.ping()
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export class OptionallySyncedHistory<T extends object | string> {
|
||||
public readonly syncPreference: UIEventSource<"sync" | "local" | "no">
|
||||
public readonly value: Store<T[]>
|
||||
private readonly synced: UIEventSource<T[]>
|
||||
private readonly syncedBackingStore: UIEventSource<T[]>
|
||||
private readonly syncedOrdered: RoundRobinStore<T>
|
||||
private readonly local: UIEventSource<T[]>
|
||||
private readonly thisSession: UIEventSource<T[]>
|
||||
private readonly _maxHistory: number
|
||||
|
@ -41,10 +80,14 @@ export class OptionallySyncedHistory<T> {
|
|||
this._maxHistory = maxHistory
|
||||
this._isSame = isSame
|
||||
this.syncPreference = osmconnection.getPreference("preference-" + key + "-history", "sync")
|
||||
const synced = (this.synced = UIEventSource.asObject<T[]>(
|
||||
osmconnection.getPreference(key + "-history"),
|
||||
[]
|
||||
))
|
||||
|
||||
this.syncedBackingStore = Stores.fromArray(
|
||||
Utils.TimesT(maxHistory, (i) =>
|
||||
UIEventSource.asObject<T>(osmconnection.getPreference(key + "-history-" + i), undefined)
|
||||
))
|
||||
this.syncedOrdered = new RoundRobinStore<T>(this.syncedBackingStore,
|
||||
UIEventSource.asInt(osmconnection.getPreference(key + "-history-round-robin", "0"))
|
||||
)
|
||||
const local = (this.local = LocalStorageSource.getParsed<T[]>(key + "-history", []))
|
||||
const thisSession = (this.thisSession = new UIEventSource<T[]>(
|
||||
[],
|
||||
|
@ -52,7 +95,7 @@ export class OptionallySyncedHistory<T> {
|
|||
))
|
||||
this.syncPreference.addCallback((syncmode) => {
|
||||
if (syncmode === "sync") {
|
||||
const list = [...thisSession.data, ...synced.data].slice(0, maxHistory)
|
||||
const list = [...thisSession.data, ...this.syncedOrdered.value.data].slice(0, maxHistory)
|
||||
if (this._isSame) {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
for (let j = i + 1; j < list.length; j++) {
|
||||
|
@ -62,12 +105,12 @@ export class OptionallySyncedHistory<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
synced.set(list)
|
||||
this.syncedBackingStore.set(list)
|
||||
} else if (syncmode === "local") {
|
||||
local.set(synced.data?.slice(0, maxHistory))
|
||||
synced.set([])
|
||||
local.set(this.syncedOrdered.value.data?.slice(0, maxHistory))
|
||||
this.syncedBackingStore.set([])
|
||||
} else {
|
||||
synced.set([])
|
||||
this.syncedBackingStore.set([])
|
||||
local.set([])
|
||||
}
|
||||
})
|
||||
|
@ -75,10 +118,10 @@ export class OptionallySyncedHistory<T> {
|
|||
this.value = this.syncPreference.bind((syncPref) => this.getAppropriateStore(syncPref))
|
||||
}
|
||||
|
||||
private getAppropriateStore(syncPref?: string) {
|
||||
private getAppropriateStore(syncPref?: string): Store<T[]> {
|
||||
syncPref ??= this.syncPreference.data
|
||||
if (syncPref === "sync") {
|
||||
return this.synced
|
||||
return this.syncedOrdered.value
|
||||
}
|
||||
if (syncPref === "local") {
|
||||
return this.local
|
||||
|
@ -87,12 +130,29 @@ export class OptionallySyncedHistory<T> {
|
|||
}
|
||||
|
||||
public add(t: T) {
|
||||
const store = this.getAppropriateStore()
|
||||
let oldList = store.data ?? []
|
||||
if (this._isSame) {
|
||||
oldList = oldList.filter((x) => !this._isSame(t, x))
|
||||
const alreadyNoted = this.getAppropriateStore().data.some(item => this._isSame(item, t))
|
||||
if (alreadyNoted) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (this.syncPreference.data === "local") {
|
||||
const ls = this.local.data
|
||||
ls.unshift(t)
|
||||
if (ls.length >= this._maxHistory) {
|
||||
ls.splice(this._maxHistory, 1)
|
||||
}
|
||||
this.local.ping()
|
||||
} else if (this.syncPreference.data === "sync") {
|
||||
this.osmconnection.isLoggedIn.addCallbackAndRun(loggedIn => {
|
||||
// Wait until we are logged in and the settings are downloaded before adding the preference
|
||||
if (loggedIn) {
|
||||
this.syncedOrdered.add(t)
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
store.set([t, ...oldList].slice(0, this._maxHistory))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,7 +173,8 @@ export class OptionallySyncedHistory<T> {
|
|||
}
|
||||
|
||||
clear() {
|
||||
this.getAppropriateStore().set([])
|
||||
this.syncedBackingStore.set([])
|
||||
this.local.set([])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,6 +290,7 @@ export default class UserRelatedState {
|
|||
10,
|
||||
(a, b) => a === b
|
||||
)
|
||||
this.recentlyVisitedThemes.value.addCallbackAndRunD(th => console.log(">>> themes", th))
|
||||
this.recentlyVisitedSearch = new OptionallySyncedHistory<GeocodeResult>(
|
||||
"places",
|
||||
this.osmConnection,
|
||||
|
@ -298,10 +360,10 @@ export default class UserRelatedState {
|
|||
try {
|
||||
return JSON.parse(str)
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
e.warn(
|
||||
"Removing theme " +
|
||||
id +
|
||||
" as it could not be parsed from the preferences; the content is:",
|
||||
id +
|
||||
" as it could not be parsed from the preferences; the content is:",
|
||||
str
|
||||
)
|
||||
pref.setData(null)
|
||||
|
@ -331,7 +393,7 @@ export default class UserRelatedState {
|
|||
icon: layout.icon,
|
||||
title: layout.title.translations,
|
||||
shortDescription: layout.shortDescription.translations,
|
||||
definition: layout["definition"],
|
||||
definition: layout["definition"]
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -386,13 +448,13 @@ export default class UserRelatedState {
|
|||
id: "home",
|
||||
"user:home": "yes",
|
||||
_lon: homeLonLat[0],
|
||||
_lat: homeLonLat[1],
|
||||
_lat: homeLonLat[1]
|
||||
},
|
||||
geometry: {
|
||||
type: "Point",
|
||||
coordinates: homeLonLat,
|
||||
},
|
||||
},
|
||||
coordinates: homeLonLat
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
return new StaticFeatureSource(feature)
|
||||
|
@ -414,7 +476,7 @@ export default class UserRelatedState {
|
|||
_applicationOpened: new Date().toISOString(),
|
||||
_supports_sharing:
|
||||
typeof window === "undefined" ? "no" : window.navigator.share ? "yes" : "no",
|
||||
_iframe: Utils.isIframe ? "yes" : "no",
|
||||
_iframe: Utils.isIframe ? "yes" : "no"
|
||||
})
|
||||
if (!Utils.runningFromConsole) {
|
||||
amendedPrefs.data["_host"] = window.location.host
|
||||
|
@ -462,18 +524,18 @@ export default class UserRelatedState {
|
|||
const zenLinks: { link: string; id: string }[] = Utils.NoNull([
|
||||
hasMissingTheme
|
||||
? {
|
||||
id: "theme:" + layout.id,
|
||||
link: LinkToWeblate.hrefToWeblateZen(
|
||||
language,
|
||||
"themes",
|
||||
layout.id
|
||||
),
|
||||
}
|
||||
id: "theme:" + layout.id,
|
||||
link: LinkToWeblate.hrefToWeblateZen(
|
||||
language,
|
||||
"themes",
|
||||
layout.id
|
||||
)
|
||||
}
|
||||
: undefined,
|
||||
...missingLayers.map((id) => ({
|
||||
id: "layer:" + id,
|
||||
link: LinkToWeblate.hrefToWeblateZen(language, "layers", id),
|
||||
})),
|
||||
link: LinkToWeblate.hrefToWeblateZen(language, "layers", id)
|
||||
}))
|
||||
])
|
||||
const untranslated_count = untranslated.length
|
||||
amendedPrefs.data["_translation_total"] = "" + total
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue