import { useEffect, useRef, useState } from 'react'; import { ChevronDown, ChevronLeft, ChevronRight, Folder, Loader2, MessageSquarePlus, Pencil, Settings, Trash2, X } from 'lucide-react'; import { compactPath, formatTime } from '../app-core-utils.js'; import { DrawerQuota } from './DrawerQuota.jsx'; // Keep longer than the .drawer transform transition so close animation can finish. const DRAWER_UNMOUNT_DELAY_MS = 230; export function Drawer({ open, onClose, projects, selectedProject, selectedSession, expandedProjectIds, sessionsByProject, loadingProjectId, onToggleProject, onHideProject, onSelectSession, onRenameSession, onDeleteSession, onNewConversation, onSync, syncing, hiddenProjectIds, theme, setTheme, backgroundInert = false }) { const [drawerView, setDrawerView] = useState('main'); const closeButtonRef = useRef(null); const [mounted, setMounted] = useState(open); const [swipedProjectId, setSwipedProjectId] = useState(null); const projectSwipeRef = useRef(null); const closeDrawer = () => { onClose(); }; const hiddenFromAssistive = backgroundInert || !open; const dialogProps = { role: 'dialog', 'aria-modal': open && !backgroundInert ? true : undefined, 'aria-label': '导航菜单', inert: hiddenFromAssistive ? '' : undefined }; useEffect(() => { if (!open || backgroundInert) { return; } closeButtonRef.current?.focus(); }, [backgroundInert, open]); useEffect(() => { if (open) { setMounted(true); return undefined; } const timer = window.setTimeout(() => { setMounted(false); setDrawerView('main'); }, DRAWER_UNMOUNT_DELAY_MS); return () => window.clearTimeout(timer); }, [open]); function handleProjectTouchStart(event, projectId) { const touch = event.touches?.[0]; if (!touch) { return; } projectSwipeRef.current = { projectId, x: touch.clientX, y: touch.clientY }; } function handleProjectTouchMove(event) { const start = projectSwipeRef.current; const touch = event.touches?.[0]; if (!start || !touch) { return; } const deltaX = touch.clientX - start.x; const deltaY = touch.clientY - start.y; if (Math.abs(deltaX) < 28 || Math.abs(deltaX) < Math.abs(deltaY) * 1.15) { return; } if (deltaX < 0) { setSwipedProjectId(start.projectId); } else if (swipedProjectId === start.projectId) { setSwipedProjectId(null); } } function handleProjectTouchEnd() { projectSwipeRef.current = null; } if (!mounted) { return null; } if (drawerView === 'settings') { return ( <>
> ); } const visibleProjects = projects.filter((project) => !hiddenProjectIds?.has(project.id)); return ( <> > ); }