import { useState, useRef, useEffect, useCallback } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { springs } from "@/lib/motion"; import { ArrowLeft, Settings, Search, Undo2, Redo2, SlidersHorizontal, Filter } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Tooltip, TooltipTrigger, TooltipContent, } from "@/components/ui/tooltip"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { VersionHistoryDialog } from "@/components/board/VersionHistoryDialog"; import { useAppStore } from "@/stores/app-store"; import { useBoardStore } from "@/stores/board-store"; import { WindowControls } from "@/components/layout/WindowControls"; export function TopBar() { const view = useAppStore((s) => s.view); const setView = useAppStore((s) => s.setView); const board = useBoardStore((s) => s.board); const updateBoardTitle = useBoardStore((s) => s.updateBoardTitle); const saving = useBoardStore((s) => s.saving); const lastSaved = useBoardStore((s) => s.lastSaved); const isBoardView = view.type === "board"; const [showVersionHistory, setShowVersionHistory] = useState(false); const [editing, setEditing] = useState(false); const [editValue, setEditValue] = useState(""); const inputRef = useRef(null); useEffect(() => { if (editing && inputRef.current) { inputRef.current.focus(); inputRef.current.select(); } }, [editing]); const startEditing = useCallback(() => { if (board) { setEditValue(board.title); setEditing(true); } }, [board]); const commitEdit = useCallback(() => { const trimmed = editValue.trim(); if (trimmed && trimmed !== board?.title) { updateBoardTitle(trimmed); } setEditing(false); }, [editValue, board?.title, updateBoardTitle]); const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === "Enter") { commitEdit(); } else if (e.key === "Escape") { setEditing(false); } }, [commitEdit] ); const savingStatus = saving ? "Saving..." : lastSaved ? `Saved ${formatTimeAgo(lastSaved)}` : null; return (
{/* Left section */}
{isBoardView && ( Back to board list )}
{/* Center section */}
{isBoardView && board ? ( editing ? ( setEditValue(e.target.value)} onBlur={commitEdit} onKeyDown={handleKeyDown} className="h-7 rounded-md border border-border bg-transparent px-2 text-center font-heading text-lg text-pylon-text outline-none focus:border-pylon-accent" /> ) : ( ) ) : ( OpenPylon )}
{/* Right section */}
{isBoardView && ( <> {savingStatus && ( {savingStatus} )}
Undo Ctrl+Z Redo Ctrl+Shift+Z Filter cards / )} {isBoardView && board && ( Background useBoardStore.getState().updateBoardSettings({ ...board.settings, background: v as typeof board.settings.background })} > {(["none", "dots", "grid", "gradient"] as const).map((bg) => ( {bg.charAt(0).toUpperCase() + bg.slice(1)} ))} Attachments useBoardStore.getState().updateBoardSettings({ ...board.settings, attachmentMode: v as typeof board.settings.attachmentMode })} > Link to original Copy into board setShowVersionHistory(true)}> Version History )} Command palette{" "} Ctrl+K Settings
{isBoardView && ( )}
); } function formatTimeAgo(timestamp: number): string { const seconds = Math.floor((Date.now() - timestamp) / 1000); if (seconds < 5) return "just now"; if (seconds < 60) return `${seconds}s ago`; const minutes = Math.floor(seconds / 60); return `${minutes}m ago`; }