surface SMTP delivery failures and add interactive rotor compass target
This commit is contained in:
@@ -11,6 +11,7 @@ let activationWatchInFlight = false;
|
||||
let activationPending = false;
|
||||
let remainingUsageTimer = null;
|
||||
let resumeRefreshInFlight = false;
|
||||
let rotorCompassDragPointerId = null;
|
||||
|
||||
const state = {
|
||||
user: null,
|
||||
@@ -716,6 +717,51 @@ function bindEvents() {
|
||||
await setOpenWebRxRotor();
|
||||
});
|
||||
}
|
||||
if (els.rotorCompass) {
|
||||
els.rotorCompass.addEventListener("pointerdown", (event) => {
|
||||
if (!els.rotorTarget || els.rotorTarget.disabled) {
|
||||
return;
|
||||
}
|
||||
if (event.pointerType === "mouse" && event.button !== 0) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
rotorCompassDragPointerId = event.pointerId;
|
||||
if (typeof els.rotorCompass.setPointerCapture === "function") {
|
||||
try {
|
||||
els.rotorCompass.setPointerCapture(event.pointerId);
|
||||
} catch {
|
||||
// ignore pointer capture errors
|
||||
}
|
||||
}
|
||||
els.rotorCompass.classList.add("is-dragging");
|
||||
updateRotorTargetFromPointerEvent(event);
|
||||
});
|
||||
els.rotorCompass.addEventListener("pointermove", (event) => {
|
||||
if (rotorCompassDragPointerId !== event.pointerId) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
updateRotorTargetFromPointerEvent(event);
|
||||
});
|
||||
const stopRotorCompassDrag = (event) => {
|
||||
if (rotorCompassDragPointerId !== event.pointerId) {
|
||||
return;
|
||||
}
|
||||
if (typeof els.rotorCompass.releasePointerCapture === "function") {
|
||||
try {
|
||||
els.rotorCompass.releasePointerCapture(event.pointerId);
|
||||
} catch {
|
||||
// ignore pointer capture errors
|
||||
}
|
||||
}
|
||||
rotorCompassDragPointerId = null;
|
||||
els.rotorCompass.classList.remove("is-dragging");
|
||||
};
|
||||
els.rotorCompass.addEventListener("pointerup", stopRotorCompassDrag);
|
||||
els.rotorCompass.addEventListener("pointercancel", stopRotorCompassDrag);
|
||||
els.rotorCompass.addEventListener("lostpointercapture", stopRotorCompassDrag);
|
||||
}
|
||||
if (els.openwebrxBandSetBtn) {
|
||||
els.openwebrxBandSetBtn.addEventListener("click", async () => {
|
||||
await setOpenWebRxBand();
|
||||
@@ -2031,6 +2077,43 @@ async function setOpenWebRxRotor() {
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeCompassAzimuth(value) {
|
||||
return ((Number(value) % 360) + 360) % 360;
|
||||
}
|
||||
|
||||
function rotorTargetBounds() {
|
||||
const rotor = state.openWebRx && state.openWebRx.rotor ? state.openWebRx.rotor : null;
|
||||
const min = rotor && Number.isFinite(Number(rotor.min)) ? Number(rotor.min) : 0;
|
||||
const max = rotor && Number.isFinite(Number(rotor.max)) ? Number(rotor.max) : 360;
|
||||
return {
|
||||
min: Math.min(min, max),
|
||||
max: Math.max(min, max)
|
||||
};
|
||||
}
|
||||
|
||||
function updateRotorTargetFromPointerEvent(event) {
|
||||
if (!els.rotorCompass || !els.rotorTarget) {
|
||||
return;
|
||||
}
|
||||
const rect = els.rotorCompass.getBoundingClientRect();
|
||||
const centerX = rect.left + rect.width / 2;
|
||||
const centerY = rect.top + rect.height / 2;
|
||||
const pointerX = Number(event.clientX);
|
||||
const pointerY = Number(event.clientY);
|
||||
if (!Number.isFinite(pointerX) || !Number.isFinite(pointerY)) {
|
||||
return;
|
||||
}
|
||||
const dx = pointerX - centerX;
|
||||
const dy = pointerY - centerY;
|
||||
if (Math.abs(dx) < 0.5 && Math.abs(dy) < 0.5) {
|
||||
return;
|
||||
}
|
||||
const azimuth = normalizeCompassAzimuth((Math.atan2(dx, -dy) * 180) / Math.PI);
|
||||
const bounds = rotorTargetBounds();
|
||||
const clamped = Math.min(bounds.max, Math.max(bounds.min, Math.round(azimuth)));
|
||||
els.rotorTarget.value = String(clamped);
|
||||
}
|
||||
|
||||
function renderRotorState() {
|
||||
if (!els.rotorCurrent) {
|
||||
return;
|
||||
|
||||
@@ -204,7 +204,7 @@
|
||||
<button type="button" class="ghost-btn" data-azimuth="315">NW</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="rotorCompass" class="rotor-compass" aria-label="Rotor Kompass">
|
||||
<div id="rotorCompass" class="rotor-compass" aria-label="Rotor Kompass" title="Mit Maus oder Touch den Ziel-Azimut waehlen">
|
||||
<span class="rotor-mark rotor-mark-n">0</span>
|
||||
<span class="rotor-mark rotor-mark-e">90</span>
|
||||
<span class="rotor-mark rotor-mark-s">180</span>
|
||||
|
||||
@@ -510,6 +510,13 @@ button:disabled {
|
||||
background: radial-gradient(circle at 35% 30%, rgba(255,255,255,0.1), rgba(15,23,42,0.88) 65%);
|
||||
box-shadow: inset 0 0 0 1px rgba(255,255,255,0.05);
|
||||
flex: 0 0 auto;
|
||||
cursor: crosshair;
|
||||
touch-action: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.rotor-compass.is-dragging {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.rotor-mark {
|
||||
|
||||
Reference in New Issue
Block a user