perf: reduce CPU usage and unify next-track buffering settings

- Throttle audio:progress from 100ms to 500ms; WaveformSeek and
  FsSeekbar use imperative DOM updates instead of React re-renders
- Fix all usePlayerStore() calls without selectors across pages and
  components (useShallow / individual selectors throughout)
- Remove filter:blur and transform:scale from Hero, AlbumDetail and
  FullscreenPlayer backgrounds — eliminated expensive software
  compositing layers on WebKitGTK
- Replace translate3d with 2D translate in FS mesh and portrait
  animations; remove will-change:transform from mesh blobs
- Move Hot Cache section from Storage tab to Audio tab; group Preload
  and Hot Cache under a shared 'Next Track Buffering' section with a
  mutual-exclusivity note and auto-disable logic
- Add 'off' toggle to Preload (replaces Off button with toggle switch);
  enabling either method now automatically disables the other

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Psychotoxical
2026-04-10 13:38:33 +02:00
parent c9dfbcc19f
commit c49f6af38b
21 changed files with 398 additions and 271 deletions
+16 -31
View File
@@ -21,17 +21,7 @@
inset: 0;
background-size: cover;
background-position: center;
transition: transform 8s ease, opacity 0.8s ease, filter 0.8s ease;
transform: scale(1.05);
filter: blur(12px);
}
.hero:hover .hero-bg {
filter: blur(8px);
}
.hero:hover .hero-bg {
transform: scale(1);
transition: opacity 0.8s ease;
}
.hero-dots {
@@ -909,11 +899,8 @@
inset: 0;
background-size: cover;
background-position: center;
filter: blur(20px) brightness(0.6);
transform: scale(1.1);
/* Hide blur edges */
z-index: 0;
opacity: 0.8;
opacity: 0.35;
transition: opacity var(--transition-slow);
}
@@ -3014,23 +3001,22 @@
to { transform: translateY(0); opacity: 1; }
}
/* ── Animated dark mesh — GPU-only: only transform3d, no scale, real divs for will-change ── */
@keyframes mesh-aura-a {
0% { transform: translate3d(0, 0, 0); }
33% { transform: translate3d(5%, -6%, 0); }
66% { transform: translate3d(-3%, 2%, 0); }
100% { transform: translate3d(0, 0, 0); }
0% { transform: translate(0, 0 ); }
33% { transform: translate(5%, -6% ); }
66% { transform: translate(-3%, 2% ); }
100% { transform: translate(0, 0 ); }
}
@keyframes mesh-aura-b {
0% { transform: translate3d(0, 0, 0); }
50% { transform: translate3d(-6%, 5%, 0); }
100% { transform: translate3d(0, 0, 0); }
0% { transform: translate(0, 0 ); }
50% { transform: translate(-6%, 5% ); }
100% { transform: translate(0, 0 ); }
}
@keyframes portrait-drift {
0%, 100% { transform: translate3d(0, 0, 0); }
50% { transform: translate3d(0, -10px, 0); }
0%, 100% { transform: translateY(0 ); }
50% { transform: translateY(-10px); }
}
.fs-mesh-bg {
@@ -3042,12 +3028,11 @@
pointer-events: none;
}
/* Blobs are real divs so will-change: transform applies (pseudo-elements can't have it) */
/* Blobs are real divs — no will-change/filter to avoid software compositing layers */
.fs-mesh-blob {
position: absolute;
border-radius: 50%;
pointer-events: none;
will-change: transform;
}
.fs-mesh-blob-a {
@@ -3058,8 +3043,8 @@
bottom: -35%;
background: radial-gradient(ellipse,
color-mix(in srgb, var(--dynamic-fs-accent, var(--accent)), transparent 86%) 0%,
transparent 65%);
filter: blur(55px);
color-mix(in srgb, var(--dynamic-fs-accent, var(--accent)), transparent 96%) 45%,
transparent 70%);
animation: mesh-aura-a 26s ease-in-out infinite;
animation-delay: 350ms;
transition: background 400ms ease-in-out;
@@ -3072,8 +3057,8 @@
top: -25%;
background: radial-gradient(ellipse,
color-mix(in srgb, var(--dynamic-fs-accent, var(--accent)), transparent 92%) 0%,
transparent 65%);
filter: blur(65px);
color-mix(in srgb, var(--dynamic-fs-accent, var(--accent)), transparent 98%) 45%,
transparent 70%);
animation: mesh-aura-b 20s ease-in-out infinite;
animation-delay: 350ms;
transition: background 400ms ease-in-out;