6ef9d95172
- 创建 packages/desktop 模块 - 实现 Tauri 2.0 + React 桌面应用 - 复用 Web 前端代码 - 添加系统托盘功能 - 实现本地文件访问命令 - 配置 Vite + Tauri 集成 - 更新 .gitignore 添加 Rust/Tauri 相关规则
91 lines
2.5 KiB
TypeScript
91 lines
2.5 KiB
TypeScript
/**
|
|
* Chat Page
|
|
*/
|
|
|
|
import { useEffect, useRef } from 'react';
|
|
import { Wifi, WifiOff } from 'lucide-react';
|
|
import { useChat } from '../hooks/useChat';
|
|
import { ChatMessage, StreamingMessage, TypingIndicator } from '../components/ChatMessage';
|
|
import { ChatInput } from '../components/ChatInput';
|
|
|
|
interface ChatPageProps {
|
|
sessionId: string;
|
|
}
|
|
|
|
export function ChatPage({ sessionId }: ChatPageProps) {
|
|
const {
|
|
messages,
|
|
isConnected,
|
|
isLoading,
|
|
streamingContent,
|
|
sendMessage,
|
|
cancelProcessing,
|
|
} = useChat({
|
|
sessionId,
|
|
onError: (error) => {
|
|
console.error('Chat error:', error);
|
|
},
|
|
});
|
|
|
|
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
|
|
// 自动滚动到底部
|
|
useEffect(() => {
|
|
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
}, [messages, streamingContent]);
|
|
|
|
return (
|
|
<div className="flex-1 flex flex-col h-screen">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between px-6 py-3 border-b border-gray-700 bg-gray-800">
|
|
<h1 className="text-lg font-medium">Chat</h1>
|
|
<div className="flex items-center gap-2 text-sm">
|
|
{isConnected ? (
|
|
<>
|
|
<Wifi size={16} className="text-green-500" />
|
|
<span className="text-green-500">Connected</span>
|
|
</>
|
|
) : (
|
|
<>
|
|
<WifiOff size={16} className="text-red-500" />
|
|
<span className="text-red-500">Disconnected</span>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Messages */}
|
|
<div className="flex-1 overflow-y-auto p-6">
|
|
<div className="max-w-4xl mx-auto space-y-4">
|
|
{messages.length === 0 && !isLoading && (
|
|
<div className="text-center py-20">
|
|
<h2 className="text-2xl font-semibold mb-2">Start a conversation</h2>
|
|
<p className="text-gray-400">
|
|
Type a message below to begin chatting with your AI assistant.
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
{messages.map((message) => (
|
|
<ChatMessage key={message.id} message={message} />
|
|
))}
|
|
|
|
{streamingContent && <StreamingMessage content={streamingContent} />}
|
|
|
|
{isLoading && !streamingContent && <TypingIndicator />}
|
|
|
|
<div ref={messagesEndRef} />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Input */}
|
|
<ChatInput
|
|
onSend={sendMessage}
|
|
onCancel={cancelProcessing}
|
|
isLoading={isLoading}
|
|
disabled={!isConnected}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|