mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-09-02 00:32:33 +00:00
fix mounting and destroying issues
This commit is contained in:
@@ -3,11 +3,18 @@
|
|||||||
import ElevationProfile from '$lib/components/ElevationProfile.svelte';
|
import ElevationProfile from '$lib/components/ElevationProfile.svelte';
|
||||||
import FileList from '$lib/components/file-list/FileList.svelte';
|
import FileList from '$lib/components/file-list/FileList.svelte';
|
||||||
import GPXStatistics from '$lib/components/GPXStatistics.svelte';
|
import GPXStatistics from '$lib/components/GPXStatistics.svelte';
|
||||||
import MapComponent from '$lib/components/Map.svelte';
|
import Map from '$lib/components/Map.svelte';
|
||||||
import LayerControl from '$lib/components/layer-control/LayerControl.svelte';
|
import LayerControl from '$lib/components/layer-control/LayerControl.svelte';
|
||||||
import OpenIn from '$lib/components/embedding/OpenIn.svelte';
|
import OpenIn from '$lib/components/embedding/OpenIn.svelte';
|
||||||
|
|
||||||
import { gpxStatistics, slicedGPXStatistics, embedding, loadFile, map } from '$lib/stores';
|
import {
|
||||||
|
gpxStatistics,
|
||||||
|
slicedGPXStatistics,
|
||||||
|
embedding,
|
||||||
|
loadFile,
|
||||||
|
map,
|
||||||
|
updateGPXData
|
||||||
|
} from '$lib/stores';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
import { fileObservers, settings, GPXStatisticsTree } from '$lib/db';
|
import { fileObservers, settings, GPXStatisticsTree } from '$lib/db';
|
||||||
import { readable } from 'svelte/store';
|
import { readable } from 'svelte/store';
|
||||||
@@ -167,6 +174,10 @@
|
|||||||
applyOptions();
|
applyOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: if ($fileOrder) {
|
||||||
|
updateGPXData();
|
||||||
|
}
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
if ($distanceMarkers !== prevSettings.distanceMarkers) {
|
if ($distanceMarkers !== prevSettings.distanceMarkers) {
|
||||||
$distanceMarkers = prevSettings.distanceMarkers;
|
$distanceMarkers = prevSettings.distanceMarkers;
|
||||||
@@ -194,7 +205,7 @@
|
|||||||
|
|
||||||
<div class="absolute flex flex-col h-full w-full border rounded-xl overflow-clip">
|
<div class="absolute flex flex-col h-full w-full border rounded-xl overflow-clip">
|
||||||
<div class="grow relative">
|
<div class="grow relative">
|
||||||
<MapComponent
|
<Map
|
||||||
class="h-full {$fileObservers.size > 1 ? 'horizontal' : ''}"
|
class="h-full {$fileObservers.size > 1 ? 'horizontal' : ''}"
|
||||||
accessToken={options.token}
|
accessToken={options.token}
|
||||||
geocoder={false}
|
geocoder={false}
|
||||||
|
@@ -9,13 +9,14 @@ const { distanceMarkers, distanceUnits, currentBasemap } = settings;
|
|||||||
export class DistanceMarkers {
|
export class DistanceMarkers {
|
||||||
map: mapboxgl.Map;
|
map: mapboxgl.Map;
|
||||||
updateBinded: () => void = this.update.bind(this);
|
updateBinded: () => void = this.update.bind(this);
|
||||||
|
unsubscribes: (() => void)[] = [];
|
||||||
|
|
||||||
constructor(map: mapboxgl.Map) {
|
constructor(map: mapboxgl.Map) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
|
|
||||||
gpxStatistics.subscribe(this.updateBinded);
|
this.unsubscribes.push(gpxStatistics.subscribe(this.updateBinded));
|
||||||
distanceMarkers.subscribe(this.updateBinded);
|
this.unsubscribes.push(distanceMarkers.subscribe(this.updateBinded));
|
||||||
distanceUnits.subscribe(this.updateBinded);
|
this.unsubscribes.push(distanceUnits.subscribe(this.updateBinded));
|
||||||
this.map.on('style.load', this.updateBinded);
|
this.map.on('style.load', this.updateBinded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +62,10 @@ export class DistanceMarkers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
this.unsubscribes.forEach(unsubscribe => unsubscribe());
|
||||||
|
}
|
||||||
|
|
||||||
getDistanceMarkersGeoJSON(): GeoJSON.FeatureCollection {
|
getDistanceMarkersGeoJSON(): GeoJSON.FeatureCollection {
|
||||||
let statistics = get(gpxStatistics);
|
let statistics = get(gpxStatistics);
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { currentTool, Tool } from "$lib/stores";
|
import { currentTool, map, Tool } from "$lib/stores";
|
||||||
import { settings, type GPXFileWithStatistics, dbUtils } from "$lib/db";
|
import { settings, type GPXFileWithStatistics, dbUtils } from "$lib/db";
|
||||||
import { get, type Readable } from "svelte/store";
|
import { get, type Readable } from "svelte/store";
|
||||||
import mapboxgl from "mapbox-gl";
|
import mapboxgl from "mapbox-gl";
|
||||||
@@ -259,20 +259,28 @@ export class GPXLayer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
remove() {
|
updateMap(map: mapboxgl.Map) {
|
||||||
this.map.off('click', this.fileId, this.layerOnClickBinded);
|
this.map = map;
|
||||||
this.map.off('mouseenter', this.fileId, this.layerOnMouseEnterBinded);
|
this.map.on('style.load', this.updateBinded);
|
||||||
this.map.off('mouseleave', this.fileId, this.layerOnMouseLeaveBinded);
|
this.update();
|
||||||
this.map.off('style.load', this.updateBinded);
|
}
|
||||||
|
|
||||||
if (this.map.getLayer(this.fileId + '-direction')) {
|
remove() {
|
||||||
this.map.removeLayer(this.fileId + '-direction');
|
if (get(map)) {
|
||||||
}
|
this.map.off('click', this.fileId, this.layerOnClickBinded);
|
||||||
if (this.map.getLayer(this.fileId)) {
|
this.map.off('mouseenter', this.fileId, this.layerOnMouseEnterBinded);
|
||||||
this.map.removeLayer(this.fileId);
|
this.map.off('mouseleave', this.fileId, this.layerOnMouseLeaveBinded);
|
||||||
}
|
this.map.off('style.load', this.updateBinded);
|
||||||
if (this.map.getSource(this.fileId)) {
|
|
||||||
this.map.removeSource(this.fileId);
|
if (this.map.getLayer(this.fileId + '-direction')) {
|
||||||
|
this.map.removeLayer(this.fileId + '-direction');
|
||||||
|
}
|
||||||
|
if (this.map.getLayer(this.fileId)) {
|
||||||
|
this.map.removeLayer(this.fileId);
|
||||||
|
}
|
||||||
|
if (this.map.getSource(this.fileId)) {
|
||||||
|
this.map.removeSource(this.fileId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.markers.forEach((marker) => {
|
this.markers.forEach((marker) => {
|
||||||
|
@@ -5,9 +5,10 @@
|
|||||||
import { fileObservers } from '$lib/db';
|
import { fileObservers } from '$lib/db';
|
||||||
import { DistanceMarkers } from './DistanceMarkers';
|
import { DistanceMarkers } from './DistanceMarkers';
|
||||||
import { StartEndMarkers } from './StartEndMarkers';
|
import { StartEndMarkers } from './StartEndMarkers';
|
||||||
|
import { onDestroy } from 'svelte';
|
||||||
|
|
||||||
let distanceMarkers: DistanceMarkers;
|
let distanceMarkers: DistanceMarkers | undefined = undefined;
|
||||||
let startEndMarkers: StartEndMarkers;
|
let startEndMarkers: StartEndMarkers | undefined = undefined;
|
||||||
|
|
||||||
$: if ($map && $fileObservers) {
|
$: if ($map && $fileObservers) {
|
||||||
// remove layers for deleted files
|
// remove layers for deleted files
|
||||||
@@ -15,6 +16,8 @@
|
|||||||
if (!$fileObservers.has(fileId)) {
|
if (!$fileObservers.has(fileId)) {
|
||||||
layer.remove();
|
layer.remove();
|
||||||
gpxLayers.delete(fileId);
|
gpxLayers.delete(fileId);
|
||||||
|
} else if ($map !== layer.map) {
|
||||||
|
layer.updateMap($map);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// add layers for new files
|
// add layers for new files
|
||||||
@@ -26,9 +29,30 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$: if ($map) {
|
$: if ($map) {
|
||||||
|
if (distanceMarkers) {
|
||||||
|
distanceMarkers.remove();
|
||||||
|
}
|
||||||
|
if (startEndMarkers) {
|
||||||
|
startEndMarkers.remove();
|
||||||
|
}
|
||||||
distanceMarkers = new DistanceMarkers($map);
|
distanceMarkers = new DistanceMarkers($map);
|
||||||
startEndMarkers = new StartEndMarkers($map);
|
startEndMarkers = new StartEndMarkers($map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
gpxLayers.forEach((layer) => layer.remove());
|
||||||
|
gpxLayers.clear();
|
||||||
|
|
||||||
|
if (distanceMarkers) {
|
||||||
|
distanceMarkers.remove();
|
||||||
|
distanceMarkers = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startEndMarkers) {
|
||||||
|
startEndMarkers.remove();
|
||||||
|
startEndMarkers = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<WaypointPopup />
|
<WaypointPopup />
|
||||||
|
@@ -7,6 +7,7 @@ export class StartEndMarkers {
|
|||||||
start: mapboxgl.Marker;
|
start: mapboxgl.Marker;
|
||||||
end: mapboxgl.Marker;
|
end: mapboxgl.Marker;
|
||||||
updateBinded: () => void = this.update.bind(this);
|
updateBinded: () => void = this.update.bind(this);
|
||||||
|
unsubscribes: (() => void)[] = [];
|
||||||
|
|
||||||
constructor(map: mapboxgl.Map) {
|
constructor(map: mapboxgl.Map) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
@@ -20,9 +21,9 @@ export class StartEndMarkers {
|
|||||||
this.start = new mapboxgl.Marker({ element: startElement });
|
this.start = new mapboxgl.Marker({ element: startElement });
|
||||||
this.end = new mapboxgl.Marker({ element: endElement });
|
this.end = new mapboxgl.Marker({ element: endElement });
|
||||||
|
|
||||||
gpxStatistics.subscribe(this.updateBinded);
|
this.unsubscribes.push(gpxStatistics.subscribe(this.updateBinded));
|
||||||
slicedGPXStatistics.subscribe(this.updateBinded);
|
this.unsubscribes.push(slicedGPXStatistics.subscribe(this.updateBinded));
|
||||||
currentTool.subscribe(this.updateBinded);
|
this.unsubscribes.push(currentTool.subscribe(this.updateBinded));
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
@@ -36,4 +37,11 @@ export class StartEndMarkers {
|
|||||||
this.end.remove();
|
this.end.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove() {
|
||||||
|
this.unsubscribes.forEach(unsubscribe => unsubscribe());
|
||||||
|
|
||||||
|
this.start.remove();
|
||||||
|
this.end.remove();
|
||||||
|
}
|
||||||
}
|
}
|
@@ -54,15 +54,14 @@
|
|||||||
if (selectedItem && selectedItem.getFileId() === fileId) {
|
if (selectedItem && selectedItem.getFileId() === fileId) {
|
||||||
selectedItem = null;
|
selectedItem = null;
|
||||||
}
|
}
|
||||||
|
} else if ($map !== controls.map) {
|
||||||
|
controls.updateMap($map);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// add controls for new files
|
// add controls for new files
|
||||||
$fileObservers.forEach((file, fileId) => {
|
$fileObservers.forEach((file, fileId) => {
|
||||||
if (!routingControls.has(fileId)) {
|
if (!routingControls.has(fileId)) {
|
||||||
routingControls.set(
|
routingControls.set(fileId, new RoutingControls($map, fileId, file, popup, popupElement));
|
||||||
fileId,
|
|
||||||
new RoutingControls(get(map), fileId, file, popup, popupElement)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -92,6 +91,9 @@
|
|||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
$map?.off('click', createFileWithPoint);
|
$map?.off('click', createFileWithPoint);
|
||||||
|
|
||||||
|
routingControls.forEach((controls) => controls.destroy());
|
||||||
|
routingControls.clear();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@@ -135,6 +135,10 @@ export class RoutingControls {
|
|||||||
this.fileUnsubscribe();
|
this.fileUnsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMap(map: mapboxgl.Map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
createAnchor(point: TrackPoint, segment: TrackSegment, trackIndex: number, segmentIndex: number): AnchorWithMarker {
|
createAnchor(point: TrackPoint, segment: TrackSegment, trackIndex: number, segmentIndex: number): AnchorWithMarker {
|
||||||
let element = document.createElement('div');
|
let element = document.createElement('div');
|
||||||
element.className = `h-3 w-3 rounded-full bg-white border-2 border-black cursor-pointer`;
|
element.className = `h-3 w-3 rounded-full bg-white border-2 border-black cursor-pointer`;
|
||||||
|
@@ -20,7 +20,7 @@ export const selectFiles = writable<{ [key: string]: (fileId?: string) => void }
|
|||||||
export const gpxStatistics: Writable<GPXStatistics> = writable(new GPXStatistics());
|
export const gpxStatistics: Writable<GPXStatistics> = writable(new GPXStatistics());
|
||||||
export const slicedGPXStatistics: Writable<[GPXStatistics, number, number] | undefined> = writable(undefined);
|
export const slicedGPXStatistics: Writable<[GPXStatistics, number, number] | undefined> = writable(undefined);
|
||||||
|
|
||||||
function updateGPXData() {
|
export function updateGPXData() {
|
||||||
let statistics = new GPXStatistics();
|
let statistics = new GPXStatistics();
|
||||||
applyToOrderedSelectedItemsFromFile((fileId, level, items) => {
|
applyToOrderedSelectedItemsFromFile((fileId, level, items) => {
|
||||||
let stats = getStatistics(fileId);
|
let stats = getStatistics(fileId);
|
||||||
|
Reference in New Issue
Block a user