Compare commits

...

5 Commits

Author SHA1 Message Date
github-actions[bot] 7f9f9167c4 chore(nix): refresh lock + npmDepsHash for v1.45.0 (#457)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-04 22:23:19 +02:00
github-actions[bot] 21033e82f4 chore(release): finalize release version 1.45.0 2026-05-04 20:00:08 +00:00
github-actions[bot] c7407af05b chore(nix): refresh lock + npmDepsHash for v1.45.0-rc.6 (#455)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-04 21:08:17 +02:00
github-actions[bot] 159973fb16 chore(release): bump next channel to 1.45.0-rc.6 2026-05-04 18:53:32 +00:00
Frank Stellmacher 5913d20cc2 fix(lyrics): keep highlight + auto-scroll alive after tab switch (#454)
The track-change reset wiped lineRefs/wordRefs in its effect body, which
ran *after* the commit phase that just populated them on remount. The
tracker effect then saw an empty refs array, no-op'd the DOM update, but
still advanced prevActive — so every following progress tick early-returned
on `prev.line === lineIdx` and the highlight froze.

Track the previous track id in a ref and skip the reset on initial mount,
so refs only get cleared on an actual track change.
2026-05-04 20:47:15 +02:00
7 changed files with 21 additions and 14 deletions
Generated
+3 -3
View File
@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1776877367,
"narHash": "sha256-EHq1/OX139R1RvBzOJ0aMRT3xnWyqtHBRUBuO1gFzjI=",
"lastModified": 1777578337,
"narHash": "sha256-Ad49moKWeXtKBJNy2ebiTQUEgdLyvGmTeykAQ9xM+Z4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0726a0ecb6d4e08f6adced58726b95db924cef57",
"rev": "15f4ee454b1dce334612fa6843b3e05cf546efab",
"type": "github"
},
"original": {
+1 -1
View File
@@ -1,3 +1,3 @@
{
"npmDepsHash": "sha256-7mSqNSw7KApMERXzhW/Ta7j1wLf55mxBEf3pWs2aaic="
"npmDepsHash": "sha256-WXfc5WsypV2HdUTaZLDzPN9OdgLq18/hcJVvKCn3LTU="
}
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "psysonic",
"version": "1.45.0-dev",
"version": "1.45.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "psysonic",
"version": "1.45.0-dev",
"version": "1.45.0",
"dependencies": {
"@fontsource-variable/dm-sans": "^5.2.8",
"@fontsource-variable/figtree": "^5.2.10",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "psysonic",
"version": "1.45.0-dev",
"version": "1.45.0",
"private": true,
"scripts": {
"dev": "vite",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "psysonic"
version = "1.45.0-dev"
version = "1.45.0"
description = "Psysonic Desktop Music Player"
authors = []
license = ""
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Psysonic",
"version": "1.45.0-dev",
"version": "1.45.0",
"identifier": "dev.psysonic.player",
"build": {
"beforeDevCommand": "npm run dev",
+12 -5
View File
@@ -38,6 +38,7 @@ export default function LyricsPane({ currentTrack }: Props) {
const lineRefs = useRef<(HTMLDivElement | null)[]>([]);
const wordRefs = useRef<HTMLSpanElement[][]>([]);
const prevActive = useRef({ line: -1, word: -1 });
const prevTrackId = useRef<string | null | undefined>(undefined);
const isUserScroll = useRef(false);
const scrollTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
@@ -65,12 +66,18 @@ export default function LyricsPane({ currentTrack }: Props) {
}
}, [sidebarLyricsStyle]);
// Reset refs when track changes.
// Reset refs on actual track change. Skip the initial mount so we don't wipe
// the callback-refs that the commit phase just populated — that would leave
// the tracker effect with an empty lineRefs and freeze the highlight.
useEffect(() => {
lineRefs.current = [];
wordRefs.current = [];
prevActive.current = { line: -1, word: -1 };
scrollerRef.current?.jump(0);
const id = currentTrack?.id ?? null;
if (prevTrackId.current !== undefined && prevTrackId.current !== id) {
lineRefs.current = [];
wordRefs.current = [];
prevActive.current = { line: -1, word: -1 };
scrollerRef.current?.jump(0);
}
prevTrackId.current = id;
}, [currentTrack?.id]);
// Imperative tracker — subscribes directly to the store, zero React re-renders per tick.