mirror of
https://github.com/JezzWTF/vibepod.git
synced 2026-06-01 15:22:14 +00:00
feat: surface VIBEPOD_DEVICE (CPU/CUDA) in the frontend header
This commit is contained in:
@@ -23,6 +23,7 @@ export async function GET() {
|
|||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{
|
{
|
||||||
status,
|
status,
|
||||||
|
device: data.device ?? null,
|
||||||
message: data.message,
|
message: data.message,
|
||||||
progress: data.progress ?? null,
|
progress: data.progress ?? null,
|
||||||
voices: data.voices ?? [],
|
voices: data.voices ?? [],
|
||||||
|
|||||||
+43
-18
@@ -3,6 +3,7 @@
|
|||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
type ServerStatus = "checking" | "downloading" | "loading" | "online" | "error" | "offline";
|
type ServerStatus = "checking" | "downloading" | "loading" | "online" | "error" | "offline";
|
||||||
|
type Device = "cpu" | "cuda" | null;
|
||||||
|
|
||||||
// Polling intervals: poll quickly until the server is online, then slow down.
|
// Polling intervals: poll quickly until the server is online, then slow down.
|
||||||
const FAST_INTERVAL_MS = 3000; // while checking / loading
|
const FAST_INTERVAL_MS = 3000; // while checking / loading
|
||||||
@@ -10,6 +11,7 @@ const SLOW_INTERVAL_MS = 30000; // once online
|
|||||||
|
|
||||||
export default function Header() {
|
export default function Header() {
|
||||||
const [status, setStatus] = useState<ServerStatus>("checking");
|
const [status, setStatus] = useState<ServerStatus>("checking");
|
||||||
|
const [device, setDevice] = useState<Device>(null);
|
||||||
const [message, setMessage] = useState<string | undefined>();
|
const [message, setMessage] = useState<string | undefined>();
|
||||||
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||||
|
|
||||||
@@ -20,6 +22,7 @@ export default function Header() {
|
|||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const newStatus: ServerStatus = (data.status as ServerStatus) ?? "offline";
|
const newStatus: ServerStatus = (data.status as ServerStatus) ?? "offline";
|
||||||
setStatus(newStatus);
|
setStatus(newStatus);
|
||||||
|
setDevice((data.device as Device) ?? null);
|
||||||
setMessage(data.message);
|
setMessage(data.message);
|
||||||
|
|
||||||
// Switch to slow polling once we know the server is online
|
// Switch to slow polling once we know the server is online
|
||||||
@@ -34,6 +37,7 @@ export default function Header() {
|
|||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
setStatus("offline");
|
setStatus("offline");
|
||||||
|
setDevice(null);
|
||||||
setMessage(undefined);
|
setMessage(undefined);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -90,6 +94,25 @@ export default function Header() {
|
|||||||
|
|
||||||
const cfg = statusConfig[status];
|
const cfg = statusConfig[status];
|
||||||
|
|
||||||
|
// Device badge — only shown once the server is online and device is known
|
||||||
|
const deviceBadge = status === "online" && device ? (
|
||||||
|
<span
|
||||||
|
className="px-2 py-0.5 rounded-full text-xs font-semibold tracking-wide uppercase"
|
||||||
|
style={{
|
||||||
|
background: device === "cuda"
|
||||||
|
? "var(--accent-violet-dim)"
|
||||||
|
: "var(--accent-teal-dim)",
|
||||||
|
color: device === "cuda"
|
||||||
|
? "var(--accent-violet)"
|
||||||
|
: "var(--accent-teal)",
|
||||||
|
border: `1px solid ${device === "cuda" ? "var(--accent-violet-dim)" : "var(--accent-teal-dim)"}`,
|
||||||
|
}}
|
||||||
|
title={device === "cuda" ? "Running on NVIDIA GPU" : "Running on CPU"}
|
||||||
|
>
|
||||||
|
{device.toUpperCase()}
|
||||||
|
</span>
|
||||||
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
className="border-b px-6 py-4 flex items-center justify-between"
|
className="border-b px-6 py-4 flex items-center justify-between"
|
||||||
@@ -128,27 +151,29 @@ export default function Header() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div className="flex items-center gap-2">
|
||||||
className={`flex items-center gap-2 px-3 py-1.5 rounded-full text-xs font-medium border ${cfg.ring}`}
|
{deviceBadge}
|
||||||
style={{
|
<div
|
||||||
background: "var(--background)",
|
className={`flex items-center gap-2 px-3 py-1.5 rounded-full text-xs font-medium border ${cfg.ring}`}
|
||||||
borderColor: "var(--border)",
|
style={{
|
||||||
}}
|
background: "var(--background)",
|
||||||
title={message}
|
borderColor: "var(--border)",
|
||||||
>
|
}}
|
||||||
<span className="relative flex h-2 w-2">
|
title={message}
|
||||||
{cfg.pulse && (
|
>
|
||||||
|
<span className="relative flex h-2 w-2">
|
||||||
|
{cfg.pulse && (
|
||||||
|
<span
|
||||||
|
className={`animate-ping absolute inline-flex h-full w-full rounded-full opacity-75 ${cfg.color}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<span
|
<span
|
||||||
className={`animate-ping absolute inline-flex h-full w-full rounded-full opacity-75 ${cfg.color}`}
|
className={`relative inline-flex rounded-full h-2 w-2 ${cfg.color}`}
|
||||||
/>
|
/>
|
||||||
)}
|
</span>
|
||||||
<span
|
<span style={{ color: "var(--foreground)" }}>{cfg.label}</span>
|
||||||
className={`relative inline-flex rounded-full h-2 w-2 ${cfg.color}`}
|
</div>
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span style={{ color: "var(--foreground)" }}>{cfg.label}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user