forked from MapComplete/MapComplete
Add caching into local storage for a faster map experience
This commit is contained in:
parent
3a2d654ac3
commit
f33fe081d0
12 changed files with 128 additions and 41 deletions
48
Logic/FeatureSource/FeaturePipeline.ts
Normal file
48
Logic/FeatureSource/FeaturePipeline.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import FilteringFeatureSource from "../FeatureSource/FilteringFeatureSource";
|
||||
import State from "../../State";
|
||||
import FeatureSourceMerger from "../FeatureSource/FeatureSourceMerger";
|
||||
import RememberingSource from "../FeatureSource/RememberingSource";
|
||||
import WayHandlingApplyingFeatureSource from "../FeatureSource/WayHandlingApplyingFeatureSource";
|
||||
import NoOverlapSource from "../FeatureSource/NoOverlapSource";
|
||||
import FeatureDuplicatorPerLayer from "../FeatureSource/FeatureDuplicatorPerLayer";
|
||||
import FeatureSource from "../FeatureSource/FeatureSource";
|
||||
import {UIEventSource} from "../UIEventSource";
|
||||
import LocalStorageSaver from "./LocalStorageSaver";
|
||||
import LayerConfig from "../../Customizations/JSON/LayerConfig";
|
||||
import LocalStorageSource from "./LocalStorageSource";
|
||||
|
||||
export default class FeaturePipeline implements FeatureSource {
|
||||
|
||||
public features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
||||
|
||||
constructor(flayers: { isDisplayed: UIEventSource<boolean>, layerDef: LayerConfig }[], updater: FeatureSource) {
|
||||
|
||||
const overpassSource = new WayHandlingApplyingFeatureSource(flayers,
|
||||
new NoOverlapSource(flayers, new FeatureDuplicatorPerLayer(flayers, updater))
|
||||
);
|
||||
|
||||
const amendedOverpassSource =
|
||||
new RememberingSource(new LocalStorageSaver(
|
||||
overpassSource
|
||||
));
|
||||
|
||||
const merged = new FeatureSourceMerger([
|
||||
amendedOverpassSource,
|
||||
new FeatureDuplicatorPerLayer(flayers, State.state.changes),
|
||||
new LocalStorageSource()
|
||||
]);
|
||||
merged.features.addCallbackAndRun(feats => console.log("Merged has",feats?.length))
|
||||
|
||||
const source =
|
||||
new FilteringFeatureSource(
|
||||
flayers,
|
||||
State.state.locationControl,
|
||||
merged
|
||||
);
|
||||
source.features.addCallbackAndRun(feats => console.log("Filtered has",feats?.length))
|
||||
|
||||
|
||||
this.features = source.features;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,15 +9,20 @@ export default class FeatureSourceMerger implements FeatureSource {
|
|||
constructor(sources: FeatureSource[]) {
|
||||
this._sources = sources;
|
||||
const self = this;
|
||||
for (const source of sources) {
|
||||
source.features.addCallback(() => self.Update());
|
||||
for (let i = 0; i < sources.length; i++){
|
||||
let source = sources[i];
|
||||
source.features.addCallback(() => {
|
||||
self.Update();
|
||||
});
|
||||
}
|
||||
this.Update();
|
||||
}
|
||||
|
||||
private Update() {
|
||||
let all = {}; // Mapping 'id' -> {feature, freshness}
|
||||
for (const source of this._sources) {
|
||||
if(source?.features?.data === undefined){
|
||||
console.log("Not defined");
|
||||
continue;
|
||||
}
|
||||
for (const f of source.features.data) {
|
||||
|
|
|
@ -74,6 +74,7 @@ export default class FilteringFeatureSource implements FeatureSource {
|
|||
update();
|
||||
});
|
||||
|
||||
update();
|
||||
|
||||
}
|
||||
|
||||
|
|
35
Logic/FeatureSource/LocalStorageSaver.ts
Normal file
35
Logic/FeatureSource/LocalStorageSaver.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
/***
|
||||
* Saves all the features that are passed in to localstorage, so they can be retrieved on the next run
|
||||
*
|
||||
* Technically, more an Actor then a featuresource, but it fits more neatly this ay
|
||||
*/
|
||||
import FeatureSource from "./FeatureSource";
|
||||
import {UIEventSource} from "../UIEventSource";
|
||||
|
||||
export default class LocalStorageSaver implements FeatureSource {
|
||||
public static readonly storageKey: string = "cached-features";
|
||||
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
||||
|
||||
constructor(source: FeatureSource) {
|
||||
this.features = source.features;
|
||||
|
||||
this.features.addCallbackAndRun(features => {
|
||||
if (features === undefined) {
|
||||
return;
|
||||
}
|
||||
if(features.length == 0){
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
localStorage.setItem(LocalStorageSaver.storageKey, JSON.stringify(features));
|
||||
} catch (e) {
|
||||
console.warn("Could not save the features to local storage:", e)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
22
Logic/FeatureSource/LocalStorageSource.ts
Normal file
22
Logic/FeatureSource/LocalStorageSource.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import FeatureSource from "./FeatureSource";
|
||||
import {UIEventSource} from "../UIEventSource";
|
||||
import LocalStorageSaver from "./LocalStorageSaver";
|
||||
|
||||
export default class LocalStorageSource implements FeatureSource {
|
||||
public features: UIEventSource<{ feature: any; freshness: Date }[]>;
|
||||
|
||||
constructor() {
|
||||
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([])
|
||||
try {
|
||||
const fromStorage = localStorage.getItem(LocalStorageSaver.storageKey);
|
||||
if (fromStorage == null) {
|
||||
return;
|
||||
}
|
||||
const loaded = JSON.parse(fromStorage);
|
||||
this.features.setData(loaded);
|
||||
} catch (e) {
|
||||
console.log("Could not load features from localStorage:", e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue