import { X, Pencil, MoreVertical, WandSparkles, Copy, CopyCheck, ArrowRightFromLine, ExternalLink, Plus, } from "lucide-react"; import { useSetAtom } from "jotai"; import { useState } from "react"; import { WindowInstance } from "@/types/app"; import { commandLauncherEditModeAtom } from "@/core/command-launcher-state"; import { reconstructCommand } from "@/lib/command-reconstructor"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, DropdownMenuSeparator, } from "@/components/ui/dropdown-menu"; import { Button } from "@/components/ui/button"; import { SpellDialog } from "@/components/nostr/SpellDialog"; import { reconstructCommand as reconstructReqCommand } from "@/lib/spell-conversion"; import { toast } from "sonner"; import { useCopy } from "@/hooks/useCopy"; import { useNip } from "@/hooks/useNip"; import { useGrimoire } from "@/core/state"; interface WindowToolbarProps { window?: WindowInstance; onClose?: () => void; onEditCommand?: () => void; // Callback to open CommandLauncher } export function WindowToolbar({ window, onClose, onEditCommand, }: WindowToolbarProps) { const setEditMode = useSetAtom(commandLauncherEditModeAtom); const [showSpellDialog, setShowSpellDialog] = useState(false); const { state, moveWindowToWorkspace, moveWindowToNewWorkspace } = useGrimoire(); // Get workspaces for move action const otherWorkspaces = Object.values(state.workspaces) .filter((ws) => ws.id !== state.activeWorkspaceId) .sort((a, b) => a.number - b.number); const handleMoveToWorkspace = (targetWorkspaceId: string) => { if (!window) return; const targetWorkspace = state.workspaces[targetWorkspaceId]; moveWindowToWorkspace(window.id, targetWorkspaceId); toast.success( `Moved to tab ${targetWorkspace.number}${targetWorkspace.label ? ` (${targetWorkspace.label})` : ""}`, ); }; const handleMoveToNewTab = () => { if (!window) return; moveWindowToNewWorkspace(window.id); toast.success("Moved to new tab"); }; const handleEdit = () => { if (!window) return; // Get command string (existing or reconstructed) const commandString = window.commandString || reconstructCommand(window); // Set edit mode state setEditMode({ windowId: window.id, initialCommand: commandString, }); // Open CommandLauncher if (onEditCommand) { onEditCommand(); } }; const handleTurnIntoSpell = () => { if (!window) return; // Only available for REQ and COUNT windows if (window.appId !== "req" && window.appId !== "count") { toast.error("Only REQ and COUNT windows can be turned into spells"); return; } setShowSpellDialog(true); }; const handlePopOut = () => { if (!window) return; // Get command string (existing or reconstructed) const commandString = window.commandString || reconstructCommand(window); // Construct the /run URL with the command as a query parameter const popOutUrl = `/run?cmd=${encodeURIComponent(commandString)}`; // Open in a new window/tab globalThis.window.open(popOutUrl, "_blank"); }; // Copy functionality for NIPs const { copy, copied } = useCopy(); const isNipWindow = window?.appId === "nip"; // Fetch NIP content for regular NIPs const { content: nipContent } = useNip( isNipWindow && window?.props?.number ? window.props.number : "", ); const handleCopyNip = () => { if (!window || !nipContent) return; copy(nipContent); toast.success("NIP markdown copied to clipboard"); }; // Check if this is a REQ or COUNT window for spell creation const isReqWindow = window?.appId === "req"; const isCountWindow = window?.appId === "count"; const isSpellableWindow = isReqWindow || isCountWindow; // Get command for spell dialog const spellCommand = isSpellableWindow && window ? window.commandString || reconstructReqCommand( window.props?.filter || {}, window.props?.relays, undefined, undefined, window.props?.closeOnEose, isCountWindow ? "COUNT" : "REQ", ) : ""; return ( <> {window && ( <> {/* Edit button */} {/* Copy button for NIPs */} {isNipWindow && ( )} {/* More actions menu */} {/* Pop out window */} Pop out window {/* Move to tab submenu */} Move to tab New {otherWorkspaces.length > 0 && } {otherWorkspaces.map((ws) => ( handleMoveToWorkspace(ws.id)} > {ws.number} {ws.label ? ` ${ws.label}` : ""} ))} {/* REQ/COUNT-specific actions */} {isSpellableWindow && ( <> Save as spell )} {/* Spell Dialog */} {isSpellableWindow && ( { toast.success("Spell published successfully!"); }} /> )} )} {onClose && ( )} ); }