分享码功能的实现,并修复了几个 bug
This commit is contained in:
+317
-102
@@ -23,8 +23,9 @@ import {
|
||||
type PeqFilter,
|
||||
type PeqApplyPayload,
|
||||
type PeqChangePayload,
|
||||
type PeqPresetBody,
|
||||
type PeqState,
|
||||
buildPeqPresetBody,
|
||||
acceptShareCode,
|
||||
} from "@/lib/luxsinApi";
|
||||
import {
|
||||
getFilterType,
|
||||
@@ -64,6 +65,7 @@ import {
|
||||
getUniquePresetName,
|
||||
bandToPeqFilter,
|
||||
fetchEqSyncPeq,
|
||||
importedFiltersToPeqFilters,
|
||||
} from "./eq/utils";
|
||||
import { IOSToggle } from "./eq/components/IOSToggle";
|
||||
import { CyanSlider } from "./eq/components/CyanSlider";
|
||||
@@ -74,6 +76,7 @@ import { AddPresetDialog } from "./eq/components/AddPresetDialog";
|
||||
import { BatchEditDialog } from "./eq/components/BatchEditDialog";
|
||||
import { ShareDialog } from "./eq/components/ShareDialog";
|
||||
import { BrandDrawer } from "./eq/components/BrandDrawer";
|
||||
import { PeqOverwriteConfirmDialog } from "./eq/components/PeqOverwriteConfirmDialog";
|
||||
import { useRawCurve } from "./eq/hooks/useRawCurve";
|
||||
|
||||
/* ── Default bands imported from eq/constants ── */
|
||||
@@ -123,6 +126,7 @@ export default function EQPage() {
|
||||
name: string;
|
||||
brand?: string;
|
||||
model?: string;
|
||||
target?: string;
|
||||
form?: string;
|
||||
filters?: any[] | string;
|
||||
autoPre?: number;
|
||||
@@ -154,6 +158,11 @@ export default function EQPage() {
|
||||
const [brandDrawerKey, setBrandDrawerKey] = useState(0);
|
||||
const [isShareDialogOpen, setIsShareDialogOpen] = useState(false);
|
||||
const [shareDialogKey, setShareDialogKey] = useState(0);
|
||||
const [overwritePresetDialog, setOverwritePresetDialog] = useState<{
|
||||
name: string;
|
||||
onConfirm: () => void | Promise<void>;
|
||||
onDismiss: () => void;
|
||||
} | null>(null);
|
||||
const {
|
||||
currentRawCurve,
|
||||
setCurrentRawCurve,
|
||||
@@ -162,6 +171,7 @@ export default function EQPage() {
|
||||
loadRawCurveForPeq,
|
||||
} = useRawCurve();
|
||||
const allowPeqRemoteSyncRef = useRef(false);
|
||||
const peqHydrationPendingRef = useRef(true);
|
||||
const lastPeqCatalogSyncKeyRef = useRef("");
|
||||
const syncingHeadphoneRef = useRef(false);
|
||||
const peqSyncTimerRef = useRef<number | null>(null);
|
||||
@@ -215,6 +225,29 @@ export default function EQPage() {
|
||||
return false;
|
||||
};
|
||||
|
||||
const promptOverwriteIfNeeded = useCallback(
|
||||
(name: string, action: () => void | Promise<void>): Promise<boolean> => {
|
||||
if (!headphoneModels.includes(name)) {
|
||||
return Promise.resolve(action()).then(() => true);
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
setOverwritePresetDialog({
|
||||
name,
|
||||
onConfirm: async () => {
|
||||
setOverwritePresetDialog(null);
|
||||
await action();
|
||||
resolve(true);
|
||||
},
|
||||
onDismiss: () => {
|
||||
setOverwritePresetDialog(null);
|
||||
resolve(false);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
[headphoneModels],
|
||||
);
|
||||
|
||||
const openAddHeadsetCatalog = () => {
|
||||
if (!guardPeqPresetCapacity()) return;
|
||||
setIsBrandDrawerOpen(true);
|
||||
@@ -510,28 +543,29 @@ export default function EQPage() {
|
||||
|
||||
const copyBrand = currentPeq?.brand?.trim() ?? "";
|
||||
const copyModel = currentPeq?.model?.trim() ?? "";
|
||||
const copyTarget = currentPeq?.target?.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,
|
||||
canDel: currentPeq?.canDel ?? 1,
|
||||
},
|
||||
peqChange: buildPeqPresetBody(
|
||||
{
|
||||
name: nextName,
|
||||
brand: copyBrand || undefined,
|
||||
model: copyModel || undefined,
|
||||
target: copyTarget || undefined,
|
||||
form: copyForm || undefined,
|
||||
autoPre: currentPeq?.autoPre,
|
||||
preamp: currentPeq?.preamp,
|
||||
canDel: currentPeq?.canDel,
|
||||
},
|
||||
bands.map(bandToPeqFilter),
|
||||
),
|
||||
};
|
||||
|
||||
const flatPayload: PeqChangePayload = {
|
||||
peqChange: {
|
||||
name: nextName,
|
||||
preamp: 0,
|
||||
canDel: 1,
|
||||
autoPre: 0,
|
||||
filters: FLAT_PRESET_FILTERS,
|
||||
},
|
||||
peqChange: buildPeqPresetBody(
|
||||
{ name: nextName, preamp: 0, canDel: 1, autoPre: 0 },
|
||||
FLAT_PRESET_FILTERS,
|
||||
),
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -557,6 +591,7 @@ export default function EQPage() {
|
||||
name: nextName,
|
||||
...(addPresetMode === "copy" && copyBrand ? { brand: copyBrand } : {}),
|
||||
...(addPresetMode === "copy" && copyModel ? { model: copyModel } : {}),
|
||||
...(addPresetMode === "copy" && copyTarget ? { target: copyTarget } : {}),
|
||||
...(addPresetMode === "copy" && copyForm ? { form: copyForm } : {}),
|
||||
filters: localFilters,
|
||||
autoPre: localAutoPre,
|
||||
@@ -587,13 +622,19 @@ export default function EQPage() {
|
||||
const bBands = cloneBands(bandsByMode.B);
|
||||
const filters = bBands.map(bandToPeqFilter);
|
||||
const payload: PeqChangePayload = {
|
||||
peqChange: {
|
||||
name: nextName,
|
||||
peqChange: buildPeqPresetBody(
|
||||
{
|
||||
name: nextName,
|
||||
brand: currentPeq?.brand,
|
||||
model: currentPeq?.model,
|
||||
target: currentPeq?.target,
|
||||
form: currentPeq?.form,
|
||||
autoPre: currentPeq?.autoPre,
|
||||
preamp: currentPeq?.preamp,
|
||||
canDel: currentPeq?.canDel,
|
||||
},
|
||||
filters,
|
||||
autoPre: currentPeq?.autoPre ?? 0,
|
||||
preamp: currentPeq?.preamp ?? 0,
|
||||
canDel: currentPeq?.canDel ?? 1,
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -627,6 +668,125 @@ export default function EQPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleImportSharedEq = async (
|
||||
data: {
|
||||
name: string;
|
||||
brand?: string;
|
||||
model?: string;
|
||||
target?: string;
|
||||
form?: string;
|
||||
filters?: unknown;
|
||||
preamp?: number;
|
||||
autoPre?: number;
|
||||
},
|
||||
shareCode: string,
|
||||
) => {
|
||||
const nextName = data.name?.trim();
|
||||
if (!nextName) {
|
||||
toast.error(eqUi.addPresetNameEmpty);
|
||||
return;
|
||||
}
|
||||
if (!shareCode.trim()) {
|
||||
toast.error(eqUi.importCodeNotFound);
|
||||
return;
|
||||
}
|
||||
if (!guardPeqPresetCapacity() && !headphoneModels.includes(nextName)) return;
|
||||
|
||||
const filters = importedFiltersToPeqFilters(data.filters);
|
||||
if (filters.length === 0) {
|
||||
toast.error(eqUi.importFail ?? eqUi.toastAddPresetFail);
|
||||
return;
|
||||
}
|
||||
|
||||
const submitImport = async () => {
|
||||
const existingIdx = headphoneModels.indexOf(nextName);
|
||||
const isOverwrite = existingIdx >= 0;
|
||||
const payload: PeqChangePayload = {
|
||||
peqChange: buildPeqPresetBody(
|
||||
{
|
||||
name: nextName,
|
||||
brand: data.brand,
|
||||
model: data.model,
|
||||
target: data.target,
|
||||
form: data.form,
|
||||
preamp: data.preamp,
|
||||
autoPre: data.autoPre ?? 0,
|
||||
canDel: 1,
|
||||
},
|
||||
filters,
|
||||
),
|
||||
};
|
||||
|
||||
skipPeqAutoSyncRef.current = true;
|
||||
try {
|
||||
const mac = deviceState?.mac ?? "";
|
||||
if (!isDemoMode && mac) {
|
||||
const acceptRes = await acceptShareCode(mac, shareCode.trim());
|
||||
if (acceptRes.code !== 200) {
|
||||
toast.error(eqUi.importFail ?? eqUi.importCodeNotFound);
|
||||
skipPeqAutoSyncRef.current = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await upgradePeqChange(payload);
|
||||
if (api && !isDemoMode) {
|
||||
const latest = await fetchEqSyncPeq(api, "importSharedEq");
|
||||
applyPeqStateToUI(latest as { peq?: Array<{ name: string; filters?: any[] | string }>; peqSelect?: number });
|
||||
const targetIdx = latest.peq?.findIndex((item) => item.name === nextName) ?? -1;
|
||||
if (targetIdx >= 0) {
|
||||
setHeadphoneIdx(targetIdx);
|
||||
updateSetting({ peqSelect: targetIdx });
|
||||
}
|
||||
} else if (isOverwrite) {
|
||||
setPeqItems((prev) =>
|
||||
prev.map((item, i) =>
|
||||
i === existingIdx
|
||||
? {
|
||||
...item,
|
||||
name: nextName,
|
||||
brand: data.brand,
|
||||
model: data.model,
|
||||
target: data.target,
|
||||
form: data.form,
|
||||
filters,
|
||||
preamp: data.preamp ?? 0,
|
||||
autoPre: data.autoPre ?? 0,
|
||||
canDel: 1,
|
||||
}
|
||||
: item,
|
||||
),
|
||||
);
|
||||
setHeadphoneIdx(existingIdx);
|
||||
} else {
|
||||
setHeadphoneModels((prev) => [...prev, nextName]);
|
||||
setPeqItems((prev) => [
|
||||
...prev,
|
||||
{
|
||||
name: nextName,
|
||||
brand: data.brand,
|
||||
model: data.model,
|
||||
target: data.target,
|
||||
form: data.form,
|
||||
filters,
|
||||
preamp: data.preamp ?? 0,
|
||||
autoPre: data.autoPre ?? 0,
|
||||
canDel: 1,
|
||||
},
|
||||
]);
|
||||
setHeadphoneIdx(headphoneModels.length);
|
||||
}
|
||||
toast.success(eqUi.importSuccess);
|
||||
setIsShareDialogOpen(false);
|
||||
} catch {
|
||||
skipPeqAutoSyncRef.current = false;
|
||||
toast.error(eqUi.importFail ?? eqUi.toastAddPresetFail);
|
||||
}
|
||||
};
|
||||
|
||||
await promptOverwriteIfNeeded(nextName, submitImport);
|
||||
};
|
||||
|
||||
// msgCount 轮询更新 peqState 后,同步耳机列表与当前选中项
|
||||
useEffect(() => {
|
||||
if (!peqState?.peq) return;
|
||||
@@ -644,6 +804,7 @@ export default function EQPage() {
|
||||
// 加载耳机列表并初始化曲线
|
||||
useEffect(() => {
|
||||
async function loadHeadphones() {
|
||||
peqHydrationPendingRef.current = true;
|
||||
allowPeqRemoteSyncRef.current = false;
|
||||
try {
|
||||
if (isDemoMode || !api) {
|
||||
@@ -720,6 +881,10 @@ export default function EQPage() {
|
||||
}
|
||||
} finally {
|
||||
allowPeqRemoteSyncRef.current = true;
|
||||
skipPeqAutoSyncRef.current = true;
|
||||
queueMicrotask(() => {
|
||||
peqHydrationPendingRef.current = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
loadHeadphones();
|
||||
@@ -739,6 +904,7 @@ export default function EQPage() {
|
||||
const nextBands = normalizeFiltersFromPeq(peq);
|
||||
if (!nextBands.length) return;
|
||||
syncingHeadphoneRef.current = true;
|
||||
skipPeqAutoSyncRef.current = true;
|
||||
setBandsForBothModes(nextBands);
|
||||
setSelectedBandByMode({ A: 0, B: 0 });
|
||||
const shouldFetchModelCurve = !!(peq.brand?.trim() && peq.model?.trim());
|
||||
@@ -835,7 +1001,16 @@ export default function EQPage() {
|
||||
|
||||
const schedulePeqSync = useCallback(
|
||||
(
|
||||
peq: { name: string; autoPre?: number; preamp?: number; canDel?: number } | undefined,
|
||||
peq: {
|
||||
name: string;
|
||||
autoPre?: number;
|
||||
preamp?: number;
|
||||
canDel?: number;
|
||||
brand?: string;
|
||||
model?: string;
|
||||
target?: string;
|
||||
form?: string;
|
||||
} | undefined,
|
||||
filtersSource: typeof DEFAULT_BANDS,
|
||||
mode: "A" | "B",
|
||||
delay = 320,
|
||||
@@ -843,6 +1018,7 @@ export default function EQPage() {
|
||||
catalogIdx = headphoneIdx,
|
||||
) => {
|
||||
if (!allowPeqRemoteSyncRef.current) return;
|
||||
if (peqHydrationPendingRef.current) return;
|
||||
if (!isDemoMode && !api) return;
|
||||
if (!peq?.name) return;
|
||||
|
||||
@@ -853,13 +1029,7 @@ export default function EQPage() {
|
||||
const idxAtSchedule = catalogIdx;
|
||||
peqSyncTimerRef.current = window.setTimeout(() => {
|
||||
const filters = filtersSource.map(bandToPeqFilter);
|
||||
const body: PeqPresetBody = {
|
||||
name: peq.name,
|
||||
filters,
|
||||
autoPre: peq.autoPre ?? 0,
|
||||
preamp: peq.preamp ?? 0,
|
||||
canDel: peq.canDel ?? 1,
|
||||
};
|
||||
const body = buildPeqPresetBody(peq, filters);
|
||||
const usePeqChange =
|
||||
topLevel === "peqChange" || (topLevel === "byMode" && mode === "A");
|
||||
if (usePeqChange) {
|
||||
@@ -904,6 +1074,7 @@ export default function EQPage() {
|
||||
|
||||
// 参数编辑防抖:A→peqChange,B→peqApply
|
||||
useEffect(() => {
|
||||
if (peqHydrationPendingRef.current) return;
|
||||
if (syncingHeadphoneRef.current) return;
|
||||
if (skipPeqAutoSyncRef.current) {
|
||||
skipPeqAutoSyncRef.current = false;
|
||||
@@ -949,13 +1120,19 @@ export default function EQPage() {
|
||||
const bBands = cloneBands(bandsByMode.B);
|
||||
const filters = bBands.map(bandToPeqFilter);
|
||||
const payload: PeqChangePayload = {
|
||||
peqChange: {
|
||||
name: peq.name,
|
||||
peqChange: buildPeqPresetBody(
|
||||
{
|
||||
name: peq.name,
|
||||
brand: peq.brand,
|
||||
model: peq.model,
|
||||
target: peq.target,
|
||||
form: peq.form,
|
||||
autoPre: peq.autoPre,
|
||||
preamp: peq.preamp,
|
||||
canDel: peq.canDel,
|
||||
},
|
||||
filters,
|
||||
autoPre: peq.autoPre ?? 0,
|
||||
preamp: peq.preamp ?? 0,
|
||||
canDel: peq.canDel ?? 1,
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
skipPeqAutoSyncRef.current = true;
|
||||
@@ -1525,7 +1702,7 @@ export default function EQPage() {
|
||||
/>
|
||||
|
||||
<BrandDrawer
|
||||
key={brandDrawerKey}
|
||||
key={`brand-drawer-${brandDrawerKey}`}
|
||||
open={isBrandDrawerOpen}
|
||||
onClose={() => setIsBrandDrawerOpen(false)}
|
||||
eqUi={eqUi}
|
||||
@@ -1540,7 +1717,9 @@ export default function EQPage() {
|
||||
|
||||
const parsedObj = parsed && typeof parsed === "object" ? (parsed as Record<string, unknown>) : null;
|
||||
const parametricEqRaw = parsedObj?.parametric_eq;
|
||||
if (!parametricEqRaw || typeof parametricEqRaw !== "object") return;
|
||||
if (!parametricEqRaw || typeof parametricEqRaw !== "object") {
|
||||
throw new Error("parametric_eq missing");
|
||||
}
|
||||
|
||||
const parametricEq = parametricEqRaw as {
|
||||
filters?: Array<{ type: string | number; fc: number; gain: number; q: number }>;
|
||||
@@ -1556,86 +1735,122 @@ export default function EQPage() {
|
||||
q: Number(Number(item.q).toFixed(2)),
|
||||
}));
|
||||
|
||||
const createdName = `${brand} ${name}`;
|
||||
const postPeq: PeqChangePayload = {
|
||||
peqChange: {
|
||||
name: `${brand} ${name}`,
|
||||
brand,
|
||||
model: name,
|
||||
target,
|
||||
...(form ? { form } : {}),
|
||||
filters,
|
||||
preamp: Number(Number(parametricEq.preamp ?? 0).toFixed(2)),
|
||||
autoPre: 0,
|
||||
canDel: 1,
|
||||
},
|
||||
};
|
||||
|
||||
await upgradePeqChange(postPeq);
|
||||
const createdName = postPeq.peqChange.name;
|
||||
if (api && !isDemoMode) {
|
||||
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) {
|
||||
setHeadphoneIdx(createdIndex);
|
||||
updateSetting({ peqSelect: createdIndex });
|
||||
}
|
||||
} else {
|
||||
let nextIndex = 0;
|
||||
setPeqItems((prev) => [
|
||||
...prev,
|
||||
peqChange: buildPeqPresetBody(
|
||||
{
|
||||
name: createdName,
|
||||
brand,
|
||||
model: name,
|
||||
target,
|
||||
...(form ? { form } : {}),
|
||||
filters: postPeq.peqChange.filters,
|
||||
preamp: postPeq.peqChange.preamp ?? 0,
|
||||
autoPre: postPeq.peqChange.autoPre ?? 0,
|
||||
canDel: postPeq.peqChange.canDel ?? 1,
|
||||
form,
|
||||
preamp: Number(Number(parametricEq.preamp ?? 0).toFixed(2)),
|
||||
autoPre: 0,
|
||||
canDel: 1,
|
||||
},
|
||||
]);
|
||||
setHeadphoneModels((prev) => {
|
||||
nextIndex = prev.length;
|
||||
return [...prev, createdName];
|
||||
});
|
||||
setHeadphoneIdx(nextIndex);
|
||||
filters,
|
||||
),
|
||||
};
|
||||
|
||||
const submitCatalogPreset = async () => {
|
||||
const existingIdx = headphoneModels.indexOf(createdName);
|
||||
const isOverwrite = existingIdx >= 0;
|
||||
if (!isOverwrite && !guardPeqPresetCapacity()) return;
|
||||
skipPeqAutoSyncRef.current = true;
|
||||
try {
|
||||
await upgradePeqChange(postPeq);
|
||||
if (api && !isDemoMode) {
|
||||
const latest = await fetchEqSyncPeq(api, "addCatalogPreset");
|
||||
applyPeqStateToUI(latest as { peq?: Array<{ name: string; filters?: any[] | string }>; peqSelect?: number });
|
||||
const targetIdx = latest.peq?.findIndex((item) => item.name === createdName) ?? -1;
|
||||
if (targetIdx >= 0) {
|
||||
setHeadphoneIdx(targetIdx);
|
||||
updateSetting({ peqSelect: targetIdx });
|
||||
}
|
||||
} else if (isOverwrite) {
|
||||
setPeqItems((prev) =>
|
||||
prev.map((item, i) =>
|
||||
i === existingIdx
|
||||
? {
|
||||
...item,
|
||||
name: createdName,
|
||||
brand,
|
||||
model: name,
|
||||
target,
|
||||
...(form ? { form } : {}),
|
||||
filters: postPeq.peqChange.filters,
|
||||
preamp: postPeq.peqChange.preamp ?? 0,
|
||||
autoPre: postPeq.peqChange.autoPre ?? 0,
|
||||
canDel: postPeq.peqChange.canDel ?? 1,
|
||||
}
|
||||
: item,
|
||||
),
|
||||
);
|
||||
setHeadphoneIdx(existingIdx);
|
||||
} else {
|
||||
let nextIndex = 0;
|
||||
setPeqItems((prev) => [
|
||||
...prev,
|
||||
{
|
||||
name: createdName,
|
||||
brand,
|
||||
model: name,
|
||||
target,
|
||||
...(form ? { form } : {}),
|
||||
filters: postPeq.peqChange.filters,
|
||||
preamp: postPeq.peqChange.preamp ?? 0,
|
||||
autoPre: postPeq.peqChange.autoPre ?? 0,
|
||||
canDel: postPeq.peqChange.canDel ?? 1,
|
||||
},
|
||||
]);
|
||||
setHeadphoneModels((prev) => {
|
||||
nextIndex = prev.length;
|
||||
return [...prev, createdName];
|
||||
});
|
||||
setHeadphoneIdx(nextIndex);
|
||||
}
|
||||
setIsBrandDrawerOpen(false);
|
||||
} catch {
|
||||
skipPeqAutoSyncRef.current = false;
|
||||
toast.error(eqUi.toastAddPresetFail);
|
||||
}
|
||||
};
|
||||
|
||||
if (headphoneModels.includes(createdName)) {
|
||||
setIsBrandDrawerOpen(false);
|
||||
}
|
||||
return promptOverwriteIfNeeded(createdName, submitCatalogPreset);
|
||||
}}
|
||||
/>
|
||||
|
||||
<PeqOverwriteConfirmDialog
|
||||
open={!!overwritePresetDialog}
|
||||
title={eqUi.overwritePresetTitle ?? "Preset name already exists"}
|
||||
description={
|
||||
overwritePresetDialog
|
||||
? eqInterp(eqUi.overwritePresetDesc, { name: overwritePresetDialog.name })
|
||||
: ""
|
||||
}
|
||||
cancelLabel={eqUi.cancel}
|
||||
confirmLabel={eqUi.overwritePresetConfirm ?? eqUi.confirmButton ?? eqUi.save}
|
||||
onConfirm={() => {
|
||||
void overwritePresetDialog?.onConfirm();
|
||||
}}
|
||||
onCancel={() => {
|
||||
overwritePresetDialog?.onDismiss();
|
||||
}}
|
||||
/>
|
||||
|
||||
<ShareDialog
|
||||
key={shareDialogKey}
|
||||
key={`share-dialog-${shareDialogKey}`}
|
||||
open={isShareDialogOpen}
|
||||
onClose={() => setIsShareDialogOpen(false)}
|
||||
peqItems={peqItems}
|
||||
headphoneIdx={headphoneIdx}
|
||||
eqUi={eqUi}
|
||||
peqCardLabels={peqCardLabels}
|
||||
onImportEq={(data) => {
|
||||
// ── TODO: 伪代码 — 导入 EQ 到预设列表 ──
|
||||
// if (!guardPeqPresetCapacity()) return;
|
||||
// setPeqItems((prev) => [
|
||||
// ...prev,
|
||||
// {
|
||||
// name: data.name,
|
||||
// brand: data.brand,
|
||||
// model: data.model,
|
||||
// form: data.form,
|
||||
// filters: data.filters,
|
||||
// preamp: data.preamp,
|
||||
// autoPre: 0,
|
||||
// canDel: 1,
|
||||
// },
|
||||
// ]);
|
||||
// setHeadphoneIdx(peqItems.length);
|
||||
// toast.success(eqUi.importSuccess);
|
||||
|
||||
// 模拟导入
|
||||
toast.success(eqUi.importSuccess);
|
||||
setIsShareDialogOpen(false);
|
||||
}}
|
||||
mac={deviceState?.mac ?? ""}
|
||||
onImportEq={handleImportSharedEq}
|
||||
/>
|
||||
|
||||
<BottomNav />
|
||||
|
||||
Reference in New Issue
Block a user