From 0d9481cae2223652e461f5b73775b3d01144a89d Mon Sep 17 00:00:00 2001 From: Thomas Date: Sun, 23 Aug 2026 12:53:07 +0200 Subject: [PATCH] Tag-Ansicht: pausierte Zeiten bleiben als Verlauf stehen (verschwinden nicht mehr) live-client loggt Pausen-Spannen (__pauseSpans: {s,e}), live.php reicht sie durch, renderLiveSummary zeichnet jede als bleibendes halbhohes Segment im Tag-Balken (offene/laufende Pause blinkt). Fallback fuer Sim-Pause via phase bleibt. Co-Authored-By: Claude Opus 4.8 --- App/assets/js/live-client.js | 12 ++++++++++++ App/php/api/live.php | 2 ++ App/teacher.html | 23 +++++++++++++++++++---- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/App/assets/js/live-client.js b/App/assets/js/live-client.js index 2ca703b..f8eca57 100644 --- a/App/assets/js/live-client.js +++ b/App/assets/js/live-client.js @@ -71,6 +71,8 @@ var sessionCapped = false; var paused = false; // Sim-Pause: friert activeMs ein (opt-in) var idleActive = false; // sichtbare Idle-Pause aktiv (Weiter-Overlay) + var pauseSpans = []; // Verlauf abgeschlossener Pausen {s,e} (ms-Epoch) + var curPauseStart = 0; // Beginn der laufenden Pause (0 = keine) function onInteraction() { lastInteractionAt = Date.now(); @@ -180,6 +182,10 @@ state.__capped = sessionCapped; state.__paused = paused || idleActive; state.__idlePaused = idleActive; + // Pausen-Verlauf für die Tag-Ansicht: abgeschlossene Spannen + laufende (offen). + state.__pauseSpans = curPauseStart + ? pauseSpans.concat([{ s: curPauseStart, e: Date.now() }]) + : pauseSpans.slice(); fetch(apiBase + '/live.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -239,10 +245,16 @@ function showIdlePause() { if (idleActive) return; idleActive = true; + curPauseStart = Date.now(); // Pausenbeginn merken (für den Tag-Verlauf) ensureIdleOverlay().style.display = 'flex'; } function resumeFromIdle() { idleActive = false; + if (curPauseStart) { + pauseSpans.push({ s: curPauseStart, e: Date.now() }); + if (pauseSpans.length > 30) pauseSpans.shift(); // Deckel gegen Wildwuchs + curPauseStart = 0; + } lastInteractionAt = Date.now(); lastTickAt = Date.now(); // kein Zeitsprung beim Fortsetzen if (idleOverlay) idleOverlay.style.display = 'none'; diff --git a/App/php/api/live.php b/App/php/api/live.php index eb9685e..ae5a023 100644 --- a/App/php/api/live.php +++ b/App/php/api/live.php @@ -373,6 +373,8 @@ if ($method === 'GET') { 'isLive' => true, 'paused' => $isPaused, 'activeUntilMs'=> ($activeUntil > $startMs && $activeUntil < $endMs) ? $activeUntil : 0, + // Pausen-Verlauf (bleibt im Tag-Balken stehen, auch nach dem Fortsetzen). + 'pauseSpans' => (isset($state['__pauseSpans']) && is_array($state['__pauseSpans'])) ? array_slice($state['__pauseSpans'], -30) : [], ]; $byStudent[$sid]['totalSec'] += $durSec; } diff --git a/App/teacher.html b/App/teacher.html index 1c4c648..bdb5a26 100644 --- a/App/teacher.html +++ b/App/teacher.html @@ -2282,12 +2282,27 @@ async function renderLiveSummary() { + 'white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;' + 'text-shadow:0 1px 1px rgba(0,0,0,.3);box-shadow:0 1px 2px rgba(0,0,0,.12)">' + inner + ''; - // Pausen-Schwanz: halbhoch, gedämpft, blinkt langsam — „läuft noch, aber gerade ruhig". - if (isPausedRun) { - var halfH = 9; + // Pausen im Verlauf: jede geloggte Pausen-Spanne bleibt als halbhohes, + // gedämpftes Segment im Balken stehen — auch nachdem die Schüler:in wieder + // weiterarbeitet. So sieht man, WANN und WIE LANGE pausiert wurde. + var spans = sess.pauseSpans || []; + var halfH = 9, halfTop = 5 + barH - halfH; + if (spans.length) { + spans.forEach(function(sp){ + if (!sp || !sp.s || !sp.e) return; + var a = _msToPct(sp.s), b = _msToPct(sp.e); + var w = Math.max(0.4, b - a); + var live = (Math.abs(sp.e - endMs) < 6000); // die offene (laufende) Pause blinkt + html += '
'; + }); + } else if (isPausedRun) { + // Fallback ohne geloggte Spannen (z. B. Sim-Pause via phase): aktueller Schwanz. var tailW = Math.max(0.6, _msToPct(endMs) - pctR); html += '
'; }