diff --git a/public/app.js b/public/app.js index 03114a9..23bb7ea 100755 --- a/public/app.js +++ b/public/app.js @@ -60,7 +60,7 @@ function switchToLogout() { function performLocalLogout() { loggedIn = false; stopArmedPolling(); - estopBtn.style.display = "none"; + hideEstopInstant(); iframe.src = ""; iframe.style.display = "none"; nav.innerHTML = ""; @@ -74,6 +74,41 @@ function performLocalLogout() { const POWER_STATUS_URL = '/api/power-status'; const ESTOP_URL = '/api/emergency-stop'; +let estopFadeTimer = null; +const ESTOP_FADE_MS = 10000; // 10s Ausblende-Dauer + +// Einblenden: zügig (Sicherheit – Button soll prompt da sein) +function showEstop() { + if (estopFadeTimer) { clearTimeout(estopFadeTimer); estopFadeTimer = null; } + estopBtn.style.transition = "opacity 0.3s ease, transform 0.1s ease"; + estopBtn.style.pointerEvents = "auto"; + estopBtn.style.display = "block"; + void estopBtn.offsetWidth; // Reflow erzwingen -> Transition startet sauber + estopBtn.style.opacity = "1"; +} + +// Ausblenden: langsam über 10s, danach display:none +function fadeOutEstop() { + // schon weg oder ein Fade läuft bereits? -> nichts tun (kein Neustart des Timers) + if (estopBtn.style.display === "none" || estopFadeTimer) return; + estopBtn.style.transition = "opacity " + (ESTOP_FADE_MS / 1000) + "s ease, transform 0.1s ease"; + estopBtn.style.pointerEvents = "none"; // während Ausblenden nicht mehr klickbar + estopBtn.style.opacity = "0"; + estopFadeTimer = setTimeout(() => { + estopBtn.style.display = "none"; + estopFadeTimer = null; + }, ESTOP_FADE_MS); +} + +// Sofort verstecken ohne Animation (z.B. Logout) +function hideEstopInstant() { + if (estopFadeTimer) { clearTimeout(estopFadeTimer); estopFadeTimer = null; } + estopBtn.style.transition = "none"; + estopBtn.style.pointerEvents = "none"; + estopBtn.style.opacity = "0"; + estopBtn.style.display = "none"; +} + async function updateArmedStatus() { console.log('[armed-check] GET', POWER_STATUS_URL); try { @@ -81,14 +116,14 @@ async function updateArmedStatus() { if (r.ok) { const data = await r.json(); console.log('[armed-check] response:', data); - estopBtn.style.display = data.armed ? "block" : "none"; + if (data.armed) showEstop(); else fadeOutEstop(); } else { - console.warn('[armed-check] HTTP', r.status, '– Button versteckt'); - estopBtn.style.display = "none"; + console.warn('[armed-check] HTTP', r.status, '– Button wird ausgeblendet'); + fadeOutEstop(); } } catch (e) { console.error('[armed-check] Fehler bei', POWER_STATUS_URL, '–', e.message); - estopBtn.style.display = "none"; + fadeOutEstop(); } } diff --git a/public/style.css b/public/style.css index 70cf131..347c5df 100755 --- a/public/style.css +++ b/public/style.css @@ -41,6 +41,7 @@ header { #emergency-stop { display: none; + opacity: 0; /* Startwert – Fade-Dauer wird per JS gesetzt */ position: relative; width: 78px; height: 78px;