diff --git a/assets/css/radio.css b/assets/css/radio.css index 15bdcfe..5c631f4 100644 --- a/assets/css/radio.css +++ b/assets/css/radio.css @@ -187,7 +187,13 @@ audio[controls] { width: 100%; outline: 0; } } .lyrics[hidden] { display: none; } /* [hidden] must beat position:absolute rule specificity */ -.lyrics-line { padding: 4px 0; opacity: .55; transition: opacity .2s ease, color .2s ease; } +.lyrics-line { + display: block; width: 100%; text-align: left; + background: none; border: none; margin: 0; padding: 4px 0; + font: inherit; color: inherit; cursor: pointer; + opacity: .55; transition: opacity .2s ease, color .2s ease; +} +.lyrics-line:hover, .lyrics-line:focus-visible { opacity: .85; outline: 0; } .lyrics-line.current { opacity: 1; font-weight: 700; } .lyrics-sync { diff --git a/assets/js/player.js b/assets/js/player.js index 4e66cec..fe2031e 100644 --- a/assets/js/player.js +++ b/assets/js/player.js @@ -442,6 +442,21 @@ }); } + // Click a line to say "this is playing right now" — re-anchors the karaoke + // clock to that line, which is how we recover from loading mid-song (we + // have no reliable elapsed time on most providers) or from drift building + // up over a long track. The buffering-delay nudge above is left as-is. + if (el.lyricsLines) { + el.lyricsLines.addEventListener('click', function (e) { + var btn = e.target.closest('.lyrics-line'); + if (!btn) return; + var line = syncedLines.filter(function (l) { return l.el === btn; })[0]; + if (!line) return; + trackStartedAt = Date.now() + lyricsOffsetMs - line.time * 1000; + startKaraoke(); + }); + } + function loadLyrics(track) { if (!CFG.lyricsEnabled || !el.lyricsToggle) return; el.lyricsToggle.hidden = true; @@ -460,11 +475,12 @@ if (!res.found || !res.lyrics || !el.lyricsLines) return; if (res.synced && res.synced.length) { syncedLines = res.synced.map(function (l) { - var div = document.createElement('div'); - div.className = 'lyrics-line'; - div.textContent = l.text; - el.lyricsLines.appendChild(div); - return { time: l.time, el: div }; + var btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'lyrics-line'; + btn.textContent = l.text; + el.lyricsLines.appendChild(btn); + return { time: l.time, el: btn }; }); if (el.lyricsSync) el.lyricsSync.hidden = false; if (el.lyrics && !el.lyrics.hidden) startKaraoke();