82 lines
2.5 KiB
TypeScript
82 lines
2.5 KiB
TypeScript
import { useRef, useEffect, useState } from 'react';
|
|
import { useNavigate, useLocation } from 'react-router';
|
|
import { useChatSessions } from 'state/useChatSessions';
|
|
import { SessionBar, EmbeddableChat, type UsePiChatType, type Attachment } from 'officerdev';
|
|
import { Card } from '@/components/Card';
|
|
|
|
export type { Attachment };
|
|
|
|
type ChatPanelProps = {
|
|
chat: UsePiChatType;
|
|
};
|
|
|
|
export const ChatScreen = ({ chat }: ChatPanelProps) => {
|
|
const { isConnected, isGenerating, sessionId, setSelectedModel, sendPrompt } = chat;
|
|
|
|
const location = useLocation();
|
|
const navigate = useNavigate();
|
|
const [fullscreen, setFullscreen] = useState(false);
|
|
|
|
const { sessions, deleteSession } = useChatSessions();
|
|
const sessionTitle = sessionId ? sessions.find((s) => s.id === sessionId)?.title : undefined;
|
|
const listPath = '/chat';
|
|
|
|
// Capture initial state from navigation
|
|
const locationState = location.state as {
|
|
initialMessage?: string;
|
|
prefillInput?: string;
|
|
model?: string;
|
|
cwd?: { root?: string; path: string };
|
|
attachmentIds?: string[];
|
|
images?: { filename: string; dataUrl: string }[];
|
|
} | null;
|
|
|
|
const initialMessage = locationState?.initialMessage
|
|
? {
|
|
text: locationState.initialMessage,
|
|
attachmentIds: locationState.attachmentIds,
|
|
images: locationState.images,
|
|
cwd: locationState.cwd,
|
|
}
|
|
: undefined;
|
|
|
|
const defaultInput = locationState?.prefillInput ?? '';
|
|
const initialModel = locationState?.model ?? null;
|
|
|
|
// Clear location state after capturing
|
|
useEffect(() => {
|
|
if (locationState) {
|
|
window.history.replaceState({}, '', location.pathname);
|
|
}
|
|
}, []);
|
|
|
|
return (
|
|
<Card
|
|
className={`flex flex-col overflow-hidden transition-all duration-200 rounded-none border-0 md:rounded-xl md:border-2 ${fullscreen ? 'fixed inset-0 m-auto z-50 w-[90vw] h-[calc(90vh-4.5rem)]' : 'h-full'
|
|
}`}
|
|
>
|
|
<SessionBar
|
|
listPath={listPath}
|
|
sessionTitle={sessionTitle}
|
|
isConnected={isConnected}
|
|
isGenerating={isGenerating}
|
|
fullscreen={fullscreen}
|
|
onDelete={async () => {
|
|
if (!sessionId) return;
|
|
await deleteSession(sessionId);
|
|
navigate(listPath);
|
|
}}
|
|
onToggleFullscreen={() => setFullscreen((f) => !f)}
|
|
/>
|
|
|
|
<EmbeddableChat
|
|
sessionId={sessionId ?? undefined}
|
|
initialModel={initialModel}
|
|
initialMessage={initialMessage}
|
|
defaultInput={defaultInput}
|
|
className="flex-1 min-h-0"
|
|
/>
|
|
</Card>
|
|
);
|
|
};
|