fixes race condition in route edit menu

This commit is contained in:
Christian Beutel
2025-08-02 18:35:50 +02:00
parent 46d3c45b58
commit 396e64b5a6
3 changed files with 61 additions and 63 deletions

View File

@@ -12,6 +12,7 @@
import Select, { type SelectItem } from "../base/select.svelte"; import Select, { type SelectItem } from "../base/select.svelte";
import Slider from "../base/slider.svelte"; import Slider from "../base/slider.svelte";
import Toggle from "../base/toggle.svelte"; import Toggle from "../base/toggle.svelte";
import { tick } from "svelte";
interface Props { interface Props {
options: RoutingOptions; options: RoutingOptions;
onReverse: () => void; onReverse: () => void;
@@ -114,6 +115,14 @@
break; break;
} }
} }
async function togglePanels(_edit: boolean, _crop: boolean, _recalc: boolean) {
recalculateElevationData = _recalc;
crop = _crop;
editRoute = _edit
await tick()
onCropToggle(_crop);
}
</script> </script>
<div class="flex gap-x-2 items-start"> <div class="flex gap-x-2 items-start">
@@ -122,34 +131,19 @@
class="btn-icon" class="btn-icon"
class:bg-secondary-hover={editRoute} class:bg-secondary-hover={editRoute}
aria-label="edit route" aria-label="edit route"
onclick={() => { onclick={async () => await togglePanels(!editRoute, false, false)}><i class="fa fa-route text-sm"></i></button
recalculateElevationData = false;
crop = false;
editRoute = !editRoute;
onCropToggle(false);
}}><i class="fa fa-route text-sm"></i></button
> >
<button <button
class="btn-icon" class="btn-icon"
class:bg-secondary-hover={crop} class:bg-secondary-hover={crop}
aria-label="crop route" aria-label="crop route"
onclick={() => { onclick={async () => await togglePanels(false, !crop, false)}><i class="fa fa-scissors text-sm"></i></button
recalculateElevationData = false;
crop = !crop;
editRoute = false;
onCropToggle(crop);
}}><i class="fa fa-scissors text-sm"></i></button
> >
<button <button
class="btn-icon" class="btn-icon"
class:bg-secondary-hover={recalculateElevationData} class:bg-secondary-hover={recalculateElevationData}
aria-label="recalculate elevation data" aria-label="recalculate elevation data"
onclick={() => { onclick={async () => await togglePanels(false, false, !recalculateElevationData)}><i class="fa fa-mountain text-sm"></i></button
recalculateElevationData = !recalculateElevationData;
crop = false;
editRoute = false;
onCropToggle(false);
}}><i class="fa fa-mountain text-sm"></i></button
> >
<button <button
class="btn-icon" class="btn-icon"

View File

