/** * Breadcrumb navigation for the active file in the editor. * * Each segment is clickable — expands and scrolls the folder in the file tree. */ import { useCallback, useMemo } from 'react'; import { useStore } from '@renderer/store'; import { isWindowsishPath, joinPath, splitPath } from '@shared/utils/platformPath'; import { ChevronRight } from 'lucide-react'; import { useShallow } from 'zustand/react/shallow'; import { FileIcon } from './FileIcon'; // ============================================================================= // Component // ============================================================================= export const EditorBreadcrumb = (): React.ReactElement | null => { const { activeTabId, projectPath } = useStore( useShallow((s) => ({ activeTabId: s.editorActiveTabId, projectPath: s.editorProjectPath, })) ); const expandDirectory = useStore((s) => s.expandDirectory); const segments = useMemo(() => { if (!activeTabId) return []; if (!projectPath) return splitPath(activeTabId); const fullParts = splitPath(activeTabId); const rootParts = splitPath(projectPath); if (rootParts.length === 0) return fullParts; const win = isWindowsishPath(projectPath); const eq = (a: string, b: string) => (win ? a.toLowerCase() === b.toLowerCase() : a === b); const hasPrefix = fullParts.length >= rootParts.length && rootParts.every((seg, i) => eq(seg, fullParts[i])); return hasPrefix ? fullParts.slice(rootParts.length) : fullParts; }, [activeTabId, projectPath]); const handleSegmentClick = useCallback( (segmentIndex: number): void => { if (!projectPath) return; const dirSegments = segments.slice(0, segmentIndex + 1); const dirPath = joinPath(projectPath, ...dirSegments); void expandDirectory(dirPath); }, [segments, projectPath, expandDirectory] ); if (segments.length === 0) return null; const fileName = segments[segments.length - 1]; return (
{segments.map((segment, idx) => { const isLast = idx === segments.length - 1; return ( {idx > 0 && } {isLast ? ( {segment} ) : ( )} ); })}
); };