修复 bug
This commit is contained in:
+70
-19
@@ -52,6 +52,7 @@ import {
|
||||
DEFAULT_BANDS,
|
||||
FILTER_TYPES,
|
||||
FLAT_PRESET_FILTERS,
|
||||
PEQ_PRESET_MAX,
|
||||
} from "./eq/eqConstants";
|
||||
import {
|
||||
eqInterp,
|
||||
@@ -64,7 +65,13 @@ import {
|
||||
normalizeBandFreqHz,
|
||||
parseBandParamInput,
|
||||
} from "./eq/eqFormatters";
|
||||
import { bandToPeqFilter, buildPeqCatalogSyncKey, cloneBands, getUniquePresetName } from "./eq/peqMappers";
|
||||
import {
|
||||
bandToPeqFilter,
|
||||
buildPeqCatalogSyncKey,
|
||||
cloneBands,
|
||||
fetchEqSyncPeq,
|
||||
getUniquePresetName,
|
||||
} from "./eq/peqMappers";
|
||||
import type { BandParamKind, PeqCatalogItem, PeqEqUi, PeqPresetLocalCache } from "./eq/types";
|
||||
|
||||
/* ── Main Component ── */
|
||||
@@ -137,6 +144,7 @@ export default function EQPage() {
|
||||
gain?: number;
|
||||
q?: number;
|
||||
} | null>(null);
|
||||
const bandSliderDragRef = useRef<BandParamKind | null>(null);
|
||||
const [isBatchEditDialogOpen, setIsBatchEditDialogOpen] = useState(false);
|
||||
const [batchEditText, setBatchEditText] = useState("");
|
||||
type BrandDrawerTab = "brands" | "models" | "target";
|
||||
@@ -282,7 +290,17 @@ export default function EQPage() {
|
||||
}
|
||||
}, [eqUi]);
|
||||
|
||||
const guardPeqPresetCapacity = () => {
|
||||
if (peqItems.length < PEQ_PRESET_MAX) return true;
|
||||
toast.error(
|
||||
eqInterp(eqUi.toastPresetLimitReached, { max: PEQ_PRESET_MAX })
|
||||
|| `Preset limit reached (${PEQ_PRESET_MAX}). Delete some presets first.`,
|
||||
);
|
||||
return false;
|
||||
};
|
||||
|
||||
const openAddHeadsetCatalog = () => {
|
||||
if (!guardPeqPresetCapacity()) return;
|
||||
setIsBrandDrawerOpen(true);
|
||||
setBrandDrawerTab("brands");
|
||||
setBrandSearchQuery("");
|
||||
@@ -632,7 +650,7 @@ export default function EQPage() {
|
||||
|
||||
delete peqPresetCacheRef.current[target.name];
|
||||
await api.removePeq([target.name]);
|
||||
const latest = await api.getPeqState();
|
||||
const latest = await fetchEqSyncPeq(api, "deleteHeadphone");
|
||||
applyPeqStateToUI(latest);
|
||||
toast.success(eqUi.toastDeleted);
|
||||
} catch {
|
||||
@@ -641,6 +659,7 @@ export default function EQPage() {
|
||||
};
|
||||
|
||||
const openAddPresetDialog = () => {
|
||||
if (!guardPeqPresetCapacity()) return;
|
||||
const existingNames = headphoneModels;
|
||||
const currentName = headphoneModels[headphoneIdx] ?? "Preset";
|
||||
setCopyPresetName(getUniquePresetName(currentName, existingNames));
|
||||
@@ -669,11 +688,13 @@ export default function EQPage() {
|
||||
|
||||
const copyBrand = currentPeq?.brand?.trim() ?? "";
|
||||
const copyModel = currentPeq?.model?.trim() ?? "";
|
||||
const copyForm = currentPeq?.form?.trim() ?? "";
|
||||
const copyPayload: PeqChangePayload = {
|
||||
peqChange: {
|
||||
name: nextName,
|
||||
...(copyBrand ? { brand: copyBrand } : {}),
|
||||
...(copyModel ? { model: copyModel } : {}),
|
||||
...(copyForm ? { form: copyForm } : {}),
|
||||
filters: bands.map(bandToPeqFilter),
|
||||
autoPre: currentPeq?.autoPre ?? 0,
|
||||
preamp: currentPeq?.preamp ?? 0,
|
||||
@@ -694,7 +715,7 @@ export default function EQPage() {
|
||||
try {
|
||||
await upgradePeqChange(addPresetMode === "copy" ? copyPayload : flatPayload);
|
||||
if (api && !isDemoMode) {
|
||||
const latest = await api.getPeqState();
|
||||
const latest = await fetchEqSyncPeq(api, "addPreset");
|
||||
applyPeqStateToUI(latest as { peq?: Array<{ name: string; filters?: any[] | string }>; peqSelect?: number });
|
||||
const createdIndex = latest.peq?.findIndex((item) => item.name === nextName) ?? -1;
|
||||
if (createdIndex >= 0) {
|
||||
@@ -714,6 +735,7 @@ export default function EQPage() {
|
||||
name: nextName,
|
||||
...(addPresetMode === "copy" && copyBrand ? { brand: copyBrand } : {}),
|
||||
...(addPresetMode === "copy" && copyModel ? { model: copyModel } : {}),
|
||||
...(addPresetMode === "copy" && copyForm ? { form: copyForm } : {}),
|
||||
filters: localFilters,
|
||||
autoPre: localAutoPre,
|
||||
preamp: localPreamp,
|
||||
@@ -755,7 +777,7 @@ export default function EQPage() {
|
||||
try {
|
||||
await upgradePeqChange(payload);
|
||||
if (api && !isDemoMode) {
|
||||
const latest = await api.getPeqState();
|
||||
const latest = await fetchEqSyncPeq(api, "saveBAsPreset");
|
||||
applyPeqStateToUI(latest as { peq?: Array<{ name: string; filters?: any[] | string }>; peqSelect?: number });
|
||||
const createdIndex = latest.peq?.findIndex((item) => item.name === nextName) ?? -1;
|
||||
if (createdIndex >= 0) {
|
||||
@@ -902,7 +924,7 @@ export default function EQPage() {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const loadedPeq = await api.getPeqState();
|
||||
const loadedPeq = await fetchEqSyncPeq(api, "loadHeadphones");
|
||||
if (loadedPeq.peq && loadedPeq.peq.length > 0) {
|
||||
syncPeqCatalog(loadedPeq);
|
||||
setHeadphoneModels(loadedPeq.peq.map((h) => h.name));
|
||||
@@ -1259,6 +1281,37 @@ export default function EQPage() {
|
||||
[setBands],
|
||||
);
|
||||
|
||||
const clearBandSliderPreviewField = useCallback((kind: BandParamKind) => {
|
||||
setBandSliderPreview((prev) => {
|
||||
if (prev?.[kind] === undefined) return prev;
|
||||
const next = { ...prev };
|
||||
delete next[kind];
|
||||
return next.freq !== undefined || next.gain !== undefined || next.q !== undefined ? next : null;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const beginBandSliderDrag = useCallback((kind: BandParamKind) => {
|
||||
bandSliderDragRef.current = kind;
|
||||
}, []);
|
||||
|
||||
const endBandSliderDrag = useCallback(
|
||||
(kind: BandParamKind) => {
|
||||
if (bandSliderDragRef.current !== kind) return;
|
||||
bandSliderDragRef.current = null;
|
||||
clearBandSliderPreviewField(kind);
|
||||
},
|
||||
[clearBandSliderPreviewField],
|
||||
);
|
||||
|
||||
const handleBandSliderChange = useCallback(
|
||||
(kind: BandParamKind, value: number) => {
|
||||
if (bandSliderDragRef.current !== kind) return;
|
||||
setBandSliderPreview((prev) => ({ ...prev, [kind]: value }));
|
||||
updateBand(selectedBand, { [kind]: value });
|
||||
},
|
||||
[selectedBand, updateBand],
|
||||
);
|
||||
|
||||
const bandParamDialogMeta = useMemo(() => {
|
||||
if (!bandParamDialog) return null;
|
||||
const rangeMessages = {
|
||||
@@ -1328,9 +1381,11 @@ export default function EQPage() {
|
||||
toast.error(parsed.message);
|
||||
return;
|
||||
}
|
||||
bandSliderDragRef.current = null;
|
||||
if (bandParamDialog === "freq") updateBand(selectedBand, { freq: parsed.value });
|
||||
else if (bandParamDialog === "gain") updateBand(selectedBand, { gain: parsed.value });
|
||||
else updateBand(selectedBand, { q: parsed.value });
|
||||
setBandSliderPreview(null);
|
||||
closeBandParamDialog();
|
||||
};
|
||||
|
||||
@@ -1604,11 +1659,9 @@ export default function EQPage() {
|
||||
min={Math.log10(BAND_FREQ_MIN)}
|
||||
max={Math.log10(BAND_FREQ_MAX)}
|
||||
step={0.005}
|
||||
onChange={(v) => {
|
||||
const freq = Math.round(Math.pow(10, v));
|
||||
setBandSliderPreview((prev) => ({ ...prev, freq }));
|
||||
updateBand(selectedBand, { freq });
|
||||
}}
|
||||
onInteractionStart={() => beginBandSliderDrag("freq")}
|
||||
onInteractionEnd={() => endBandSliderDrag("freq")}
|
||||
onChange={(v) => handleBandSliderChange("freq", Math.round(Math.pow(10, v)))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1630,10 +1683,9 @@ export default function EQPage() {
|
||||
min={BAND_GAIN_MIN}
|
||||
max={BAND_GAIN_MAX}
|
||||
step={0.1}
|
||||
onChange={(v) => {
|
||||
setBandSliderPreview((prev) => ({ ...prev, gain: v }));
|
||||
updateBand(selectedBand, { gain: v });
|
||||
}}
|
||||
onInteractionStart={() => beginBandSliderDrag("gain")}
|
||||
onInteractionEnd={() => endBandSliderDrag("gain")}
|
||||
onChange={(v) => handleBandSliderChange("gain", v)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1655,10 +1707,9 @@ export default function EQPage() {
|
||||
min={BAND_Q_MIN}
|
||||
max={BAND_Q_MAX}
|
||||
step={0.01}
|
||||
onChange={(v) => {
|
||||
setBandSliderPreview((prev) => ({ ...prev, q: v }));
|
||||
updateBand(selectedBand, { q: v });
|
||||
}}
|
||||
onInteractionStart={() => beginBandSliderDrag("q")}
|
||||
onInteractionEnd={() => endBandSliderDrag("q")}
|
||||
onChange={(v) => handleBandSliderChange("q", v)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2189,7 +2240,7 @@ export default function EQPage() {
|
||||
await upgradePeqChange(postPeq);
|
||||
const createdName = postPeq.peqChange.name;
|
||||
if (api && !isDemoMode) {
|
||||
const latest = await api.getPeqState();
|
||||
const latest = await fetchEqSyncPeq(api, "addCatalogPreset");
|
||||
applyPeqStateToUI(latest as { peq?: Array<{ name: string; filters?: any[] | string }>; peqSelect?: number });
|
||||
const createdIndex = latest.peq?.findIndex((item) => item.name === createdName) ?? -1;
|
||||
if (createdIndex >= 0) {
|
||||
|
||||
Reference in New Issue
Block a user