fix: restore audio refactor + features lost in #419 squash-merge (#429)

The squash-merge of PR #419 was performed against an outdated PR base
that predated several main-side refactors and features. The resulting
squash inadvertently re-introduced files that had already been removed
(`src-tauri/src/audio.rs` monolith, `app-icon.png`) and reverted main's
content for ~20 files (`src-tauri/src/lib.rs` decompose, `src/App.tsx`
animation-pause, `src/components/AlbumRow.tsx` headerExtra, etc).

This commit:

* Restores all collateral-damage files to their pre-#419 main state
  (5662dafe), including the audio module split, lib decompose,
  Cargo.toml `windows` dep, animation-pause-on-blur logic, and
  `reducedAnimations` toggle plumbing in WaveformSeek/Settings.
* Keeps the genuine #419 work intact: tri-state duration toggle,
  position counter, persistent Now Playing collapse, animated EQ
  indicator (in QueuePanel.tsx, 8 locales, authStore, components.css).
* Merges authStore.ts so both `reducedAnimations` (from #426) and
  `queueNowPlayingCollapsed` (from #419) coexist.
* Adds the `.eq-bars.paused` CSS rule manually since components.css
  needed a 5662dafe base + the single #419 addition.
* Fixes a latent type error in OverlayScrollArea.tsx (`useRef<T>(null)`
  is `RefObject<T>` / read-only under current `@types/react`; widened to
  `useRef<T | null>(null)` so the existing `wrapRef.current = el`
  assignment compiles).

Verified locally with `cargo check` and `npm run build` — both green.
This commit is contained in:
Frank Stellmacher
2026-05-02 22:01:51 +02:00
committed by GitHub
parent 18b4a982ef
commit e44e6dcdf4
23 changed files with 1286 additions and 9912 deletions
+46 -2
View File
@@ -1866,7 +1866,27 @@
transform: translateX(0.5px);
}
.playlist-suggestion-preview-btn.is-previewing .playlist-suggestion-preview-ring-progress {
/* Loading state: the engine is still downloading/decoding/seeking. A short
rotating arc (~25% of the circumference) signals "pending" without
pretending to be progress. 150 ms delay suppresses the spinner for
small/cached files where audio starts almost instantly. */
.playlist-suggestion-preview-btn.is-previewing:not(.audio-started) .playlist-suggestion-preview-ring-progress {
/* circumference = 2π × 10.5 ≈ 65.97 → 25% arc + 75% gap */
stroke-dasharray: 16.5 49.5;
stroke-dashoffset: 0;
animation: playlist-preview-loading 1.1s linear infinite;
animation-delay: 150ms;
}
@keyframes playlist-preview-loading {
from { stroke-dashoffset: 0; }
to { stroke-dashoffset: -65.97; }
}
/* Animation runs only after `audio-started` is added i.e. once the engine
emitted `audio:preview-start` for this track. Prevents the ring from
sprinting ahead of audio during the engine's download/decode/seek warmup. */
.playlist-suggestion-preview-btn.audio-started .playlist-suggestion-preview-ring-progress {
animation: playlist-preview-progress var(--preview-duration, 30s) linear forwards;
}
@@ -2492,6 +2512,27 @@ html[data-track-previews-randommix="off"] [data-preview-loc="randomMix"] .pl
stroke-linecap: round;
stroke-dasharray: 100;
stroke-dashoffset: 100;
}
/* Loading spinner same logic as the tracklist ring above. The SVG uses
pathLength="100", so the circumference is normalised: 25 unit arc + 75
unit gap, with the offset rolling from 0 to -100. */
.player-bar.is-previewing:not(.audio-started) .player-btn-preview-ring-progress {
stroke-dasharray: 25 75;
stroke-dashoffset: 0;
animation: player-preview-loading 1.1s linear infinite;
animation-delay: 150ms;
}
@keyframes player-preview-loading {
from { stroke-dashoffset: 0; }
to { stroke-dashoffset: -100; }
}
/* Animation gated on the player-bar `audio-started` flag (set after the
engine emits `audio:preview-start`). Same rationale as the tracklist
preview ring above. */
.player-bar.audio-started .player-btn-preview-ring-progress {
animation: player-preview-progress var(--preview-duration, 30s) linear forwards;
}
@@ -11061,7 +11102,10 @@ html[data-app-hidden="true"] *::before,
html[data-app-hidden="true"] *::after,
html[data-psy-native-hidden="true"] *,
html[data-psy-native-hidden="true"] *::before,
html[data-psy-native-hidden="true"] *::after {
html[data-psy-native-hidden="true"] *::after,
html[data-app-blurred="true"] *,
html[data-app-blurred="true"] *::before,
html[data-app-blurred="true"] *::after {
animation-play-state: paused !important;
}