mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +00:00
refactor(settings): remove redundant Animations 3-state setting (#495)
* refactor(settings): remove redundant Animations 3-state setting under Seekbar Style The `animationMode` setting (Full / Reduced / Static) duplicated work the perf-flag system and OS-level reduced-motion preference already covered: - `perfFlags.disableMarqueeScroll` already kills marquee scrolling on demand, replacing what `static` mode used to gate. - The `data-perf-disable-animations` html-level switch already strips every `*` animation, replacing what `static` mode used to do globally. - `@media (prefers-reduced-motion: reduce)` honours the OS setting for every user that asked for it via system preferences. - The 30 fps cap that `reduced` mode applied to the seekbar wave was better served by per-feature perf toggles cucadmuh added later. Removed: - `AnimationMode` type, `animationMode` field + setter from auth store. - Settings UI block (3 buttons + hint text) under Appearance > Seekbar Style. - `animationMode === 'static'` short-circuit in WaveformSeek's rAF effect; `isReduced` skip-every-other-frame logic; `static`-checks in `drawNow` / `needsDirectDraw`. - `animationMode !== 'static'` guard and `data-anim-mode` attribute in MarqueeText. - `[data-anim-mode="static"]` and `[data-anim-mode="reduced"]` rules in layout.css. - Seven i18n keys (animationMode + 6 variants) across all eight locales. Migration: the persist layer strips `animationMode` (and the legacy `reducedAnimations` boolean predecessor) so anyone who had `'reduced'` or `'static'` selected silently lands on the former `'full'` path on first launch after upgrade. No user-facing prompt — the missing setting just stops existing. cucadmuh's PR #472 (FPS overlay), #476 (preview-freeze main seekbar, sleep-recovery hooks, card-hover removal) and #486 (interpolation anchor reset on resume) are all preserved untouched — they live in separate effects / files and were not driven by `animationMode`. * docs(changelog): add Removed section for animationMode setting (PR #495) * docs(changelog): refine animationMode removal rationale (drop prefers-reduced-motion overstatement)
This commit is contained in:
committed by
GitHub
parent
ba73649360
commit
ddb1f29af9
@@ -1,5 +1,4 @@
|
||||
import React, { useRef, useState, useEffect, useCallback } from 'react';
|
||||
import { useAuthStore } from '../store/authStore';
|
||||
import { usePerfProbeFlags } from '../utils/perfFlags';
|
||||
|
||||
interface Props {
|
||||
@@ -13,7 +12,6 @@ export default function MarqueeText({ text, className, style, onClick }: Props)
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const textRef = useRef<HTMLSpanElement>(null);
|
||||
const [scrollAmount, setScrollAmount] = useState(0);
|
||||
const animationMode = useAuthStore(s => s.animationMode);
|
||||
const perfFlags = usePerfProbeFlags();
|
||||
|
||||
const measure = useCallback(() => {
|
||||
@@ -34,9 +32,7 @@ export default function MarqueeText({ text, className, style, onClick }: Props)
|
||||
return () => ro.disconnect();
|
||||
}, [text, measure]);
|
||||
|
||||
// In `static` animation mode the marquee never scrolls — overflowing text
|
||||
// is truncated with an ellipsis (handled by CSS via data-anim-mode).
|
||||
const shouldScroll = scrollAmount > 0 && animationMode !== 'static' && !perfFlags.disableMarqueeScroll;
|
||||
const shouldScroll = scrollAmount > 0 && !perfFlags.disableMarqueeScroll;
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -44,7 +40,6 @@ export default function MarqueeText({ text, className, style, onClick }: Props)
|
||||
className={`marquee-wrap${className ? ` ${className}` : ''}`}
|
||||
style={style}
|
||||
onClick={onClick}
|
||||
data-anim-mode={animationMode}
|
||||
>
|
||||
<span
|
||||
ref={textRef}
|
||||
|
||||
@@ -967,14 +967,11 @@ export default function WaveformSeek({ trackId }: Props) {
|
||||
const waveformBins = usePlayerStore(s => s.waveformBins);
|
||||
const duration = usePlayerStore(s => s.currentTrack?.duration ?? 0);
|
||||
const seekbarStyle = useAuthStore(s => s.seekbarStyle);
|
||||
const animationMode = useAuthStore(s => s.animationMode);
|
||||
|
||||
// Ref so the subscription callback (closed over at mount) can read the
|
||||
// current style without stale-closure issues.
|
||||
const styleRef = useRef(seekbarStyle);
|
||||
styleRef.current = seekbarStyle;
|
||||
const animationModeRef = useRef(animationMode);
|
||||
animationModeRef.current = animationMode;
|
||||
|
||||
useEffect(() => {
|
||||
if (!trackId) {
|
||||
@@ -1096,10 +1093,8 @@ export default function WaveformSeek({ trackId }: Props) {
|
||||
visualProgressRef.current = visualTargetProgressRef.current;
|
||||
}
|
||||
// Static styles always redraw on progress; animated styles let the rAF
|
||||
// loop drive paints. In `static` animation mode we skip the rAF loop
|
||||
// entirely, so animated styles also need to repaint here on every tick.
|
||||
const drawNow =
|
||||
!ANIMATED_STYLES.has(styleRef.current) || animationModeRef.current === 'static';
|
||||
// loop drive paints.
|
||||
const drawNow = !ANIMATED_STYLES.has(styleRef.current);
|
||||
if (drawNow) {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
@@ -1137,28 +1132,14 @@ export default function WaveformSeek({ trackId }: Props) {
|
||||
duration,
|
||||
]);
|
||||
|
||||
// rAF loop — animated styles only, and only in `full`/`reduced` mode.
|
||||
// In `static` mode the loop is skipped entirely; the imperative progress
|
||||
// subscription (~2 Hz audio heartbeat) handles repaints, so the seekbar
|
||||
// updates a couple of times per second with no wave animation.
|
||||
// rAF loop — animated styles only.
|
||||
useEffect(() => {
|
||||
if (!ANIMATED_STYLES.has(seekbarStyle)) return;
|
||||
if (animationMode === 'static') {
|
||||
// Repaint once on entry so the canvas reflects current progress
|
||||
// without any wave morph and stays put until the next heartbeat.
|
||||
const canvas = canvasRef.current;
|
||||
if (canvas) {
|
||||
animStateRef.current = makeAnimState();
|
||||
drawSeekbar(canvas, seekbarStyle, heightsRef.current, progressRef.current, bufferedRef.current, animStateRef.current);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
animStateRef.current = makeAnimState();
|
||||
let rafId: number | null = null;
|
||||
let pollId: number | null = null;
|
||||
let skip = false;
|
||||
const stop = () => {
|
||||
if (rafId !== null) {
|
||||
cancelAnimationFrame(rafId);
|
||||
@@ -1177,22 +1158,13 @@ export default function WaveformSeek({ trackId }: Props) {
|
||||
}, 400);
|
||||
return;
|
||||
}
|
||||
// 30 fps cap in `reduced` mode: skip every other rAF, advance
|
||||
// animation time by a doubled delta so wave speed stays the same.
|
||||
const isReduced = animationModeRef.current === 'reduced';
|
||||
if (isReduced && skip) {
|
||||
skip = false;
|
||||
rafId = requestAnimationFrame(tick);
|
||||
return;
|
||||
}
|
||||
skip = isReduced;
|
||||
animStateRef.current.time += isReduced ? 0.032 : 0.016;
|
||||
animStateRef.current.time += 0.016;
|
||||
drawSeekbar(canvas, seekbarStyle, heightsRef.current, progressRef.current, bufferedRef.current, animStateRef.current);
|
||||
rafId = requestAnimationFrame(tick);
|
||||
};
|
||||
tick();
|
||||
return () => stop();
|
||||
}, [seekbarStyle, animationMode]);
|
||||
}, [seekbarStyle]);
|
||||
|
||||
// Smoothly advance progress between sparse transport ticks.
|
||||
// Preview pauses main sink in Rust while UI `isPlaying` may still be true.
|
||||
@@ -1267,8 +1239,7 @@ export default function WaveformSeek({ trackId }: Props) {
|
||||
: currentVisual + delta * smoothing;
|
||||
visualProgressRef.current = nextVisualProgress;
|
||||
progressRef.current = nextVisualProgress;
|
||||
const needsDirectDraw =
|
||||
!ANIMATED_STYLES.has(styleRef.current) || animationModeRef.current === 'static';
|
||||
const needsDirectDraw = !ANIMATED_STYLES.has(styleRef.current);
|
||||
if (needsDirectDraw && now - lastPaintAt >= INTERPOLATION_PAINT_MIN_MS) {
|
||||
const canvas = canvasRef.current;
|
||||
if (canvas) {
|
||||
|
||||
Reference in New Issue
Block a user