/** * Shared Edit and View menus for recollections. Always rendered in the menubar; * uses the active slot (flux or logos by pathname) for undo, redo, and Flux-only actions. */ import React, { useEffect, useMemo } from 'react' import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSeparator, MenubarTrigger, } from '@/components/ui/menubar' import { Kbd, KbdGroup } from '@/components/ui/kbd' import { useRecollectionActions } from './RecollectionActionsContext' import { ClipboardPaste, Copy, CopyPlus, Redo2, Undo2 } from 'lucide-react' const UNDO_KEYS = { key: 'z', shiftKey: false } const REDO_KEYS = { key: 'z', shiftKey: true } function matchKey(ev: KeyboardEvent, want: { key: string; shiftKey: boolean }) { const mod = ev.ctrlKey || ev.metaKey return ev.key.toLowerCase() === want.key && !!mod && !!ev.shiftKey === want.shiftKey } export function RecollectionEditViewMenus() { const { activeSlot, flux, isFluxActive } = useRecollectionActions() const fluxSlot = isFluxActive ? flux : null useEffect(() => { if (!activeSlot) return const onKeyDown = (ev: KeyboardEvent) => { if (matchKey(ev, UNDO_KEYS) && activeSlot.canUndo) { ev.preventDefault() ev.stopPropagation() activeSlot.undo() } else if (matchKey(ev, REDO_KEYS) && activeSlot.canRedo) { ev.preventDefault() ev.stopPropagation() activeSlot.redo() } } window.addEventListener('keydown', onKeyDown, true) return () => window.removeEventListener('keydown', onKeyDown, true) }, [activeSlot]) const menus = useMemo(() => { if (!activeSlot) return null const hasFluxOnly = fluxSlot && (fluxSlot.onDuplicate != null || fluxSlot.onCopy != null || fluxSlot.onPaste != null) return ( Edit Undo ⌘ + Z Redo ⌘ + ⇧ + Z {hasFluxOnly && ( <> {fluxSlot!.onDuplicate != null && ( Duplicate ⌘D )} {fluxSlot!.onCopy != null && ( Copy ⌘C )} {fluxSlot!.onPaste != null && ( Paste ⌘V )} )} View {fluxSlot?.onFitView && ( Fit View ⌘0 )} ) }, [activeSlot, fluxSlot]) return menus }