"use client" import { useCallback, useEffect, useRef, useState, type KeyboardEvent as ReactKeyboardEvent, } from "react" import { Columns2, EllipsisVertical, FileCode2, Menu, MessageSquare, PanelLeft, PanelRight, Search, Settings, SquareTerminal, } from "lucide-react" import { useTranslations } from "next-intl" import { openSettingsWindow } from "@/lib/api" import { useAppWorkspace } from "@/contexts/app-workspace-context" import { useActiveFolder } from "@/contexts/active-folder-context" import { isDesktop, openFileDialog } from "@/lib/platform" import { Button } from "@/components/ui/button" import { useSidebarContext } from "@/contexts/sidebar-context" import { useAuxPanelContext } from "@/contexts/aux-panel-context" import { useTerminalContext } from "@/contexts/terminal-context" import { useTabContext } from "@/contexts/tab-context" import { useWorkspaceContext } from "@/contexts/workspace-context" import { useIsMac } from "@/hooks/use-is-mac" import { useShortcutSettings } from "@/hooks/use-shortcut-settings" import { formatShortcutLabel, matchShortcutEvent, } from "@/lib/keyboard-shortcuts" import { AppTitleBar } from "./app-title-bar" import { BranchDropdown } from "./branch-dropdown" import { CommandDropdown } from "./command-dropdown" import { NewFolderDropdown } from "./new-folder-dropdown" import { SearchCommandDialog } from "@/components/conversations/search-command-dialog" import { DirectoryBrowserDialog } from "@/components/shared/directory-browser-dialog" import { cn } from "@/lib/utils" import { useIsMobile } from "@/hooks/use-mobile" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" const MODE_TABS = [ { mode: "conversation", titleKey: "conversation", icon: MessageSquare, }, { mode: "fusion", titleKey: "fusion", icon: Columns2, }, { mode: "files", titleKey: "files", icon: FileCode2, }, ] as const export function FolderTitleBar() { const tModes = useTranslations("Folder.modes") const tTitleBar = useTranslations("Folder.folderTitleBar") const { openFolder } = useAppWorkspace() const { activeFolder } = useActiveFolder() const { isOpen, toggle } = useSidebarContext() const { isOpen: auxPanelOpen, toggle: toggleAuxPanel } = useAuxPanelContext() const { isOpen: terminalOpen, toggle: toggleTerminal } = useTerminalContext() const { openNewConversationTab } = useTabContext() const { mode, setMode } = useWorkspaceContext() const isMac = useIsMac() const { shortcuts } = useShortcutSettings() const [searchOpen, setSearchOpen] = useState(false) const [browserOpen, setBrowserOpen] = useState(false) const handleOpenFolder = useCallback(async () => { if (isDesktop()) { try { const result = await openFileDialog({ directory: true, multiple: false, }) if (!result) return const selected = Array.isArray(result) ? result[0] : result await openFolder(selected) } catch (err) { console.error("[FolderTitleBar] failed to open folder:", err) } } else { setBrowserOpen(true) } }, [openFolder]) const handleOpenSettings = useCallback(() => { openSettingsWindow().catch((err) => { console.error("[FolderTitleBar] failed to open settings:", err) }) }, []) useEffect(() => { function handleKeyDown(e: KeyboardEvent) { if (matchShortcutEvent(e, shortcuts.toggle_search)) { e.preventDefault() setSearchOpen((prev) => !prev) return } if (matchShortcutEvent(e, shortcuts.toggle_sidebar)) { e.preventDefault() toggle() return } if (matchShortcutEvent(e, shortcuts.toggle_terminal)) { e.preventDefault() toggleTerminal() return } if (matchShortcutEvent(e, shortcuts.toggle_aux_panel)) { e.preventDefault() toggleAuxPanel() return } if (matchShortcutEvent(e, shortcuts.new_conversation)) { if (!activeFolder) return e.preventDefault() openNewConversationTab(activeFolder.id, activeFolder.path) return } if (matchShortcutEvent(e, shortcuts.open_folder)) { e.preventDefault() void handleOpenFolder() return } if (matchShortcutEvent(e, shortcuts.open_settings)) { e.preventDefault() handleOpenSettings() } } document.addEventListener("keydown", handleKeyDown) return () => document.removeEventListener("keydown", handleKeyDown) }, [ activeFolder, handleOpenFolder, handleOpenSettings, openNewConversationTab, shortcuts, toggle, toggleAuxPanel, toggleTerminal, ]) const isMobile = useIsMobile() const modeContainerRef = useRef(null) const modeItemRefs = useRef>(new Map()) const [modeIndicator, setModeIndicator] = useState<{ left: number width: number } | null>(null) useEffect(() => { const container = modeContainerRef.current if (!container) return const measure = () => { const btn = modeItemRefs.current.get(mode) if (!btn || !container) { setModeIndicator(null) return } const containerRect = container.getBoundingClientRect() const btnRect = btn.getBoundingClientRect() setModeIndicator({ left: btnRect.left - containerRect.left, width: btnRect.width, }) } const ro = new ResizeObserver(() => measure()) for (const btn of modeItemRefs.current.values()) { ro.observe(btn) } ro.observe(container) measure() return () => { ro.disconnect() } }, [mode]) const handleModeKeyDown = useCallback( (event: ReactKeyboardEvent, nextMode: typeof mode) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault() setMode(nextMode) } }, [setMode] ) const modeTabsElement = (
{modeIndicator && (
)} {MODE_TABS.map((item) => { const Icon = item.icon const isActive = mode === item.mode const title = tModes(item.titleKey) return (
{ if (el) { modeItemRefs.current.set(item.mode, el) } else { modeItemRefs.current.delete(item.mode) } }} role="tab" tabIndex={0} className={cn( "relative z-10 m-0 flex h-[1.4375rem] cursor-pointer select-none items-center justify-center gap-1 rounded-full border-0 bg-transparent p-0 align-middle text-xs font-medium leading-none transition-all duration-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60", isActive ? "px-2.5" : "px-2", isActive ? "text-foreground" : "text-muted-foreground hover:text-foreground/70" )} onClick={() => setMode(item.mode)} onKeyDown={(event) => handleModeKeyDown(event, item.mode)} onMouseDown={(event) => event.preventDefault()} title={!isActive ? title : undefined} aria-label={title} aria-selected={isActive} > {!isMobile && ( {title} )}
) })}
) return ( <>
) : (
) } center={isMobile ? undefined : modeTabsElement} right={ isMobile ? (
{tTitleBar("toggleAuxPanel")} toggleTerminal()} disabled={!activeFolder} > {tTitleBar("toggleTerminal")} {tTitleBar("openSettings")}
) : (
) } /> { openFolder(path).catch((err) => { console.error("[FolderTitleBar] failed to open folder:", err) }) }} /> ) }