@@ -214,6 +214,8 @@ export async function recalculateHeight() {
} }
export async function splitSegment(index: number, pos: LngLat) { export async function splitSegment(index: number, pos: LngLat) {
console.log(valhallaStore.route.features.duration);
let seg = valhallaStore.route.trk?.at(0)?.trkseg?.at(index); let seg = valhallaStore.route.trk?.at(0)?.trkseg?.at(index);
if (!seg || !seg.trkpt) { if (!seg || !seg.trkpt) {
return; return;
@@ -232,12 +234,13 @@ export async function splitSegment(index: number, pos: LngLat) {
} }
} }
const intersectionPoint = new Waypoint({ $: { lat: pos.lat, lon: pos.lng }, ele: points[bestSplitIndex].ele }); const intersectionPoint = new Waypoint({ ...points[bestSplitIndex], $: { lat: pos.lat, lon: pos.lng } });
const firstSegmentPoints = [...points.slice(0, bestSplitIndex), intersectionPoint]; const firstSegmentPoints = [...points.slice(0, bestSplitIndex), intersectionPoint];
const secondSegmentPoints = [intersectionPoint, ...points.slice(bestSplitIndex)]; const secondSegmentPoints = [intersectionPoint, ...points.slice(bestSplitIndex)];
editRoute(index, firstSegmentPoints) editRoute(index, firstSegmentPoints)
insertIntoRoute(secondSegmentPoints, index + 1) insertIntoRoute(secondSegmentPoints, index + 1)
} }
export function normalizeRouteTime() { export function normalizeRouteTime() {

View File

@@ -94,7 +94,7 @@
import cryptoRandomString from "crypto-random-string"; import cryptoRandomString from "crypto-random-string";
import { createForm } from "felte"; import { createForm } from "felte";
import * as M from "maplibre-gl"; import * as M from "maplibre-gl";
import { onMount, untrack } from "svelte"; import { onMount, tick, untrack } from "svelte";
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { backInOut } from "svelte/easing"; import { backInOut } from "svelte/easing";
import { fly, slide } from "svelte/transition"; import { fly, slide } from "svelte/transition";
@@ -548,7 +548,6 @@
} }
function startDrawing() { function startDrawing() {
console.log("starting drawing...");
if (!map) { if (!map) {
return; return;
} }
@@ -561,32 +560,30 @@
} }
async function stopDrawing() { async function stopDrawing() {
console.log("stopping drawing...");
drawingActive = false; drawingActive = false;
// for (const anchor of valhallaStore.anchors) { for (const anchor of valhallaStore.anchors) {
// anchor.marker?.remove(); anchor.marker?.remove();
// } }
// toggleCropMarkers(false); toggleCropMarkers(false);
// clearUndoRedoStack(); clearUndoRedoStack();
// if (valhallaStore.route.trk?.at(0)?.trkseg?.at(0)?.trkpt?.at(0)) { if (valhallaStore.route.trk?.at(0)?.trkseg?.at(0)?.trkpt?.at(0)) {
// $formData.lat = valhallaStore.route.trk $formData.lat = valhallaStore.route.trk
// ?.at(0) ?.at(0)
// ?.trkseg?.at(0) ?.trkseg?.at(0)
// ?.trkpt?.at(0)?.$.lat; ?.trkpt?.at(0)?.$.lat;
// $formData.lon = valhallaStore.route.trk $formData.lon = valhallaStore.route.trk
// ?.at(0) ?.at(0)
// ?.trkseg?.at(0) ?.trkseg?.at(0)
// ?.trkpt?.at(0)?.$.lon; ?.trkpt?.at(0)?.$.lon;
// } }
// if ($formData.lat && $formData.lon) { if ($formData.lat && $formData.lon) {
// const r = await searchLocationReverse($formData.lat, $formData.lon); const r = await searchLocationReverse($formData.lat, $formData.lon);
// if (r) { if (r) {
// setFields("location", r); setFields("location", r);
// } }
// } }
} }
async function handleMapClick(e: M.MapMouseEvent) { async function handleMapClick(e: M.MapMouseEvent) {
@@ -922,17 +919,15 @@
} }
function toggleCropMarkers(active: boolean) { function toggleCropMarkers(active: boolean) {
console.log("toggleCropMarkers", active);
if (active) { if (active) {
cropStartMarker?.setOpacity("1"); cropStartMarker?.setOpacity("1");
cropEndMarker?.setOpacity("1"); cropEndMarker?.setOpacity("1");
} else { } else {
cropStartMarker?.setOpacity("0"); cropStartMarker?.setOpacity("0");
cropEndMarker?.setOpacity("0"); cropEndMarker?.setOpacity("0");
const totals = valhallaStore.route.features;
$formData.distance = totals.distance; updateTotals(valhallaStore.route);
$formData.duration = totals.duration / 1000;
$formData.elevation_gain = totals.elevationGain;
$formData.elevation_loss = totals.elevationLoss;
} }
} }
@@ -966,7 +961,6 @@
cropStartMarker.setLngLat([0, 0]).addTo(map!); cropStartMarker.setLngLat([0, 0]).addTo(map!);
cropEndMarker.setLngLat([0, 0]).addTo(map!); cropEndMarker.setLngLat([0, 0]).addTo(map!);
} }
const [start, end] = range; const [start, end] = range;
const flatRoute = valhallaStore.route.flatten(); const flatRoute = valhallaStore.route.flatten();
@@ -995,11 +989,8 @@
flatRoute[endIndex], flatRoute[endIndex],
valhallaStore.route, valhallaStore.route,
); );
const totals = croppedGPX.features;
$formData.distance = totals.distance; updateTotals(croppedGPX);
$formData.duration = totals.duration / 1000;
$formData.elevation_gain = totals.elevationGain;
$formData.elevation_loss = totals.elevationLoss;
} }
function confirmCrop() { function confirmCrop() {
@@ -1043,11 +1034,7 @@
function updateTrailWithRouteData() { function updateTrailWithRouteData() {
overwriteGPX = true; overwriteGPX = true;
const totals = valhallaStore.route.features; updateTotals(valhallaStore.route);
$formData.distance = totals.distance;
$formData.duration = totals.duration / 1000;
$formData.elevation_gain = totals.elevationGain;
$formData.elevation_loss = totals.elevationLoss;
$formData.expand!.gpx_data = valhallaStore.route.toString(); $formData.expand!.gpx_data = valhallaStore.route.toString();
if (!$formData.id) { if (!$formData.id) {
@@ -1055,6 +1042,14 @@
} }
} }
function updateTotals(gpx: GPX) {
const totals = gpx.features;
$formData.distance = totals.distance;
$formData.duration = totals.duration / 1000;
$formData.elevation_gain = totals.elevationGain;
$formData.elevation_loss = totals.elevationLoss;
}
function updateTrailOnMap() { function updateTrailOnMap() {
mapTrail = [$formData as Trail]; mapTrail = [$formData as Trail];
} }
@@ -1155,16 +1150,16 @@
function undoRouteEdit() { function undoRouteEdit() {
undo(); undo();
updateTrailWithRouteData();
clearAnchors(); clearAnchors();
initRouteAnchors(valhallaStore.route, true); initRouteAnchors(valhallaStore.route, true);
updateTrailWithRouteData();
} }
function redoRouteEdit() { function redoRouteEdit() {
redo(); redo();
updateTrailWithRouteData();
clearAnchors(); clearAnchors();
initRouteAnchors(valhallaStore.route, true); initRouteAnchors(valhallaStore.route, true);
updateTrailWithRouteData();
} }
</script> </script>
@@ -1208,7 +1203,13 @@
<button <button
class="btn-primary" class="btn-primary"
type="button" type="button"
onclick={drawingActive ? stopDrawing : startDrawing} onclick={async () => {
if (drawingActive) {
await stopDrawing();
} else {
startDrawing();
}
}}
> >
{$formData.expand?.gpx_data {$formData.expand?.gpx_data
? drawingActive ? drawingActive