Internal error occurred but is skipped: FindTagsByCommitIDs

Files
CamTalk/frontend/src/App.tsx

102 lines
2.9 KiB
TypeScript
Raw Normal View History

// ============================================================
// CamTalk — 主应用组件
// ============================================================
import { useVisionSession } from "./hooks/useVisionSession";
import { VideoPreview } from "./components/VideoPreview";
import { ChatPanel } from "./components/ChatPanel";
import { ToastContainer } from "./components/Toast";
import "./App.css";
function App() {
const {
messages,
currentReply,
isProcessing,
isSpeaking,
isVADReady,
vadError,
connectionStatus,
videoRef,
stream,
startSession,
stopSession,
interrupt,
} = useVisionSession();
const isConnected = connectionStatus === "connected";
return (
<div className="app">
<header className="app-header">
<h1>CamTalk</h1>
<span className={`status status--${connectionStatus}`}>
{isConnected
? "已连接"
: connectionStatus === "connecting"
? "连接中..."
: "未连接"}
</span>
</header>
<main className="app-main">
<div className="video-section">
<VideoPreview ref={videoRef} isStreaming={!!stream} />
{isSpeaking && <div className="vad-indicator">🎤 ...</div>}
{isConnected && !isVADReady && !vadError && (
<div className="vad-indicator vad-indicator--loading">
...
</div>
)}
{vadError && (
<div className="vad-indicator vad-indicator--error">
{vadError}
</div>
)}
{isProcessing && (
<div className="video-overlay">
<div className="video-overlay__spinner" />
</div>
)}
</div>
<div className="chat-section">
{connectionStatus === "disconnected" && messages.length > 0 && (
<div className="system-message system-message--warning">
...
</div>
)}
<ChatPanel
messages={messages}
currentReply={currentReply}
connectionStatus={connectionStatus}
/>
</div>
</main>
<footer className="app-footer">
{!isConnected ? (
<button className="btn btn--primary" onClick={startSession}>
{connectionStatus === "connecting" ? "连接中..." : "开始对话"}
</button>
) : (
<>
<button className="btn btn--secondary" onClick={stopSession}>
</button>
{isProcessing && (
<button className="btn btn--warning" onClick={interrupt}>
</button>
)}
</>
)}
</footer>
<ToastContainer />
</div>
);
}
export default App;