diff --git a/Customizations/JSON/LayoutConfig.ts b/Customizations/JSON/LayoutConfig.ts
index a1f58c7d6e..fb22a66c69 100644
--- a/Customizations/JSON/LayoutConfig.ts
+++ b/Customizations/JSON/LayoutConfig.ts
@@ -91,7 +91,6 @@ export default class LayoutConfig {
if (layer.builtin !== undefined) {
// @ts-ignore
const name = layer.builtin;
- console.warn("Overwriting!")
const shared = SharedLayers.sharedLayersJson[name];
if (shared === undefined) {
throw "Unkown fixed layer " + name;
diff --git a/InitUiElements.ts b/InitUiElements.ts
index 5f2eb40fc7..fb558632bf 100644
--- a/InitUiElements.ts
+++ b/InitUiElements.ts
@@ -45,7 +45,7 @@ export class InitUiElements {
layoutDefinition: string = "") {
if (layoutToUse === undefined) {
console.log("Incorrect layout")
- new FixedUiElement(`Error: incorrect layout ${layoutName}
Go back`).AttachTo("centermessage").onClick(() => {
+ new FixedUiElement(`Error: incorrect layout ${layoutName}
Go back`).AttachTo("centermessage").onClick(() => {
});
throw "Incorrect layout"
}
@@ -400,10 +400,13 @@ export class InitUiElements {
const updater = new LoadFromOverpass(state.locationControl, state.layoutToUse, state.leafletMap);
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);
features.forEach(feature => {
State.state.allElements.addElement(feature);
diff --git a/Logic/FeatureSource/FeaturePipeline.ts b/Logic/FeatureSource/FeaturePipeline.ts
index a9794c14a9..ea2e9b2e91 100644
--- a/Logic/FeatureSource/FeaturePipeline.ts
+++ b/Logic/FeatureSource/FeaturePipeline.ts
@@ -10,38 +10,41 @@ import {UIEventSource} from "../UIEventSource";
import LocalStorageSaver from "./LocalStorageSaver";
import LayerConfig from "../../Customizations/JSON/LayerConfig";
import LocalStorageSource from "./LocalStorageSource";
+import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
export default class FeaturePipeline implements FeatureSource {
public features: UIEventSource<{ feature: any; freshness: Date }[]>;
- constructor(flayers: { isDisplayed: UIEventSource, layerDef: LayerConfig }[], updater: FeatureSource) {
-
- const overpassSource = new WayHandlingApplyingFeatureSource(flayers,
- new NoOverlapSource(flayers, new FeatureDuplicatorPerLayer(flayers, updater))
- );
+ constructor(flayers: { isDisplayed: UIEventSource, layerDef: LayerConfig }[],
+ updater: FeatureSource,
+ layout: UIEventSource) {
const amendedOverpassSource =
- new RememberingSource(new LocalStorageSaver(
- overpassSource
- ));
+ new RememberingSource(
+ 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([
amendedOverpassSource,
new FeatureDuplicatorPerLayer(flayers, State.state.changes),
- new LocalStorageSource()
+ amendedLocalStorageSource
]);
- 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;
}
diff --git a/Logic/FeatureSource/LocalStorageSaver.ts b/Logic/FeatureSource/LocalStorageSaver.ts
index 82aab778a3..6dc4630981 100644
--- a/Logic/FeatureSource/LocalStorageSaver.ts
+++ b/Logic/FeatureSource/LocalStorageSaver.ts
@@ -5,12 +5,13 @@
*/
import FeatureSource from "./FeatureSource";
import {UIEventSource} from "../UIEventSource";
+import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
export default class LocalStorageSaver implements FeatureSource {
public static readonly storageKey: string = "cached-features";
public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>;
- constructor(source: FeatureSource) {
+ constructor(source: FeatureSource, layout: UIEventSource) {
this.features = source.features;
this.features.addCallbackAndRun(features => {
@@ -22,7 +23,9 @@ export default class LocalStorageSaver implements FeatureSource {
}
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) {
console.warn("Could not save the features to local storage:", e)
}
diff --git a/Logic/FeatureSource/LocalStorageSource.ts b/Logic/FeatureSource/LocalStorageSource.ts
index 1cbcaca161..41711f8ded 100644
--- a/Logic/FeatureSource/LocalStorageSource.ts
+++ b/Logic/FeatureSource/LocalStorageSource.ts
@@ -1,21 +1,25 @@
import FeatureSource from "./FeatureSource";
import {UIEventSource} from "../UIEventSource";
import LocalStorageSaver from "./LocalStorageSaver";
+import LayoutConfig from "../../Customizations/JSON/LayoutConfig";
export default class LocalStorageSource implements FeatureSource {
public features: UIEventSource<{ feature: any; freshness: Date }[]>;
- constructor() {
+ constructor(layout: UIEventSource) {
this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([])
+ const key = LocalStorageSaver.storageKey + layout.data.id
try {
- const fromStorage = localStorage.getItem(LocalStorageSaver.storageKey);
+ const fromStorage = localStorage.getItem(key);
if (fromStorage == null) {
return;
}
const loaded = JSON.parse(fromStorage);
this.features.setData(loaded);
+ console.log("Loaded ",loaded.length," features from localstorage as cache")
} catch (e) {
console.log("Could not load features from localStorage:", e)
+ localStorage.removeItem(key)
}
}
diff --git a/Logic/GeoOperations.ts b/Logic/GeoOperations.ts
index b97ad5e6d8..86bc694c3a 100644
--- a/Logic/GeoOperations.ts
+++ b/Logic/GeoOperations.ts
@@ -161,7 +161,7 @@ class BBox{
}
static get(feature) {
- if (feature.bbox === undefined) {
+ if (feature.bbox?.overlapsWith === undefined) {
if (feature.geometry.type === "MultiPolygon") {
let coordinates = [];
diff --git a/Logic/Osm/OsmPreferences.ts b/Logic/Osm/OsmPreferences.ts
index 7b82c2180b..8914ae1cd7 100644
--- a/Logic/Osm/OsmPreferences.ts
+++ b/Logic/Osm/OsmPreferences.ts
@@ -4,11 +4,11 @@ import {Utils} from "../../Utils";
export class OsmPreferences {
- private auth: any;
- private userDetails: UIEventSource;
-
public preferences = new UIEventSource({});
public preferenceSources: any = {}
+ private auth: any;
+ private userDetails: UIEventSource;
+ private longPreferences = {};
constructor(auth, osmConnection: OsmConnection) {
this.auth = auth;
@@ -17,8 +17,6 @@ export class OsmPreferences {
osmConnection.OnLoggedIn(() => self.UpdatePreferences());
}
- private longPreferences = {};
-
/**
* OSM preferences can be at most 255 chars
* @param key
@@ -43,8 +41,8 @@ export class OsmPreferences {
if (str === undefined || str === "") {
return;
}
- if(str === null){
- console.error("Deleting "+allStartWith);
+ if (str === null) {
+ console.error("Deleting " + allStartWith);
let count = parseInt(length.data);
for (let i = 0; i < count; i++) {
// Delete all the preferences
@@ -99,7 +97,7 @@ export class OsmPreferences {
public GetPreference(key: string, prefix: string = "mapcomplete-"): UIEventSource {
key = prefix + key;
- if(key.length >= 255){
+ if (key.length >= 255) {
throw "Preferences: key length to big";
}
if (this.preferenceSources[key] !== undefined) {
@@ -158,14 +156,14 @@ export class OsmPreferences {
if (v === undefined || v === "") {
this.auth.xhr({
method: 'DELETE',
- path: '/api/0.6/user/preferences/' + k,
+ path: '/api/0.6/user/preferences/' + encodeURIComponent(k),
options: {header: {'Content-Type': 'text/plain'}},
}, function (error) {
if (error) {
console.log("Could not remove preference", error);
return;
}
- console.log("Preference ",k,"removed!");
+ console.log("Preference ", k, "removed!");
});
return;
@@ -174,7 +172,7 @@ export class OsmPreferences {
this.auth.xhr({
method: 'PUT',
- path: '/api/0.6/user/preferences/' + k,
+ path: '/api/0.6/user/preferences/' + encodeURIComponent(k),
options: {header: {'Content-Type': 'text/plain'}},
content: v
}, function (error) {
diff --git a/index.ts b/index.ts
index 18061dc34a..3514213af8 100644
--- a/index.ts
+++ b/index.ts
@@ -65,6 +65,7 @@ if (layoutFromBase64.startsWith("wiki:")) {
.AttachTo("centermessage");
const cleanUrl = `https://wiki.openstreetmap.org/wiki/${themeName}`;
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! //*/
@@ -81,7 +82,8 @@ if (layoutFromBase64.startsWith("wiki:")) {
console.log(data)
try {
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);
InitUiElements.InitAll(layout, layoutFromBase64, testing, layoutFromBase64, btoa(data));
} catch (e) {
@@ -92,8 +94,11 @@ if (layoutFromBase64.startsWith("wiki:")) {
throw e;
}
},
- }).fail(() => {
- new FixedUiElement(`${themeName} is invalid:
Could not download - wrong URL?`)
+ }).fail((_, textstatus, error) => {
+ console.error("Could not download the wiki theme:", textstatus, error)
+ new FixedUiElement(`${themeName} is invalid:
Could not download - wrong URL?
`+
+ error +
+ "Go back")
.SetClass("clickable")
.AttachTo("centermessage");
});
@@ -105,6 +110,7 @@ if (layoutFromBase64.startsWith("wiki:")) {
// This is the default case: a builtin theme
InitUiElements.InitAll(layoutToUse, layoutFromBase64, testing, defaultLayout);
} else {
+ // We fall through: no theme loaded: just show a few buttons
document.getElementById("decoration-desktop").remove();
State.state = new State(undefined);
document.getElementById("messagesboxmobile").remove();