This commit is contained in:
kacper 2026-03-06 22:51:19 -05:00
parent 6acf267d48
commit b7614eb3f8
4794 changed files with 1280808 additions and 1546 deletions

61
frontend/src/App.tsx Normal file
View file

@ -0,0 +1,61 @@
import { useCallback, useEffect } from "preact/hooks";
import { AgentIndicator } from "./components/AgentIndicator";
import { ControlBar, VoiceStatus } from "./components/Controls";
import { LogPanel } from "./components/LogPanel";
import { ToastContainer } from "./components/Toast";
import { useAudioMeter } from "./hooks/useAudioMeter";
import { usePTT } from "./hooks/usePTT";
import { useWebRTC } from "./hooks/useWebRTC";
export function App() {
const rtc = useWebRTC();
const audioLevel = useAudioMeter(rtc.remoteStream);
const { agentStateOverride, handlePointerDown, handlePointerUp } = usePTT({
connected: rtc.connected,
onSendPtt: (pressed) => rtc.sendJson({ type: "voice-ptt", pressed }),
onBootstrap: rtc.connect,
});
const effectiveAgentState = agentStateOverride ?? rtc.agentState;
useEffect(() => {
document.addEventListener("pointerdown", handlePointerDown, { passive: false });
document.addEventListener("pointerup", handlePointerUp, { passive: false });
document.addEventListener("pointercancel", handlePointerUp, { passive: false });
return () => {
document.removeEventListener("pointerdown", handlePointerDown);
document.removeEventListener("pointerup", handlePointerUp);
document.removeEventListener("pointercancel", handlePointerUp);
};
}, [handlePointerDown, handlePointerUp]);
const handleReset = useCallback(async () => {
await rtc.connect();
rtc.sendJson({ type: "command", command: "reset" });
}, [rtc]);
const handleChoice = useCallback(
(requestId: string, value: string) => {
rtc.sendJson({ type: "ui-response", request_id: requestId, value });
},
[rtc],
);
return (
<>
<ControlBar onReset={handleReset} />
<LogPanel lines={rtc.logLines} />
<AgentIndicator
state={effectiveAgentState}
connected={rtc.connected}
connecting={rtc.connecting}
audioLevel={audioLevel}
onPointerDown={() => {}}
onPointerUp={() => {}}
/>
<VoiceStatus text={rtc.voiceStatus} visible={rtc.statusVisible} />
<ToastContainer toasts={rtc.toasts} onDismiss={rtc.dismissToast} onChoice={handleChoice} />
</>
);
}