Multiple improvements
This commit is contained in:
@@ -1,18 +1,22 @@
|
||||
globalThis.Wegwichtel ??= {};
|
||||
(function (ns) {
|
||||
'use strict';
|
||||
const INTERVAL_MS = 30000;
|
||||
const INTERVAL_MS = 120000;
|
||||
let id = null;
|
||||
let editingId = null;
|
||||
let status = 'idle';
|
||||
let timer = null;
|
||||
let generation = 0;
|
||||
let pending = false;
|
||||
let pendingGeneration = null;
|
||||
let enabled = false;
|
||||
let manualGeneration = 0;
|
||||
let message = '';
|
||||
let manualFields = [];
|
||||
let lastPosition = null;
|
||||
|
||||
function render() {
|
||||
const toggle = document.getElementById('route-recording-toggle');
|
||||
if (toggle) { toggle.checked = enabled; toggle.setAttribute('aria-checked', String(enabled)); }
|
||||
const control = document.getElementById('route-recording-control');
|
||||
if (!control) return;
|
||||
control.hidden = status === 'idle';
|
||||
@@ -21,9 +25,9 @@ globalThis.Wegwichtel ??= {};
|
||||
}
|
||||
|
||||
async function sample() {
|
||||
if (pending || status !== 'recording') return;
|
||||
pending = true;
|
||||
if (pendingGeneration === generation || status !== 'recording') return;
|
||||
const currentGeneration = generation;
|
||||
pendingGeneration = currentGeneration;
|
||||
try {
|
||||
let position;
|
||||
try { position = await ns.Geo.current({ maximumAge: 0 }); }
|
||||
@@ -40,7 +44,7 @@ globalThis.Wegwichtel ??= {};
|
||||
ns.StorageUsage?.reportError(error);
|
||||
message = ns.I18n.t('recorder.save-error');
|
||||
} finally {
|
||||
pending = false;
|
||||
if (pendingGeneration === currentGeneration) pendingGeneration = null;
|
||||
render();
|
||||
}
|
||||
}
|
||||
@@ -69,6 +73,7 @@ globalThis.Wegwichtel ??= {};
|
||||
}
|
||||
|
||||
function stop() {
|
||||
enabled = false;
|
||||
clearTimer();
|
||||
id = null;
|
||||
lastPosition = null;
|
||||
@@ -78,6 +83,7 @@ globalThis.Wegwichtel ??= {};
|
||||
}
|
||||
|
||||
function start(routeId) {
|
||||
enabled = true;
|
||||
lastPosition = null;
|
||||
id = String(routeId);
|
||||
editingId = id;
|
||||
@@ -85,16 +91,46 @@ globalThis.Wegwichtel ??= {};
|
||||
}
|
||||
|
||||
function beginEditing(routeId) {
|
||||
if (editingId === String(routeId)) return;
|
||||
stop();
|
||||
start(routeId);
|
||||
const nextId = String(routeId);
|
||||
if (editingId === nextId) return;
|
||||
if (editingId !== null) endEditing();
|
||||
editingId = nextId;
|
||||
if (enabled) { id = editingId; resume(); }
|
||||
render();
|
||||
}
|
||||
|
||||
function setEnabled(value) {
|
||||
if (!value) { stop(); return; }
|
||||
enabled = true;
|
||||
if (editingId) { id = editingId; resume(); }
|
||||
render();
|
||||
}
|
||||
|
||||
function endEditing() {
|
||||
editingId = null;
|
||||
manualGeneration += 1;
|
||||
stop();
|
||||
}
|
||||
|
||||
async function fillCurrentLocation(field, button, notice) {
|
||||
if (button.disabled) return;
|
||||
const currentGeneration = manualGeneration;
|
||||
button.disabled = true;
|
||||
notice.textContent = ns.I18n.t('recorder.locating');
|
||||
try {
|
||||
const position = await ns.Geo.current({ maximumAge: 0 });
|
||||
if (currentGeneration !== manualGeneration || !manualFields.includes(field)) return;
|
||||
if (!Number.isFinite(position.lat) || !Number.isFinite(position.lon) || Math.abs(position.lat) > 90 || Math.abs(position.lon) > 180) throw new Error('Invalid location');
|
||||
field.lat.value = String(position.lat);
|
||||
field.lon.value = String(position.lon);
|
||||
notice.textContent = ns.I18n.t('recorder.location-set');
|
||||
} catch {
|
||||
if (currentGeneration === manualGeneration && manualFields.includes(field)) notice.textContent = ns.I18n.t('recorder.location-error');
|
||||
} finally {
|
||||
button.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
function addPositionField(position = {}, index = null) {
|
||||
const container = document.getElementById('editor-recorded-positions');
|
||||
if (!container) return;
|
||||
@@ -114,13 +150,30 @@ globalThis.Wegwichtel ??= {};
|
||||
row.appendChild(label); row.appendChild(input);
|
||||
fields[key] = input;
|
||||
}
|
||||
manualFields.push({ index, original: position, ...fields });
|
||||
const field = { index, original: position, ...fields };
|
||||
manualFields.push(field);
|
||||
const button = document.createElement('button');
|
||||
button.type = 'button';
|
||||
button.className = 'current-location-button';
|
||||
button.setAttribute('aria-label', ns.I18n.t('recorder.use-location'));
|
||||
button.title = ns.I18n.t('recorder.use-location');
|
||||
const icon = document.createElement('img');
|
||||
icon.src = '/images/icons/current-location.svg';
|
||||
icon.alt = '';
|
||||
button.appendChild(icon);
|
||||
const notice = document.createElement('p');
|
||||
notice.className = 'editor-muted';
|
||||
notice.setAttribute('aria-live', 'polite');
|
||||
button.addEventListener('click', () => { void fillCurrentLocation(field, button, notice); });
|
||||
row.appendChild(button);
|
||||
row.appendChild(notice);
|
||||
container.appendChild(row);
|
||||
}
|
||||
|
||||
function renderPoints(gpx) {
|
||||
const container = document.getElementById('editor-recorded-positions');
|
||||
if (!container) return;
|
||||
manualGeneration += 1;
|
||||
container.replaceChildren();
|
||||
manualFields = [];
|
||||
ns.LocalRoutes.recordedPositions(gpx).forEach(addPositionField);
|
||||
@@ -146,6 +199,10 @@ globalThis.Wegwichtel ??= {};
|
||||
|
||||
function bind() {
|
||||
globalThis.addEventListener?.('pagehide', endEditing);
|
||||
document.getElementById('route-recording-toggle')?.addEventListener('change', event => setEnabled(event.target.checked));
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
if (document.visibilityState === 'visible' && status === 'recording') void sample();
|
||||
});
|
||||
const activate = (elementId, action) => {
|
||||
const element = document.getElementById(elementId);
|
||||
element?.addEventListener('pointerup', event => {
|
||||
|
||||
Reference in New Issue
Block a user