mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-11-15 07:07:07 +00:00
filter out extension layers on load
This commit is contained in:
1 parent
4050420b3c
commit
57c34b388b
4 files changed
+52
-42
No files matched your search
@@ -399,13 +399,43 @@ describe('ExtensionAPI v2', () => {
|
|||||||
assert.deepEqual(calls, [{ a: true }]);
|
assert.deepEqual(calls, [{ a: true }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not tell the extension that all is hidden when the page closes', () => {
|
it('forgets the state of the overlays with the next session', () => {
|
||||||
const calls: unknown[] = [];
|
const saved = () => ({
|
||||||
api.onVisibilityChange('Heatmaps', (visible) => calls.push(visible));
|
currentOverlays: JSON.stringify(get(settings.currentOverlays)),
|
||||||
api.setOverlays('Heatmaps', [v2('a', { visible: true })]);
|
previousOverlays: JSON.stringify(get(settings.previousOverlays)),
|
||||||
(api as unknown as { destroy(): void }).destroy();
|
selectedOverlayTree: JSON.stringify(get(settings.selectedOverlayTree)),
|
||||||
assert.deepEqual(calls, []);
|
opacities: JSON.stringify(get(settings.opacities)),
|
||||||
|
});
|
||||||
|
// what was saved, not the default trees, which are the ones that are allowed
|
||||||
|
settings.connect(saved());
|
||||||
|
|
||||||
|
api.setOverlays('Heatmaps', [v2('a', { visible: true }), v2('b')]);
|
||||||
|
api.addOrUpdateOverlay(overlay('one'));
|
||||||
|
settings.selectedOverlayTree.update((tree) => {
|
||||||
|
group(tree)![id('b')] = false;
|
||||||
|
return tree;
|
||||||
|
});
|
||||||
|
settings.opacities.update((opacities) => ({ ...opacities, [id('a')]: 0.3 }));
|
||||||
|
const stored = saved();
|
||||||
|
assert.ok(stored.currentOverlays.includes(id('a')));
|
||||||
|
|
||||||
|
settings.connect(stored);
|
||||||
|
for (const tree of [
|
||||||
|
get(settings.currentOverlays),
|
||||||
|
get(settings.previousOverlays),
|
||||||
|
get(settings.selectedOverlayTree),
|
||||||
|
]) {
|
||||||
|
assert.ok(!JSON.stringify(tree).includes('extension-'));
|
||||||
|
}
|
||||||
|
assert.equal(get(settings.opacities)[id('a')], 0.3);
|
||||||
|
|
||||||
|
// an extension that is still there starts again, as the source of what it remembers
|
||||||
|
const next = new ExtensionAPI();
|
||||||
|
next.setOverlays('Heatmaps', [v2('a'), v2('b', { visible: true })]);
|
||||||
assert.equal(isSelected(get(settings.currentOverlays)!, id('a')), false);
|
assert.equal(isSelected(get(settings.currentOverlays)!, id('a')), false);
|
||||||
|
assert.equal(isSelected(get(settings.currentOverlays)!, id('b')), true);
|
||||||
|
assert.equal(isSelected(get(settings.selectedOverlayTree), id('b')), true);
|
||||||
|
next.setOverlays('Heatmaps', []);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('leaves a style URL for the map to fetch', () => {
|
it('leaves a style URL for the map to fetch', () => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { settings } from '$lib/state/settings';
|
import { settings } from '$lib/state/settings';
|
||||||
import type { StyleSpecification } from 'maplibre-gl';
|
import type { StyleSpecification } from 'maplibre-gl';
|
||||||
import { derived, get, writable, type Writable } from 'svelte/store';
|
import { derived, get, writable, type Writable } from 'svelte/store';
|
||||||
import { isSelected, prefixStyle, remove, removeAll } from './utils';
|
import { isSelected, prefixStyle, removeAll } from './utils';
|
||||||
import { layerGroup, overlays, overlayTree, type LayerTreeType } from '$lib/data/layers';
|
import { layerGroup, overlays, overlayTree, type LayerTreeType } from '$lib/data/layers';
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
import { map } from '$lib/components/map/map';
|
import { map } from '$lib/components/map/map';
|
||||||
@@ -101,9 +101,6 @@ export class ExtensionAPI {
|
|||||||
Object.defineProperty(window, 'gpxstudio', {
|
Object.defineProperty(window, 'gpxstudio', {
|
||||||
value: this,
|
value: this,
|
||||||
});
|
});
|
||||||
addEventListener('beforeunload', () => {
|
|
||||||
this.destroy();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,30 +429,6 @@ export class ExtensionAPI {
|
|||||||
const names = new Set(Array.from($overlays.values(), (overlay) => overlay.extensionName));
|
const names = new Set(Array.from($overlays.values(), (overlay) => overlay.extensionName));
|
||||||
return (id: string) => names.has(id);
|
return (id: string) => names.has(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
private destroy() {
|
|
||||||
// the page is closing: the user has not hidden anything, which extensions would then save
|
|
||||||
this._visibilityCallbacks.clear();
|
|
||||||
const ids = Array.from(get(this._overlays).keys());
|
|
||||||
currentOverlays.update((current) => {
|
|
||||||
ids.forEach((id) => {
|
|
||||||
remove(current, id);
|
|
||||||
});
|
|
||||||
return current;
|
|
||||||
});
|
|
||||||
previousOverlays.update((previous) => {
|
|
||||||
ids.forEach((id) => {
|
|
||||||
remove(previous, id);
|
|
||||||
});
|
|
||||||
return previous;
|
|
||||||
});
|
|
||||||
selectedOverlayTree.update((selected) => {
|
|
||||||
ids.forEach((id) => {
|
|
||||||
remove(selected, id);
|
|
||||||
});
|
|
||||||
return selected;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const extensionAPI = new ExtensionAPI();
|
export const extensionAPI = new ExtensionAPI();
|
||||||
@@ -141,11 +141,13 @@ describe('layer trees', () => {
|
|||||||
assert.deepEqual(filterLayerTree({}, allowed), allowed);
|
assert.deepEqual(filterLayerTree({}, allowed), allowed);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('drops the layers that are not allowed anymore, but not the custom ones', () => {
|
it('drops the layers that are not allowed anymore and those of extensions, not the custom ones', () => {
|
||||||
const filtered = filterLayerTree(
|
const filtered = filterLayerTree(
|
||||||
{
|
{
|
||||||
world: { a: true, gone: true, 'custom-1': true, 'extension-x': false },
|
world: { a: true, gone: true, 'custom-1': true, 'extension-x': true },
|
||||||
old: { x: true },
|
old: { x: true },
|
||||||
|
extension: { 'extension-Name/y': true },
|
||||||
|
custom: { 'custom-2': false },
|
||||||
},
|
},
|
||||||
allowed
|
allowed
|
||||||
);
|
);
|
||||||
@@ -153,10 +155,10 @@ describe('layer trees', () => {
|
|||||||
a: true,
|
a: true,
|
||||||
b: false,
|
b: false,
|
||||||
'custom-1': true,
|
'custom-1': true,
|
||||||
'extension-x': false,
|
|
||||||
});
|
});
|
||||||
assert.equal('old' in filtered, true);
|
assert.equal('old' in filtered, false);
|
||||||
assert.deepEqual(filtered.old, {});
|
assert.equal('extension' in filtered, false);
|
||||||
|
assert.deepEqual(filtered.custom, { 'custom-2': false });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not take a branch for a layer, or a layer for a branch', () => {
|
it('does not take a branch for a layer, or a layer for a branch', () => {
|
||||||
|
|||||||
@@ -196,7 +196,9 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The saved tree `t`, with the layers of `allowed`: the choices saved for them are kept, the new
|
* The saved tree `t`, with the layers of `allowed`: the choices saved for them are kept, the new
|
||||||
* ones have their default, and of the others only the custom and extension layers are kept.
|
* ones have their default, and of the others only the custom layers are kept. The layers of
|
||||||
|
* extensions are saved with the others, but not read back: they come again when an extension sets
|
||||||
|
* them, if it is still there.
|
||||||
*/
|
*/
|
||||||
export function filterLayerTree(t: unknown, allowed: LayerTreeType | undefined): LayerTreeType {
|
export function filterLayerTree(t: unknown, allowed: LayerTreeType | undefined): LayerTreeType {
|
||||||
const tree = isRecord(t) ? t : {};
|
const tree = isRecord(t) ? t : {};
|
||||||
@@ -214,11 +216,14 @@ export function filterLayerTree(t: unknown, allowed: LayerTreeType | undefined):
|
|||||||
Object.entries(tree).forEach(([key, value]) => {
|
Object.entries(tree).forEach(([key, value]) => {
|
||||||
if (!Object.hasOwn(filtered, key)) {
|
if (!Object.hasOwn(filtered, key)) {
|
||||||
if (typeof value === 'boolean') {
|
if (typeof value === 'boolean') {
|
||||||
if (key.startsWith('custom-') || key.startsWith('extension-')) {
|
if (key.startsWith('custom-')) {
|
||||||
filtered[key] = value;
|
filtered[key] = value;
|
||||||
}
|
}
|
||||||
} else if (isRecord(value)) {
|
} else if (isRecord(value)) {
|
||||||
filtered[key] = filterLayerTree(value, undefined);
|
const group = filterLayerTree(value, undefined);
|
||||||
|
if (Object.keys(group).length > 0) {
|
||||||
|
filtered[key] = group;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user