feat: refactor menus

This commit is contained in:
2026-03-15 21:11:57 +01:00
parent a8bd579043
commit 929359b4bc
8 changed files with 406 additions and 290 deletions

View File

@@ -4,6 +4,7 @@
*/
import React, { useCallback, useEffect, useMemo, useRef } from 'react'
import { useLocation } from 'react-router-dom'
import {
ReactFlow,
ReactFlowProvider,
@@ -36,7 +37,7 @@ import { ContextMenu, ContextMenuTrigger } from '@/components/ui/context-menu'
import { CanvasContextMenuContent } from '@/app/canvas/CanvasContextMenuContent'
import { useCanvasConnectionPathFromStore } from '@/app/canvas/useCanvasConnectionPathFromStore'
import { dispatchCanvasCommand } from '@/app/canvas/canvasStore'
import { useRecollectionMenubar } from '@/app/recollections/RecollectionMenubarContext'
import { useRecollectionTitleData } from '@/app/recollections/RecollectionTitleDataContext'
import { FluxMenubarContent } from '@/app/recollections/flux/FluxMenubarContent'
import { createContextualNode } from '@/app/canvas/ContextualZoomNode'
import { ViewportDisplayProvider } from '@/app/canvas/ViewportDisplayContext'
@@ -428,52 +429,57 @@ export function CanvasPage({ recollectionId }: CanvasPageProps) {
flowActionsRef.current?.pasteAtViewportCenter?.()
}, [])
const { setCustomContent } = useRecollectionMenubar()
const { pathname } = useLocation()
const isFluxActive = pathname.endsWith('/flux')
const { setTitleData } = useRecollectionTitleData()
useEffect(() => {
setCustomContent(
<FluxMenubarContent
onImport={handleImportRecollection}
onExport={handleExportRecollection}
onSave={
recollectionId
? () => {
save()
toast.success('Saved')
}
: undefined
}
canSave={Boolean(recollectionId)}
saveStatus={saveStatus}
undo={undo}
redo={redo}
canUndo={canUndo}
canRedo={canRedo}
onDuplicate={handleDuplicate}
onCopy={handleCopy}
onPaste={handlePaste}
canDuplicate={selectedNodes.length > 0}
canCopy={selectedNodes.length === 1}
onFitView={() => flowActionsRef.current?.fitView?.()}
/>
)
return () => setCustomContent(null)
setTitleData({
saveStatus,
onSave: recollectionId
? () => {
save()
toast.success('Saved')
}
: undefined,
canSave: Boolean(recollectionId),
onImport: handleImportRecollection,
onExport: handleExportRecollection,
})
return () => setTitleData(null)
}, [
setCustomContent,
recollectionId,
setTitleData,
saveStatus,
canUndo,
canRedo,
selectedNodes.length,
recollectionId,
save,
undo,
redo,
handleDuplicate,
handleCopy,
handlePaste,
handleImportRecollection,
handleExportRecollection,
])
const fluxMenubarProps = useMemo(
() => ({
undo,
redo,
canUndo,
canRedo,
onDuplicate: handleDuplicate,
onCopy: handleCopy,
onPaste: handlePaste,
canDuplicate: selectedNodes.length > 0,
canCopy: selectedNodes.length === 1,
onFitView: () => flowActionsRef.current?.fitView?.(),
}),
[
canUndo,
canRedo,
selectedNodes.length,
undo,
redo,
handleDuplicate,
handleCopy,
handlePaste,
]
)
const graphContextValue = useMemo(
() => ({ setNodes, setEdges, graphRef, edges }),
[setNodes, setEdges, edges]
@@ -682,6 +688,7 @@ export function CanvasPage({ recollectionId }: CanvasPageProps) {
onContextMenu={onCanvasContextMenu}
style={{ position: 'relative' }}
>
{isFluxActive && <FluxMenubarContent {...fluxMenubarProps} />}
<div role="status" aria-live="polite" aria-atomic className="sr-only">
{ariaAnnouncement}
</div>