Small tweaks, stabilizing local source cache

This commit is contained in:
pietervdvn 2021-01-15 01:57:46 +01:00
parent f33fe081d0
commit fa4fb71e06
8 changed files with 53 additions and 37 deletions

View file

@ -91,7 +91,6 @@ export default class LayoutConfig {
if (layer.builtin !== undefined) { if (layer.builtin !== undefined) {
// @ts-ignore // @ts-ignore
const name = layer.builtin; const name = layer.builtin;
console.warn("Overwriting!")
const shared = SharedLayers.sharedLayersJson[name]; const shared = SharedLayers.sharedLayersJson[name];
if (shared === undefined) { if (shared === undefined) {
throw "Unkown fixed layer " + name; throw "Unkown fixed layer " + name;

View file

@ -45,7 +45,7 @@ export class InitUiElements {
layoutDefinition: string = "") { layoutDefinition: string = "") {
if (layoutToUse === undefined) { if (layoutToUse === undefined) {
console.log("Incorrect layout") console.log("Incorrect layout")
new FixedUiElement(`Error: incorrect layout <i>${layoutName}</i><br/><a href='https://${window.location.host}/index.html'>Go back</a>`).AttachTo("centermessage").onClick(() => { new FixedUiElement(`Error: incorrect layout <i>${layoutName}</i><br/><a href='https://${window.location.host}/'>Go back</a>`).AttachTo("centermessage").onClick(() => {
}); });
throw "Incorrect layout" throw "Incorrect layout"
} }
@ -400,10 +400,13 @@ export class InitUiElements {
const updater = new LoadFromOverpass(state.locationControl, state.layoutToUse, state.leafletMap); const updater = new LoadFromOverpass(state.locationControl, state.layoutToUse, state.leafletMap);
State.state.layerUpdater = updater; State.state.layerUpdater = updater;
const source = new FeaturePipeline(flayers, updater); const source = new FeaturePipeline(flayers, updater, state.layoutToUse);
source.features.addCallback((featuresFreshness: { feature: any, freshness: Date }[]) => { source.features.addCallbackAndRun((featuresFreshness: { feature: any, freshness: Date }[]) => {
if(featuresFreshness === undefined){
return;
}
let features = featuresFreshness.map(ff => ff.feature); let features = featuresFreshness.map(ff => ff.feature);
features.forEach(feature => { features.forEach(feature => {
State.state.allElements.addElement(feature); State.state.allElements.addElement(feature);

View file

@ -10,38 +10,41 @@ import {UIEventSource} from "../UIEventSource";
import LocalStorageSaver from "./LocalStorageSaver"; import LocalStorageSaver from "./LocalStorageSaver";
import LayerConfig from "../../Customizations/JSON/LayerConfig"; import LayerConfig from "../../Customizations/JSON/LayerConfig";
import LocalStorageSource from "./LocalStorageSource"; import LocalStorageSource from "./LocalStorageSource";
import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
export default class FeaturePipeline implements FeatureSource { export default class FeaturePipeline implements FeatureSource {
public features: UIEventSource<{ feature: any; freshness: Date }[]>; public features: UIEventSource<{ feature: any; freshness: Date }[]>;
constructor(flayers: { isDisplayed: UIEventSource<boolean>, layerDef: LayerConfig }[], updater: FeatureSource) { constructor(flayers: { isDisplayed: UIEventSource<boolean>, layerDef: LayerConfig }[],
updater: FeatureSource,
const overpassSource = new WayHandlingApplyingFeatureSource(flayers, layout: UIEventSource<LayoutConfig>) {
new NoOverlapSource(flayers, new FeatureDuplicatorPerLayer(flayers, updater))
);
const amendedOverpassSource = const amendedOverpassSource =
new RememberingSource(new LocalStorageSaver( new RememberingSource(
overpassSource new WayHandlingApplyingFeatureSource(flayers,
new NoOverlapSource(flayers, new FeatureDuplicatorPerLayer(flayers,
new LocalStorageSaver(updater, layout)))
)
);
const amendedLocalStorageSource =
new RememberingSource(
new WayHandlingApplyingFeatureSource(flayers,
new NoOverlapSource(flayers, new FeatureDuplicatorPerLayer(flayers, new LocalStorageSource(layout)))
)); ));
const merged = new FeatureSourceMerger([ const merged = new FeatureSourceMerger([
amendedOverpassSource, amendedOverpassSource,
new FeatureDuplicatorPerLayer(flayers, State.state.changes), new FeatureDuplicatorPerLayer(flayers, State.state.changes),
new LocalStorageSource() amendedLocalStorageSource
]); ]);
merged.features.addCallbackAndRun(feats => console.log("Merged has",feats?.length))
const source = const source =
new FilteringFeatureSource( new FilteringFeatureSource(
flayers, flayers,
State.state.locationControl, State.state.locationControl,
merged merged
); );
source.features.addCallbackAndRun(feats => console.log("Filtered has",feats?.length))
this.features = source.features; this.features = source.features;
} }

View file

@ -5,12 +5,13 @@
*/ */
import FeatureSource from "./FeatureSource"; import FeatureSource from "./FeatureSource";
import {UIEventSource} from "../UIEventSource"; import {UIEventSource} from "../UIEventSource";
import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
export default class LocalStorageSaver implements FeatureSource { export default class LocalStorageSaver implements FeatureSource {
public static readonly storageKey: string = "cached-features"; public static readonly storageKey: string = "cached-features";
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>; public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
constructor(source: FeatureSource) { constructor(source: FeatureSource, layout: UIEventSource<LayoutConfig>) {
this.features = source.features; this.features = source.features;
this.features.addCallbackAndRun(features => { this.features.addCallbackAndRun(features => {
@ -22,7 +23,9 @@ export default class LocalStorageSaver implements FeatureSource {
} }
try { try {
localStorage.setItem(LocalStorageSaver.storageKey, JSON.stringify(features)); const key = LocalStorageSaver.storageKey+layout.data.id
localStorage.setItem(key, JSON.stringify(features));
console.log("Saved ",features.length, "elements to",key)
} catch (e) { } catch (e) {
console.warn("Could not save the features to local storage:", e) console.warn("Could not save the features to local storage:", e)
} }

View file

@ -1,21 +1,25 @@
import FeatureSource from "./FeatureSource"; import FeatureSource from "./FeatureSource";
import {UIEventSource} from "../UIEventSource"; import {UIEventSource} from "../UIEventSource";
import LocalStorageSaver from "./LocalStorageSaver"; import LocalStorageSaver from "./LocalStorageSaver";
import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
export default class LocalStorageSource implements FeatureSource { export default class LocalStorageSource implements FeatureSource {
public features: UIEventSource<{ feature: any; freshness: Date }[]>; public features: UIEventSource<{ feature: any; freshness: Date }[]>;
constructor() { constructor(layout: UIEventSource<LayoutConfig>) {
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([]) this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([])
const key = LocalStorageSaver.storageKey + layout.data.id
try { try {
const fromStorage = localStorage.getItem(LocalStorageSaver.storageKey); const fromStorage = localStorage.getItem(key);
if (fromStorage == null) { if (fromStorage == null) {
return; return;
} }
const loaded = JSON.parse(fromStorage); const loaded = JSON.parse(fromStorage);
this.features.setData(loaded); this.features.setData(loaded);
console.log("Loaded ",loaded.length," features from localstorage as cache")
} catch (e) { } catch (e) {
console.log("Could not load features from localStorage:", e) console.log("Could not load features from localStorage:", e)
localStorage.removeItem(key)
} }
} }

View file

@ -161,7 +161,7 @@ class BBox{
} }
static get(feature) { static get(feature) {
if (feature.bbox === undefined) { if (feature.bbox?.overlapsWith === undefined) {
if (feature.geometry.type === "MultiPolygon") { if (feature.geometry.type === "MultiPolygon") {
let coordinates = []; let coordinates = [];

View file

@ -4,11 +4,11 @@ import {Utils} from "../../Utils";
export class OsmPreferences { export class OsmPreferences {
private auth: any;
private userDetails: UIEventSource<UserDetails>;
public preferences = new UIEventSource<any>({}); public preferences = new UIEventSource<any>({});
public preferenceSources: any = {} public preferenceSources: any = {}
private auth: any;
private userDetails: UIEventSource<UserDetails>;
private longPreferences = {};
constructor(auth, osmConnection: OsmConnection) { constructor(auth, osmConnection: OsmConnection) {
this.auth = auth; this.auth = auth;
@ -17,8 +17,6 @@ export class OsmPreferences {
osmConnection.OnLoggedIn(() => self.UpdatePreferences()); osmConnection.OnLoggedIn(() => self.UpdatePreferences());
} }
private longPreferences = {};
/** /**
* OSM preferences can be at most 255 chars * OSM preferences can be at most 255 chars
* @param key * @param key
@ -158,7 +156,7 @@ export class OsmPreferences {
if (v === undefined || v === "") { if (v === undefined || v === "") {
this.auth.xhr({ this.auth.xhr({
method: 'DELETE', method: 'DELETE',
path: '/api/0.6/user/preferences/' + k, path: '/api/0.6/user/preferences/' + encodeURIComponent(k),
options: {header: {'Content-Type': 'text/plain'}}, options: {header: {'Content-Type': 'text/plain'}},
}, function (error) { }, function (error) {
if (error) { if (error) {
@ -174,7 +172,7 @@ export class OsmPreferences {
this.auth.xhr({ this.auth.xhr({
method: 'PUT', method: 'PUT',
path: '/api/0.6/user/preferences/' + k, path: '/api/0.6/user/preferences/' + encodeURIComponent(k),
options: {header: {'Content-Type': 'text/plain'}}, options: {header: {'Content-Type': 'text/plain'}},
content: v content: v
}, function (error) { }, function (error) {

View file

@ -65,6 +65,7 @@ if (layoutFromBase64.startsWith("wiki:")) {
.AttachTo("centermessage"); .AttachTo("centermessage");
const cleanUrl = `https://wiki.openstreetmap.org/wiki/${themeName}`; const cleanUrl = `https://wiki.openstreetmap.org/wiki/${themeName}`;
const url = `https://cors-anywhere.herokuapp.com/` + cleanUrl; // ~NOT~ VERY SAFE AND HACKER-PROOF! const url = `https://cors-anywhere.herokuapp.com/` + cleanUrl; // ~NOT~ VERY SAFE AND HACKER-PROOF!
// We use cors-anywhere because the wiki from openstreetmap is locked-down :(
/*/ /*/
const url = cleanUrl; // MUCH SAFER! //*/ const url = cleanUrl; // MUCH SAFER! //*/
@ -81,7 +82,8 @@ if (layoutFromBase64.startsWith("wiki:")) {
console.log(data) console.log(data)
try { try {
const parsed = JSON.parse(data); const parsed = JSON.parse(data);
parsed["id"] = layoutFromBase64 // Overwrite the id to the wiki:value
parsed.id = layoutFromBase64.replace(/[: \/]/g, '-')
const layout = new LayoutConfig(parsed); const layout = new LayoutConfig(parsed);
InitUiElements.InitAll(layout, layoutFromBase64, testing, layoutFromBase64, btoa(data)); InitUiElements.InitAll(layout, layoutFromBase64, testing, layoutFromBase64, btoa(data));
} catch (e) { } catch (e) {
@ -92,8 +94,11 @@ if (layoutFromBase64.startsWith("wiki:")) {
throw e; throw e;
} }
}, },
}).fail(() => { }).fail((_, textstatus, error) => {
new FixedUiElement(`<a href="${cleanUrl}">${themeName}</a> is invalid:<br/>Could not download - wrong URL?`) console.error("Could not download the wiki theme:", textstatus, error)
new FixedUiElement(`<a href="${cleanUrl}">${themeName}</a> is invalid:<br/>Could not download - wrong URL?<br/>`+
error +
"<a href='https://${window.location.host}/'>Go back</a>")
.SetClass("clickable") .SetClass("clickable")
.AttachTo("centermessage"); .AttachTo("centermessage");
}); });
@ -105,6 +110,7 @@ if (layoutFromBase64.startsWith("wiki:")) {
// This is the default case: a builtin theme // This is the default case: a builtin theme
InitUiElements.InitAll(layoutToUse, layoutFromBase64, testing, defaultLayout); InitUiElements.InitAll(layoutToUse, layoutFromBase64, testing, defaultLayout);
} else { } else {
// We fall through: no theme loaded: just show a few buttons
document.getElementById("decoration-desktop").remove(); document.getElementById("decoration-desktop").remove();
State.state = new State(undefined); State.state = new State(undefined);
document.getElementById("messagesboxmobile").remove(); document.getElementById("messagesboxmobile").remove();