新增社区页面路由,更新底部导航以移除占位符,优化音量控制按钮样式和功能
This commit is contained in:
@@ -18,6 +18,7 @@ import IOPage from "./pages/IOPage";
|
|||||||
import VUPage from "./pages/VUPage";
|
import VUPage from "./pages/VUPage";
|
||||||
import SelectPage from "./pages/SelectPage";
|
import SelectPage from "./pages/SelectPage";
|
||||||
import AIPage from "./pages/AIPage";
|
import AIPage from "./pages/AIPage";
|
||||||
|
import CommunityPage from "./pages/CommunityPage";
|
||||||
|
|
||||||
function AppRouter() {
|
function AppRouter() {
|
||||||
return (
|
return (
|
||||||
@@ -35,6 +36,7 @@ function AppRouter() {
|
|||||||
<Route path="/vu" component={VUPage} />
|
<Route path="/vu" component={VUPage} />
|
||||||
<Route path="/select" component={SelectPage} />
|
<Route path="/select" component={SelectPage} />
|
||||||
<Route path="/ai" component={AIPage} />
|
<Route path="/ai" component={AIPage} />
|
||||||
|
<Route path="/community" component={CommunityPage} />
|
||||||
<Route path="/404" component={NotFound} />
|
<Route path="/404" component={NotFound} />
|
||||||
<Route component={NotFound} />
|
<Route component={NotFound} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|||||||
@@ -19,11 +19,10 @@ interface NavItem {
|
|||||||
path: string;
|
path: string;
|
||||||
icon: React.ComponentType<{ size?: number; className?: string }>;
|
icon: React.ComponentType<{ size?: number; className?: string }>;
|
||||||
label: string;
|
label: string;
|
||||||
placeholder?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const NAV_ITEMS: NavItem[] = [
|
const NAV_ITEMS: NavItem[] = [
|
||||||
{ path: "/community", icon: MessageSquare, label: "社区", placeholder: true },
|
{ path: "/community", icon: MessageSquare, label: "社区" },
|
||||||
{ path: "/eq", icon: Sliders, label: "HP-EQ" },
|
{ path: "/eq", icon: Sliders, label: "HP-EQ" },
|
||||||
{ path: "/", icon: Home, label: "主页" },
|
{ path: "/", icon: Home, label: "主页" },
|
||||||
{ path: "/effects", icon: Activity, label: "Effect" },
|
{ path: "/effects", icon: Activity, label: "Effect" },
|
||||||
@@ -53,7 +52,7 @@ export default function BottomNav() {
|
|||||||
const Icon = item.icon;
|
const Icon = item.icon;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link key={item.path} href={item.placeholder ? "#" : item.path}>
|
<Link key={item.path} href={item.path}>
|
||||||
<div className="flex flex-col items-center justify-center relative pt-2.5 pb-1.5 px-3">
|
<div className="flex flex-col items-center justify-center relative pt-2.5 pb-1.5 px-3">
|
||||||
{/* Active indicator bar */}
|
{/* Active indicator bar */}
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import BottomNav from "@/components/BottomNav";
|
||||||
|
import { MessageSquare } from "lucide-react";
|
||||||
|
|
||||||
|
export default function CommunityPage() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="h-[100dvh] flex flex-col pb-[calc(env(safe-area-inset-bottom,0px)+56px)]"
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
"radial-gradient(120% 80% at 50% 0%, rgba(12, 24, 30, 0.45) 0%, rgba(6, 9, 16, 0.92) 38%, #04060d 100%)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<main className="relative flex-1 flex items-center justify-center px-6">
|
||||||
|
<div className="flex flex-col items-center text-center -translate-y-8">
|
||||||
|
<div
|
||||||
|
className="w-[96px] h-[96px] rounded-full flex items-center justify-center mb-7"
|
||||||
|
style={{
|
||||||
|
background: "radial-gradient(circle at 35% 30%, rgba(0,255,246,0.18), rgba(0,255,246,0.07))",
|
||||||
|
boxShadow: "0 0 34px rgba(0,255,246,0.18), inset 0 0 24px rgba(0,255,246,0.08)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MessageSquare size={38} className="text-[#00FFF6]" strokeWidth={2.2} />
|
||||||
|
</div>
|
||||||
|
<p className="text-white/85 text-[42px] leading-none font-semibold tracking-wide mb-3">Coming Soon</p>
|
||||||
|
<p className="text-white/40 text-[22px] leading-none">Community features are under development</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
<BottomNav />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -289,12 +289,6 @@ function FreqChart({
|
|||||||
onClick={() => toast.info("已复制到 B")}>
|
onClick={() => toast.info("已复制到 B")}>
|
||||||
复制到 B
|
复制到 B
|
||||||
</button>
|
</button>
|
||||||
<div className="flex-1" />
|
|
||||||
<button
|
|
||||||
className="px-2.5 py-1 rounded-[6px] text-[11px] font-bold"
|
|
||||||
style={{ background: "rgba(245,158,11,0.2)", border: "1px solid rgba(245,158,11,0.4)", color: "#f59e0b" }}>
|
|
||||||
DIFF
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* SVG chart */}
|
{/* SVG chart */}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ type HomeLocale = NonNullable<(typeof localeZh)["home"]>;
|
|||||||
|
|
||||||
// ── Volume in dB (0-200 → -100dB to 0dB) ──
|
// ── Volume in dB (0-200 → -100dB to 0dB) ──
|
||||||
function volToDB(v: number) {
|
function volToDB(v: number) {
|
||||||
if (v === 0) return "-∞";
|
if (v === 0) return "-100dB";
|
||||||
const db = (v - 200) / 2;
|
const db = (v - 200) / 2;
|
||||||
return `${db >= 0 ? "+" : ""}${db.toFixed(1)}dB`;
|
return `${db >= 0 ? "+" : ""}${db.toFixed(1)}dB`;
|
||||||
}
|
}
|
||||||
@@ -165,6 +165,12 @@ export default function Home() {
|
|||||||
const vuLabel = `${homeText.vu ?? "VU表"}${(ds.vu ?? 0) + 1}`;
|
const vuLabel = `${homeText.vu ?? "VU表"}${(ds.vu ?? 0) + 1}`;
|
||||||
const bypassOn = (ds.dsp_enable ?? 0) === 0;
|
const bypassOn = (ds.dsp_enable ?? 0) === 0;
|
||||||
|
|
||||||
|
// Home 的 volume 取值为 0..200,对应 dB = (v - 200) / 2
|
||||||
|
// 因此 1 个 volume 单位 = 0.5dB
|
||||||
|
// AudioPage 的 soundStep:0->0.5dB, 1->1dB, 2->2dB, 3->3dB
|
||||||
|
// 换算为 volume 单位:0.5/1/2/3 dB -> 1/2/4/6
|
||||||
|
const fineVolumeStep = [1, 2, 4, 6][ds.soundStep ?? 1] ?? 1;
|
||||||
|
|
||||||
// Slider fill % (0-200 → 0-100%)
|
// Slider fill % (0-200 → 0-100%)
|
||||||
const fillPct = (localVol / 200) * 100;
|
const fillPct = (localVol / 200) * 100;
|
||||||
// Knob angle (map 0..200 -> -135..+135 degrees)
|
// Knob angle (map 0..200 -> -135..+135 degrees)
|
||||||
@@ -369,10 +375,48 @@ export default function Home() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/* dB value */}
|
{/* dB value */}
|
||||||
<div className="text-center mt-1">
|
<div className="mt-[6px] flex items-center justify-center gap-3">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-label="Decrease volume"
|
||||||
|
disabled={localVol <= 0}
|
||||||
|
className="w-10 h-10 rounded-full flex items-center justify-center transition-all active:scale-95 disabled:opacity-30 disabled:cursor-not-allowed"
|
||||||
|
style={{
|
||||||
|
background: "rgba(44,44,46,0.6)",
|
||||||
|
border: "1px solid rgba(255,255,255,0.08)",
|
||||||
|
color: "rgba(255,255,255,0.55)",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
const next = Math.max(0, Math.min(200, localVol - fineVolumeStep));
|
||||||
|
setLocalVol(next);
|
||||||
|
setVolume(next);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="text-[20px] leading-none">-</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<span className="text-[22px] font-bold tracking-tight" style={{ color: "#00FFF6" }}>
|
<span className="text-[22px] font-bold tracking-tight" style={{ color: "#00FFF6" }}>
|
||||||
{volToDB(localVol)}
|
{volToDB(localVol)}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-label="Increase volume"
|
||||||
|
disabled={localVol >= 200}
|
||||||
|
className="w-10 h-10 rounded-full flex items-center justify-center transition-all active:scale-95 disabled:opacity-30 disabled:cursor-not-allowed"
|
||||||
|
style={{
|
||||||
|
background: "rgba(44,44,46,0.6)",
|
||||||
|
border: "1px solid rgba(255,255,255,0.08)",
|
||||||
|
color: "rgba(255,255,255,0.55)",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
const next = Math.max(0, Math.min(200, localVol + fineVolumeStep));
|
||||||
|
setLocalVol(next);
|
||||||
|
setVolume(next);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="text-[20px] leading-none">+</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Bluetooth info */}
|
{/* Bluetooth info */}
|
||||||
|
|||||||
Reference in New Issue
Block a user