Refactor LuxsinAPI to correct firmware version comparison in boot sound settings; enhance useStrokeDrawAnimation hook to support path updates without replaying animation. Update EQPage to utilize new animation options for smoother transitions during EQ parameter edits.

This commit is contained in:
yangy
2026-05-18 17:21:00 +08:00
parent ba5f5d074a
commit edd677c79d
3 changed files with 28 additions and 12 deletions
+2 -2
View File
@@ -312,7 +312,7 @@ export class LuxsinAPI {
setCrossfeedEnable(enable: boolean) { return this.setSetting({ crossfeed_enable: enable ? 1 : 0 }); }
setXlrPolarity(reverse: boolean) { return this.setSetting({ xlr: reverse ? 1 : 0 }); }
setDacArc(earc: boolean) { return this.setSetting({ dacArc: earc ? 1 : 0 }); }
/** Boot volume level: 0 = default, 1..6 = -5..-30 dB, 7..10 = -35..-50 dB (firmware > 26). */
/** Boot volume level: 0 = default, 1..6 = -5..-30 dB, 7..10 = -35..-50 dB (firmware >= 26). */
setBootSound(level: number) {
return this.setSetting({ bootSound: Math.max(0, Math.min(10, Math.round(level))) });
}
@@ -335,7 +335,7 @@ export function parseFirmwareVersion(version: unknown): number {
/** Max `bootSound` index available for the current firmware. */
export function getBootSoundMaxIndex(firmwareVersion: number): number {
return firmwareVersion > 26 ? 10 : 6;
return firmwareVersion >= 26 ? 10 : 6;
}
/** Normalize `bootSound` from syncData (0 = default … 10 = -50 dB). */
+16 -2
View File
@@ -1,8 +1,9 @@
import { useEffect } from "react";
import { useEffect, useRef } from "react";
/**
* Reusable left-to-right SVG stroke draw animation.
* Pass `enabled=false` to disable and clear dash styles (e.g. while dragging).
* Pass `replayOnPathChange=false` to update the path in place without replaying the intro.
*/
export function useStrokeDrawAnimation(
pathRef: React.RefObject<SVGPathElement | null>,
@@ -11,11 +12,15 @@ export function useStrokeDrawAnimation(
enabled?: boolean;
durationMs?: number;
easing?: string;
/** When false, only the first draw runs; later `pathD` updates show immediately. */
replayOnPathChange?: boolean;
},
) {
const enabled = options?.enabled ?? true;
const durationMs = options?.durationMs ?? 1350;
const easing = options?.easing ?? "cubic-bezier(0.33, 1, 0.68, 1)";
const replayOnPathChange = options?.replayOnPathChange ?? true;
const hasPlayedRef = useRef(false);
useEffect(() => {
const path = pathRef.current;
@@ -28,6 +33,13 @@ export function useStrokeDrawAnimation(
return;
}
if (!replayOnPathChange && hasPlayedRef.current) {
path.style.strokeDasharray = "";
path.style.strokeDashoffset = "";
path.style.transition = "";
return;
}
const length = path.getTotalLength();
if (!Number.isFinite(length) || length <= 0) return;
@@ -36,6 +48,8 @@ export function useStrokeDrawAnimation(
path.style.transition = "none";
let cancelled = false;
hasPlayedRef.current = true;
const id = requestAnimationFrame(() => {
requestAnimationFrame(() => {
if (cancelled) return;
@@ -48,5 +62,5 @@ export function useStrokeDrawAnimation(
cancelled = true;
cancelAnimationFrame(id);
};
}, [pathRef, pathD, enabled, durationMs, easing]);
}, [pathRef, pathD, enabled, durationMs, easing, replayOnPathChange]);
}