"use client"; import { useState, useCallback, useEffect, useRef } from "react"; import { HugeiconsIcon } from "@hugeicons/react"; import { StructureFolderIcon, PanelRightCloseIcon, PencilEdit01Icon, Tick01Icon } from "@hugeicons/core-free-icons"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; import { usePanel } from "@/hooks/usePanel"; import { FileTree } from "@/components/project/FileTree"; interface RightPanelProps { width?: number; } export function RightPanel({ width }: RightPanelProps) { const { panelOpen, setPanelOpen, workingDirectory, sessionId, sessionTitle, setSessionTitle, previewFile, setPreviewFile } = usePanel(); const [isEditingName, setIsEditingName] = useState(false); const [editName, setEditName] = useState(""); const inputRef = useRef(null); const displayTitle = sessionTitle || (sessionId ? `Session ${sessionId.slice(0, 8)}` : "Untitled Chat"); useEffect(() => { if (isEditingName && inputRef.current) { inputRef.current.focus(); inputRef.current.select(); } }, [isEditingName]); const handleStartEdit = useCallback(() => { setEditName(displayTitle); setIsEditingName(true); }, [displayTitle]); const handleSaveName = useCallback(async () => { const trimmed = editName.trim(); if (!trimmed || !sessionId) { setIsEditingName(false); return; } try { const res = await fetch(`/api/chat/sessions/${sessionId}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ title: trimmed }), }); if (res.ok) { setSessionTitle(trimmed); } } catch { // silently fail } setIsEditingName(false); }, [editName, sessionId, setSessionTitle]); const handleKeyDown = useCallback((e: React.KeyboardEvent) => { if (e.key === "Enter") { handleSaveName(); } else if (e.key === "Escape") { setIsEditingName(false); } }, [handleSaveName]); const handleFileAdd = useCallback((path: string) => { window.dispatchEvent(new CustomEvent('attach-file-to-chat', { detail: { path } })); }, []); const handleFileSelect = useCallback((path: string) => { // Only open preview for text-based files, skip images/videos/binaries const ext = path.split(".").pop()?.toLowerCase() || ""; const NON_PREVIEWABLE = new Set([ "png", "jpg", "jpeg", "gif", "bmp", "ico", "webp", "svg", "avif", "mp4", "mov", "avi", "mkv", "webm", "flv", "wmv", "mp3", "wav", "ogg", "flac", "aac", "wma", "zip", "tar", "gz", "rar", "7z", "bz2", "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "exe", "dll", "so", "dylib", "bin", "dmg", "iso", "woff", "woff2", "ttf", "otf", "eot", ]); if (NON_PREVIEWABLE.has(ext)) return; // Toggle: clicking the same file closes the preview if (previewFile === path) { setPreviewFile(null); } else { setPreviewFile(path); } }, [previewFile, setPreviewFile]); if (!panelOpen) { return (
Open panel
); } return ( ); }