Refactor BottomNav and CommunityPage to enhance community forum integration; update navigation logic for mobile and desktop views. Add new localized strings for community page and system settings, including device information and user prompts.
This commit is contained in:
@@ -17,17 +17,40 @@ import localeZh from "@/locales/data-zh.json";
|
||||
import localeZhHK from "@/locales/data-zh-HK.json";
|
||||
import localeEn from "@/locales/data-en.json";
|
||||
|
||||
function CyanSlider({ value, min, max, step = 1, onChange }: {
|
||||
value: number; min: number; max: number; step?: number; onChange: (v: number) => void;
|
||||
function CyanSlider({ value, min, max, step = 1, onChange, onRelease }: {
|
||||
value: number;
|
||||
min: number;
|
||||
max: number;
|
||||
step?: number;
|
||||
onChange: (v: number) => void;
|
||||
/** Commit to device once when the user releases the thumb (pointer / keyboard). */
|
||||
onRelease?: (v: number) => void;
|
||||
}) {
|
||||
const fillPct = ((value - min) / (max - min)) * 100;
|
||||
const emitRelease = (el: EventTarget | null) => {
|
||||
if (!(el instanceof HTMLInputElement)) return;
|
||||
onRelease?.(Number(el.value));
|
||||
};
|
||||
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}
|
||||
<input
|
||||
type="range"
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
value={value}
|
||||
className="cyan-slider relative z-10"
|
||||
onChange={(e) => onChange(Number(e.target.value))} />
|
||||
onChange={(e) => onChange(Number(e.target.value))}
|
||||
onPointerUp={(e) => emitRelease(e.currentTarget)}
|
||||
onPointerCancel={(e) => emitRelease(e.currentTarget)}
|
||||
onKeyUp={(e) => {
|
||||
if (["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "Home", "End", "PageUp", "PageDown"].includes(e.key)) {
|
||||
emitRelease(e.currentTarget);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -52,6 +75,9 @@ function ListRow({ label, value, onClick }: { label: string; value: string; onCl
|
||||
|
||||
type LocaleDac = {
|
||||
dac?: {
|
||||
sectionBalanceSensitivity?: string;
|
||||
sectionOutput?: string;
|
||||
sectionSystemInterface?: string;
|
||||
balance?: string;
|
||||
sensitivity?: string;
|
||||
filters?: { label?: string; options?: Array<{ index: number; label: string }> };
|
||||
@@ -137,7 +163,7 @@ export default function AudioPage() {
|
||||
|
||||
<div className="px-4 pb-32">
|
||||
{/* ── 平衡与灵敏度 ── */}
|
||||
<SectionHeader title="平衡与灵敏度" />
|
||||
<SectionHeader title={dacText.sectionBalanceSensitivity ?? "平衡与灵敏度"} />
|
||||
<div className="ios-list-group px-4 py-3 space-y-4">
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -146,14 +172,21 @@ export default function AudioPage() {
|
||||
{localBalance >= 0 ? `+${localBalance.toFixed(1)}` : localBalance.toFixed(1)} dB
|
||||
</span>
|
||||
</div>
|
||||
<CyanSlider value={localBalance} min={-15} max={15} step={0.1}
|
||||
<CyanSlider
|
||||
value={localBalance}
|
||||
min={-15}
|
||||
max={15}
|
||||
step={0.1}
|
||||
onChange={(v) => {
|
||||
isBalanceDragging.current = true;
|
||||
setLocalBalance(v);
|
||||
// 实时调用接口(例如:-13.0 → -130)
|
||||
}}
|
||||
onRelease={(v) => {
|
||||
isBalanceDragging.current = false;
|
||||
setLocalBalance(v);
|
||||
updateSetting({ balance: Math.round(v * 10) });
|
||||
setTimeout(() => { isBalanceDragging.current = false; }, 500);
|
||||
}} />
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="border-t border-white/[0.06]" />
|
||||
<div>
|
||||
@@ -163,19 +196,26 @@ export default function AudioPage() {
|
||||
{localVuSens >= 0 ? `+${localVuSens}` : localVuSens} dB
|
||||
</span>
|
||||
</div>
|
||||
<CyanSlider value={localVuSens} min={-20} max={20}
|
||||
<CyanSlider
|
||||
value={localVuSens}
|
||||
min={-20}
|
||||
max={20}
|
||||
step={1}
|
||||
onChange={(v) => {
|
||||
isVuDragging.current = true;
|
||||
setLocalVuSens(v);
|
||||
// 接口参数需要将显示值乘以 2(例如:10dB -> vuSensor=20)
|
||||
}}
|
||||
onRelease={(v) => {
|
||||
isVuDragging.current = false;
|
||||
setLocalVuSens(v);
|
||||
updateSetting({ vuSensor: Math.round(v * 2) });
|
||||
setTimeout(() => { isVuDragging.current = false; }, 500);
|
||||
}} />
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── 输出特性 ── */}
|
||||
<SectionHeader title="输出特性" />
|
||||
<SectionHeader title={dacText.sectionOutput ?? "输出特性"} />
|
||||
<div className="ios-list-group">
|
||||
<ListRow
|
||||
label={dacText.filters?.label ?? "滤波特性"}
|
||||
@@ -195,7 +235,7 @@ export default function AudioPage() {
|
||||
</div>
|
||||
|
||||
{/* ── 系统与接口 ── */}
|
||||
<SectionHeader title="系统与接口" />
|
||||
<SectionHeader title={dacText.sectionSystemInterface ?? "系统与接口"} />
|
||||
<div className="ios-list-group">
|
||||
<ListRow
|
||||
label={dacText.xlr?.label ?? "XLR 端口极性"}
|
||||
|
||||
Reference in New Issue
Block a user