overhaul gpx creation and usage
Sonarqube Scanner / Prepare environment (push) Successful in 8s
Sonarqube Scanner / Build and test (push) Failing after 22s
Sonarqube Scanner / SonarQube analysis (push) Skipped
Sonarqube Scanner / Deploy to Server (push) Successful in 6s

This commit is contained in:
Florian Zumpe
2026-10-03 12:40:26 +02:00
parent 1cb3977269
commit 171ea88d55
29 changed files with 969 additions and 344 deletions
+40 -26
View File
@@ -1,6 +1,10 @@
(function (ns, $) {
'use strict';
const DROPDOWN_ANIMATION_MS = 180;
let routeControlOpen = false;
let routeControlCloseTimer = null;
const state = {
routes: [],
localRoutes: [],
@@ -319,6 +323,9 @@
.prop('hidden', false)
.text(ns.I18n.t("app.pause-hint"));
showNavigation(ns.I18n.t("app.route-paused"), $('#navigation-distance').text() || '–');
$('#navigation-arrow').prop('hidden', true);
$('#route-navigation-arrow').prop('hidden', true);
$('#route-navigation-mode').text(ns.I18n.t('app.route-paused'));
updateRouteControls();
}
@@ -421,7 +428,7 @@
function poiMetrics(position) {
if (!position || !state.route?.pois?.length) return [];
const heading = effectiveHeading(position);
return state.route.pois.map(poi => {
return state.route.pois.filter(poi => Number.isFinite(poi.lat) && Number.isFinite(poi.lon)).map(poi => {
const distance = ns.Distance.meters(position, poi);
const bearing = ns.Distance.bearing(position, poi);
return {
@@ -498,49 +505,41 @@
: ns.I18n.t("app.next-station", { value1: metric.poi.title }),
`${distance} m`
);
$('#navigation-footer').attr(
$('#station-navigation').attr(
'aria-label',
ns.I18n.t("app.next-station-distance", { value1: metric.poi.title, value2: distance })
);
}
function showRoutePointNavigation(position, progress) {
const arrow = $('#route-navigation-arrow');
const mode = $('#route-navigation-mode');
if (!progress) {
$('#navigation-arrow').css('transform', 'rotate(0deg)');
showNavigation(ns.I18n.t("app.path.missing"), '–');
arrow.css('transform', 'rotate(0deg)').prop('hidden', true);
mode.text(ns.I18n.t('app.path.missing'));
return;
}
if (progress.reached) {
$('#navigation-arrow').css('transform', 'rotate(0deg)');
showNavigation(ns.I18n.t("app.destination-reached"), '0 m');
$('#navigation-footer').attr('aria-label', ns.I18n.t("app.destination-reached"));
arrow.css('transform', 'rotate(0deg)').prop('hidden', true);
mode.text(ns.I18n.t('app.destination-reached'));
return;
}
const bearing = ns.Distance.bearing(position, progress.target);
const heading = effectiveHeading(position);
const rotation = heading == null
? bearing
: ns.Distance.normalizeDegrees(bearing - heading);
const distance = Math.round(progress.distance);
$('#navigation-arrow').css('transform', `rotate(${rotation.toFixed(1)}deg)`);
showNavigation(
heading == null ? ns.I18n.t("app.next-path-point-north") : ns.I18n.t("app.next-path-point"),
`${distance} m`
);
$('#navigation-footer').attr(
'aria-label',
ns.I18n.t("app.next-path-point-distance", { value1: distance })
);
const rotation = heading == null ? bearing : ns.Distance.normalizeDegrees(bearing - heading);
arrow.prop('hidden', false).css('transform', `rotate(${rotation.toFixed(1)}deg)`);
mode.text(ns.I18n.t(heading == null ? 'app.next-path-point-north' : 'app.next-path-point'));
}
function updateNavigation(position) {
if (state.routeState !== 'running') return;
const progress = updateRouteProgress(position);
showRoutePointNavigation(position, progress);
const metrics = updatePoiIndicators(position);
const nextPoi = nearestPendingPoi(metrics);
$('#navigation-arrow').prop('hidden', !nextPoi);
if (nextPoi) showPoiNavigation(position, nextPoi);
else showRoutePointNavigation(position, progress);
else showNavigation(ns.I18n.t('recorder.no-station'), '–');
}
function updateHeading(heading) {
@@ -659,8 +658,23 @@
}
function setRouteControlOpen(open) {
$('#route-control-dropdown').prop('hidden', !open);
$('#route-control-button').attr('aria-expanded', String(open));
routeControlOpen = Boolean(open);
globalThis.clearTimeout(routeControlCloseTimer);
routeControlCloseTimer = null;
const dropdown = $('#route-control-dropdown');
$('#route-control-button').attr('aria-expanded', String(routeControlOpen));
if (routeControlOpen) {
dropdown.prop('hidden', false);
const nextFrame = globalThis.requestAnimationFrame ?? (callback => callback());
nextFrame(() => nextFrame(() => {
if (routeControlOpen) dropdown.addClass('is-open');
}));
} else {
dropdown.removeClass('is-open');
routeControlCloseTimer = globalThis.setTimeout(() => {
if (!routeControlOpen) dropdown.prop('hidden', true);
}, DROPDOWN_ANIMATION_MS);
}
}
async function selectRoute(source, id) {
@@ -718,7 +732,7 @@
});
activate('#route-control-button', function () {
setRouteControlOpen($('#route-control-dropdown').prop('hidden'));
setRouteControlOpen(!routeControlOpen);
});
activate('.route-control-actions #route-control-new', function () {
@@ -731,7 +745,7 @@
});
$(document).on('pointerup', event => {
if ($('#route-control-dropdown').prop('hidden')) return;
if (!routeControlOpen) return;
if ($(event.target).closest('.route-control').length) return;
setRouteControlOpen(false);
});