Initial commit: 提交控制器版本2核心代码
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
/* ============================================================
|
||||
AUDIO PAGE — Audio Settings
|
||||
Design: Reference luxsin_x8_音频设置.png
|
||||
Sections:
|
||||
- 平衡与灵敏度: 左右平衡 slider, VU灵敏度 slider
|
||||
- 输出特性: 滤波特性, 耳机增益, 音量幅度
|
||||
- 系统与接口: XLR极性, DAC增益, DAC阻抗
|
||||
All list rows → navigate to /select page
|
||||
============================================================ */
|
||||
import { useDevice } from "@/contexts/DeviceContext";
|
||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import { useLocation } from "wouter";
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import BottomNav from "@/components/BottomNav";
|
||||
import { navigateToSelect } from "./SelectPage";
|
||||
|
||||
function CyanSlider({ value, min, max, step = 1, onChange }: {
|
||||
value: number; min: number; max: number; step?: number; onChange: (v: number) => void;
|
||||
}) {
|
||||
const fillPct = ((value - min) / (max - min)) * 100;
|
||||
return (
|
||||
<div className="relative flex items-center w-full mt-2">
|
||||
<div className="absolute left-0 h-[4px] rounded-full pointer-events-none"
|
||||
style={{ width: `${fillPct}%`, background: "#00FFF6", boxShadow: "0 0 6px rgba(0,255,246,0.5)" }} />
|
||||
<input type="range" min={min} max={max} step={step} value={value}
|
||||
className="cyan-slider relative z-10"
|
||||
onChange={(e) => onChange(Number(e.target.value))} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function SectionHeader({ title }: { title: string }) {
|
||||
return (
|
||||
<div className="px-1 pt-5 pb-2">
|
||||
<span className="text-[14px] font-semibold" style={{ color: "#00FFF6" }}>{title}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ListRow({ label, value, onClick }: { label: string; value: string; onClick?: () => void }) {
|
||||
return (
|
||||
<button className="ios-list-row w-full text-left active:bg-white/5 transition-colors" onClick={onClick}>
|
||||
<span className="flex-1 text-[16px] text-white">{label}</span>
|
||||
<span className="ios-row-value">{value}</span>
|
||||
<ChevronRight size={16} className="ios-chevron ml-1" />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
const FILTER_OPTIONS = ["短延迟快速滚降", "短延迟慢速滚降", "快速滚降", "慢速滚降", "超慢速滚降"];
|
||||
const GAIN_OPTIONS = ["低", "中", "高"];
|
||||
const STEP_OPTIONS = ["0.5dB", "1dB", "2dB"];
|
||||
const XLR_OPTIONS = ["正常", "反转"];
|
||||
const DAC_GAIN_OPTIONS = ["0dB", "+3dB", "+6dB"];
|
||||
const DAC_IMP_OPTIONS = ["32Ω", "150Ω", "300Ω"];
|
||||
|
||||
export default function AudioPage() {
|
||||
const [, setLocation] = useLocation();
|
||||
const { deviceState, updateSetting } = useDevice();
|
||||
const ds = deviceState;
|
||||
|
||||
const balanceVal = ds?.balance ?? 0;
|
||||
const [localBalance, setLocalBalance] = useState(balanceVal);
|
||||
const [localVuSens, setLocalVuSens] = useState(12);
|
||||
const [filterIdx] = useState(0);
|
||||
const isDragging = useRef(false);
|
||||
|
||||
useEffect(() => { if (!isDragging.current) setLocalBalance(balanceVal); }, [balanceVal]);
|
||||
|
||||
const gainIdx = ds?.analogGain ?? 0;
|
||||
const stepIdx = ds?.soundStep ?? 1;
|
||||
const xlrIdx = ds?.xlr ?? 0;
|
||||
const dacGainIdx = ds?.dacGain ?? 0;
|
||||
const dacImpIdx = ds?.dacImpedance ?? 0;
|
||||
|
||||
const goSelect = (title: string, options: string[], selected: number, key: string) => {
|
||||
navigateToSelect(title, options, selected, "/audio", key);
|
||||
setLocation("/select");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-black">
|
||||
<div className="page-header">
|
||||
<button onClick={() => setLocation("/")} className="mr-4 text-white/60 active:text-white transition-colors">
|
||||
<ChevronLeft size={24} />
|
||||
</button>
|
||||
<h1 className="flex-1 text-center text-[17px] font-semibold text-white">音频设置</h1>
|
||||
<div className="w-8" />
|
||||
</div>
|
||||
|
||||
<div className="px-4 pb-32">
|
||||
{/* ── 平衡与灵敏度 ── */}
|
||||
<SectionHeader title="平衡与灵敏度" />
|
||||
<div className="ios-list-group px-4 py-3 space-y-4">
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-[16px] text-white">左右平衡</span>
|
||||
<span className="text-[16px] font-semibold" style={{ color: "#00FFF6" }}>
|
||||
{localBalance >= 0 ? `+${localBalance.toFixed(1)}` : localBalance.toFixed(1)} dB
|
||||
</span>
|
||||
</div>
|
||||
<CyanSlider value={localBalance} min={-10} max={10} step={0.1}
|
||||
onChange={(v) => {
|
||||
isDragging.current = true;
|
||||
setLocalBalance(v);
|
||||
updateSetting({ balance: v });
|
||||
setTimeout(() => { isDragging.current = false; }, 500);
|
||||
}} />
|
||||
</div>
|
||||
<div className="border-t border-white/[0.06]" />
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-[16px] text-white">VU 表灵敏度</span>
|
||||
<span className="text-[16px] font-semibold" style={{ color: "#00FFF6" }}>
|
||||
{localVuSens} dB
|
||||
</span>
|
||||
</div>
|
||||
<CyanSlider value={localVuSens} min={0} max={24}
|
||||
onChange={(v) => {
|
||||
isDragging.current = true;
|
||||
setLocalVuSens(v);
|
||||
setTimeout(() => { isDragging.current = false; }, 500);
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── 输出特性 ── */}
|
||||
<SectionHeader title="输出特性" />
|
||||
<div className="ios-list-group">
|
||||
<ListRow label="滤波特性" value={FILTER_OPTIONS[filterIdx]}
|
||||
onClick={() => goSelect("选择滤波特性", FILTER_OPTIONS, filterIdx, "filterCharacteristic")} />
|
||||
<ListRow label="耳机增益" value={GAIN_OPTIONS[gainIdx]}
|
||||
onClick={() => goSelect("选择耳机增益", GAIN_OPTIONS, gainIdx, "analogGain")} />
|
||||
<ListRow label="音量幅度" value={STEP_OPTIONS[stepIdx]}
|
||||
onClick={() => goSelect("选择音量幅度", STEP_OPTIONS, stepIdx, "soundStep")} />
|
||||
</div>
|
||||
|
||||
{/* ── 系统与接口 ── */}
|
||||
<SectionHeader title="系统与接口" />
|
||||
<div className="ios-list-group">
|
||||
<ListRow label="XLR 端口极性" value={XLR_OPTIONS[xlrIdx]}
|
||||
onClick={() => goSelect("选择 XLR 极性", XLR_OPTIONS, xlrIdx, "xlr")} />
|
||||
<ListRow label="DAC 增益" value={DAC_GAIN_OPTIONS[dacGainIdx]}
|
||||
onClick={() => goSelect("选择 DAC 增益", DAC_GAIN_OPTIONS, dacGainIdx, "dacGain")} />
|
||||
<ListRow label="DAC 阻抗" value={DAC_IMP_OPTIONS[dacImpIdx]}
|
||||
onClick={() => goSelect("选择 DAC 阻抗", DAC_IMP_OPTIONS, dacImpIdx, "dacImpedance")} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BottomNav />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user