import { useCallback } from 'react'; import { Folder, ChevronDown, MoreVertical, Palette, Monitor, Moon, Sun, Undo2, Redo2, RotateCcw, Trash2, Search, LogOut, } from 'lucide-react'; import { cn } from '@/lib/utils'; import { formatShortcut, type ThemeMode, useAppStore } from '@/store/app-store'; import { initializeProject } from '@/lib/project-init'; import type { Project } from '@/lib/electron'; import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuLabel, } from '@/components/ui/dropdown-menu'; import { DndContext, closestCenter } from '@dnd-kit/core'; import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'; import { SortableProjectItem, ThemeMenuItem } from './'; import { PROJECT_DARK_THEMES, PROJECT_LIGHT_THEMES, THEME_SUBMENU_CONSTANTS } from '../constants'; import { useProjectPicker, useDragAndDrop, useProjectTheme } from '../hooks'; import { useKeyboardShortcutsConfig } from '@/hooks/use-keyboard-shortcuts'; /** * Props for the ProjectSelectorWithOptions component. * Defines the interface for the project selector dropdown with additional options menu. */ interface ProjectSelectorWithOptionsProps { /** Whether the sidebar is currently expanded */ sidebarOpen: boolean; /** Whether the project picker dropdown is currently open */ isProjectPickerOpen: boolean; /** Callback to control the project picker dropdown open state */ setIsProjectPickerOpen: (value: boolean | ((prev: boolean) => boolean)) => void; /** Callback to show the delete project confirmation dialog */ setShowDeleteProjectDialog: (show: boolean) => void; /** Callback to show the remove from automaker confirmation dialog */ setShowRemoveFromAutomakerDialog: (show: boolean) => void; } /** * A project selector component with search, drag-and-drop reordering, and options menu. * * Features: * - Searchable dropdown for quick project switching * - Drag-and-drop reordering of projects * - Project-specific theme selection with live preview * - Project history navigation (previous/next) * - Option to move project to trash * * The component uses viewport-aware positioning via THEME_SUBMENU_CONSTANTS * for consistent submenu behavior across the application. * * @param props - Component props * @returns The rendered project selector or null if sidebar is closed or no projects exist */ export function ProjectSelectorWithOptions({ sidebarOpen, isProjectPickerOpen, setIsProjectPickerOpen, setShowDeleteProjectDialog, setShowRemoveFromAutomakerDialog, }: ProjectSelectorWithOptionsProps) { const { projects, currentProject, projectHistory, setCurrentProject, reorderProjects, cyclePrevProject, cycleNextProject, clearProjectHistory, } = useAppStore(); const shortcuts = useKeyboardShortcutsConfig(); // Wrap setCurrentProject to ensure .automaker is initialized before switching const setCurrentProjectWithInit = useCallback( async (p: Project) => { try { // Ensure .automaker directory structure exists before switching await initializeProject(p.path); } catch (error) { console.error('Failed to initialize project during switch:', error); // Continue with switch even if initialization fails - // the project may already be initialized } setCurrentProject(p); }, [setCurrentProject] ); const { projectSearchQuery, setProjectSearchQuery, selectedProjectIndex, projectSearchInputRef, scrollContainerRef, filteredProjects, } = useProjectPicker({ projects, currentProject, isProjectPickerOpen, setIsProjectPickerOpen, setCurrentProject: setCurrentProjectWithInit, }); const { sensors, handleDragEnd } = useDragAndDrop({ projects, reorderProjects }); const { globalTheme, setProjectTheme, setPreviewTheme, handlePreviewEnter, handlePreviewLeave } = useProjectTheme(); const handleSelectProject = useCallback( async (p: Project) => { await setCurrentProjectWithInit(p); setIsProjectPickerOpen(false); }, [setCurrentProjectWithInit, setIsProjectPickerOpen] ); if (!sidebarOpen || projects.length === 0) { return null; } return (
↑↓ navigate{' '} |{' '} ↵ select{' '} |{' '} esc close