diff --git a/web/frontend/index.html b/web/frontend/index.html index b298a54..7dd11dc 100644 --- a/web/frontend/index.html +++ b/web/frontend/index.html @@ -246,12 +246,19 @@ img { display: block; } } #player video { width: 100%; height: 100%; object-fit: contain; background: #000; cursor: pointer; } +/* **Die Fläche selbst nimmt keine Klicks entgegen, nur ihre Knöpfe.** + Sonst liegt sie über dem Bild und schluckt jeden Klick — und „ins Bild + tippen hält an" funktioniert genau dann nicht, wenn die Bedienung zu + sehen ist, also fast immer. */ .pl-chrome { position: absolute; inset: 0; opacity: 0; pointer-events: none; transition: opacity .25s ease; display: grid; grid-template-rows: auto 1fr auto; } -.pl-chrome.on { opacity: 1; pointer-events: auto; } +.pl-chrome.on { opacity: 1; } +.pl-chrome.on button, +.pl-chrome.on .pl-track, +.pl-chrome.on select { pointer-events: auto; } /* Zwei Verläufe statt einer Fläche: die Mitte bleibt frei, und genau dort ist das Bild. */ @@ -315,15 +322,18 @@ img { display: block; } beides unlesbar, und die Zahl ist die eigentliche Auskunft. */ #pl-back, #pl-fwd { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; } -.pl-scrub { display: flex; align-items: center; gap: var(--s-regular); } -.pl-scrub span { - font-size: 13px; color: var(--text-2); font-variant-numeric: tabular-nums; - min-width: 52px; +/* Wie in der App: der Regler über die **volle Breite**, die Zeiten darunter. + Nebeneinander gestellt nimmt er in der Mitte Platz weg und wirkt wie ein + Formularfeld zwischen zwei Beschriftungen. */ +.pl-times { + display: flex; justify-content: space-between; + margin-top: var(--s-tight); + font-size: 13px; color: rgba(255,255,255,.8); + font-variant-numeric: tabular-nums; } -.pl-scrub span:last-child { text-align: right; } .pl-track { - position: relative; flex: 1; height: 22px; cursor: pointer; + position: relative; width: 100%; height: 22px; cursor: pointer; display: flex; align-items: center; } .pl-track::before { @@ -341,14 +351,7 @@ img { display: block; } } .pl-track:hover i { transform: translateX(-50%) scale(1.25); } -.pl-tools { - display: flex; align-items: center; gap: var(--s-regular); - margin-top: var(--s-snug); -} .pl-spacer { flex: 1; } -.pl-tools input[type=range] { width: 92px; accent-color: var(--accent); } -.pl-rate { font-size: 13px; color: var(--text-2); display: flex; align-items: center; gap: var(--s-snug); } -.pl-rate .pick { width: auto; padding: 6px var(--s-regular); font-size: 13px; } /* Während geladen wird, treten die Transportknöpfe zurück: sie tun ohnehin nichts, und der Kreisel lag vorher genau hinter dem größten von ihnen. */ @@ -1600,6 +1603,9 @@ function openPlayer(item) { + + +
@@ -1609,18 +1615,11 @@ function openPlayer(item) {
-
+
+
0:00 -
–:--
-
- - - - - -
@@ -1715,20 +1714,29 @@ function openPlayer(item) { }; // --- Ton, Tempo, Vollbild --- - const vol = el2('pl-vol'); - vol.oninput = () => { v.volume = +vol.value; v.muted = +vol.value === 0; }; - el2('pl-mute').onclick = () => { - v.muted = !v.muted; - el2('pl-mute').innerHTML = icon(v.muted ? 'muted' : 'sound'); + const paintTon = () => { + el2('pl-mute').innerHTML = icon(v.muted || v.volume === 0 ? 'muted' : 'sound'); + el2('pl-mute').title = `Lautstärke ${Math.round(v.volume * 100)} %`; }; + el2('pl-mute').onclick = () => { v.muted = !v.muted; paintTon(); }; - const rate = el2('pl-rate'); - RATES.forEach((r) => { - const o = document.createElement('option'); - o.value = r; o.textContent = r === 1 ? 'Normal' : r + '×'; o.selected = r === P.rate; - rate.appendChild(o); - }); - rate.onchange = () => { v.playbackRate = +rate.value; }; + // Das Tempo als Liste wie Ton und Untertitel — ein Auswahlfeld mitten in + // der Bedienleiste war das einzige Bauteil, das nach Formular aussah. + el2('pl-speed').onclick = () => zeigeListe(el2('pl-speed'), 'Geschwindigkeit', + RATES.map((r) => ({ + text: r === 1 ? 'Normal' : r + '×', + gewaehlt: Math.abs(v.playbackRate - r) < 0.01, + waehlen: () => { v.playbackRate = r; closeMenu(); show(); }, + }))); + + // Lautstärke über das Mausrad auf dem Tonknopf und über die Pfeiltasten — + // ein Schieberegler in der Leiste steht in der App auch nicht. + el2('pl-mute').addEventListener('wheel', (e) => { + e.preventDefault(); + v.volume = Math.min(1, Math.max(0, v.volume - Math.sign(e.deltaY) * 0.05)); + v.muted = v.volume === 0; + paintTon(); + }, { passive: false }); el2('pl-full').onclick = () => document.fullscreenElement ? document.exitFullscreen() : layer.requestFullscreen?.(); @@ -1740,8 +1748,8 @@ function openPlayer(item) { ' ': () => toggle(), k: () => toggle(), ArrowLeft: () => { v.currentTime -= P.skipBackward; }, ArrowRight: () => { v.currentTime += P.skipForward; }, - ArrowUp: () => { v.volume = Math.min(1, v.volume + 0.1); vol.value = v.volume; }, - ArrowDown: () => { v.volume = Math.max(0, v.volume - 0.1); vol.value = v.volume; }, + ArrowUp: () => { v.volume = Math.min(1, v.volume + 0.1); paintTon(); }, + ArrowDown: () => { v.volume = Math.max(0, v.volume - 0.1); paintTon(); }, f: () => el2('pl-full').click(), Escape: () => close(), }; @@ -2068,6 +2076,7 @@ function streamURL(path, query) { const ICONS = { play: '', waveform: '', + speed: '', captions: '', captionsOn: '', check: '',