"use client"; import { useEffect, useState, useCallback } from "react"; import { X } from "@/components/ui/icon"; import type { Message, MessagesResponse, ChatSession } from "@/types"; import { ChatView } from "@/components/chat/ChatView"; import { Button } from "@/components/ui/button"; import { usePanel } from "@/hooks/usePanel"; import { cn } from "@/lib/utils"; import { useTranslation } from "@/hooks/useTranslation"; interface SplitColumnProps { sessionId: string; isActive: boolean; onClose: () => void; onFocus: () => void; } export function SplitColumn({ sessionId, isActive, onClose, onFocus }: SplitColumnProps) { const [messages, setMessages] = useState([]); const [hasMore, setHasMore] = useState(false); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [sessionTitle, setSessionTitle] = useState(""); const [sessionModel, setSessionModel] = useState(""); const [sessionProviderId, setSessionProviderId] = useState(""); const [sessionInfoLoaded, setSessionInfoLoaded] = useState(false); const [sessionMode, setSessionMode] = useState(""); const [projectName, setProjectName] = useState(""); const [sessionWorkingDir, setSessionWorkingDir] = useState(""); const { setWorkingDirectory, setSessionId, setSessionTitle: setPanelSessionTitle, setPanelOpen } = usePanel(); const { t } = useTranslation(); // Load session metadata useEffect(() => { let cancelled = false; setSessionInfoLoaded(false); setSessionModel(""); setSessionProviderId(""); async function loadSession() { try { const res = await fetch(`/api/chat/sessions/${sessionId}`); if (cancelled) return; if (res.ok) { const data: { session: ChatSession } = await res.json(); setSessionTitle(data.session.title || t("chat.newConversation")); setSessionModel(data.session.model || ""); setSessionProviderId(data.session.provider_id || ""); setSessionMode(data.session.mode || "code"); setProjectName(data.session.project_name || ""); setSessionWorkingDir(data.session.working_directory || ""); } } catch { // ignore } finally { if (!cancelled) setSessionInfoLoaded(true); } } loadSession(); return () => { cancelled = true; }; }, [sessionId, t]); // Load messages useEffect(() => { let cancelled = false; setLoading(true); setError(null); setMessages([]); setHasMore(false); async function loadMessages() { try { const res = await fetch(`/api/chat/sessions/${sessionId}/messages?limit=30`); if (cancelled) return; if (!res.ok) { if (res.status === 404) { setError("Session not found"); return; } throw new Error("Failed to load messages"); } const data: MessagesResponse = await res.json(); if (cancelled) return; setMessages(data.messages); setHasMore(data.hasMore ?? false); } catch (err) { if (cancelled) return; setError(err instanceof Error ? err.message : "Failed to load messages"); } finally { if (!cancelled) setLoading(false); } } loadMessages(); return () => { cancelled = true; }; }, [sessionId]); // When this column becomes active, sync PanelContext useEffect(() => { if (!isActive) return; if (sessionWorkingDir) { setWorkingDirectory(sessionWorkingDir); localStorage.setItem("codepilot:last-working-directory", sessionWorkingDir); window.dispatchEvent(new Event("refresh-file-tree")); } else { // Clear stale directory from previous column so FileTree doesn't show old project setWorkingDirectory(''); } setSessionId(sessionId); setPanelOpen(true); if (sessionTitle) { setPanelSessionTitle(sessionTitle); } }, [isActive, sessionId, sessionWorkingDir, sessionTitle, setWorkingDirectory, setSessionId, setPanelSessionTitle, setPanelOpen]); const handleClose = useCallback((e: React.MouseEvent) => { e.stopPropagation(); onClose(); }, [onClose]); if (loading || !sessionInfoLoaded) { return (
); } if (error) { return (

{error}

); } return (
{/* Compact title bar */}
{projectName && ( <> {projectName} / )} {sessionTitle}
{/* ChatView */}
); }