Skip to content

Commit 098f778

Browse files
committed
fix(synced-lyrics): improve scroll stability with fallback index and fast-scroll on tab visible
1 parent 64947e2 commit 098f778

File tree

1 file changed

+38
-7
lines changed

1 file changed

+38
-7
lines changed

src/plugins/synced-lyrics/renderer/renderer.tsx

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,13 @@ export const LyricsRenderer = () => {
381381
setCurrentIndex(index);
382382
});
383383

384+
// when lyrics tab becomes visible again, open a short fast-scroll window
385+
createEffect(() => {
386+
if (isVisible()) {
387+
requestFastScroll(1500);
388+
}
389+
});
390+
384391
// scroll effect
385392
createEffect(() => {
386393
const visible = isVisible();
@@ -572,7 +579,31 @@ export const LyricsRenderer = () => {
572579
const idx = currentIndex();
573580
const lineEffect = config()?.lineEffect;
574581

575-
if (!data || !data.lines || idx < 0) return;
582+
if (!data || !data.lines) return;
583+
584+
// robust fallback if no line is detected as "current" yet
585+
let effIdx = idx;
586+
if (effIdx < 0) {
587+
const lines = data.lines;
588+
const containing = lines.findIndex((l) => {
589+
const start = l.timeInMs;
590+
const end = l.timeInMs + l.duration;
591+
return currentTimeMs >= start && currentTimeMs < end;
592+
});
593+
if (containing !== -1) {
594+
effIdx = containing;
595+
} else {
596+
let lastBefore = 0;
597+
for (let j = lines.length - 1; j >= 0; j--) {
598+
if (lines[j].timeInMs <= currentTimeMs) {
599+
lastBefore = j;
600+
break;
601+
}
602+
}
603+
effIdx = lastBefore;
604+
}
605+
}
606+
576607
const jumped =
577608
prevTimeForScroll >= 0 &&
578609
Math.abs(currentTimeMs - prevTimeForScroll) > 400;
@@ -583,20 +614,20 @@ export const LyricsRenderer = () => {
583614
) {
584615
const timeDelta = Math.abs(currentTimeMs - prevTimeForScroll);
585616
const lineDelta =
586-
prevIndexForFast >= 0 ? Math.abs(idx - prevIndexForFast) : 0;
617+
prevIndexForFast >= 0 ? Math.abs(effIdx - prevIndexForFast) : 0;
587618
if (timeDelta > 1500 || lineDelta >= 5) {
588619
requestFastScroll(1500);
589620
}
590621
}
591622
prevTimeForScroll = currentTimeMs;
592623

593624
const scrollOffset = scroller()?.scrollOffset ?? 0;
594-
if (idx === 0 && currentTimeMs > 2000 && !jumped && scrollOffset <= 1) {
625+
if (effIdx === 0 && currentTimeMs > 2000 && !jumped && scrollOffset <= 1) {
595626
return;
596627
}
597628

598629
if (lineEffect === 'enhanced') {
599-
const nextIdx = Math.min(idx + 1, data.lines.length - 1);
630+
const nextIdx = Math.min(effIdx + 1, data.lines.length - 1);
600631
const nextLine = data.lines[nextIdx];
601632

602633
if (nextLine) {
@@ -606,14 +637,14 @@ export const LyricsRenderer = () => {
606637

607638
if (timeUntilNextLine <= leadInTimeMs) {
608639
setScrollTargetIndex(nextIdx);
609-
prevIndexForFast = idx;
640+
prevIndexForFast = effIdx;
610641
return;
611642
}
612643
}
613644
}
614645

615-
prevIndexForFast = idx;
616-
setScrollTargetIndex(idx);
646+
prevIndexForFast = effIdx;
647+
setScrollTargetIndex(effIdx);
617648
});
618649

619650
return (

0 commit comments

Comments
 (0)