import { type Dispatch, type MutableRefObject, type RefObject, type SetStateAction, useCallback, useMemo, } from 'react'; import { createLayerFromAsset, isLayerLinkedToAsset, } from './ImageCanvasEditorModel'; import type { AssetPointerDragState, CanvasLayer, CanvasViewport, EditorAsset, EditorAssetFolder, } from './ImageCanvasEditorTypes'; import { useImageCanvasAssetPointerDragBridge } from './useImageCanvasAssetPointerDragBridge'; import { useImageCanvasCanvasDropWorkflow } from './useImageCanvasCanvasDropWorkflow'; type CanvasPoint = { x: number; y: number }; type UploadFilesToCanvasOptions = { folderId?: string; canvasPoint: CanvasPoint; addToCanvas: true; }; type UseImageCanvasAssetLayerCleanupOptions = { layers: CanvasLayer[]; setLayers: Dispatch>; setSelectedLayerId: Dispatch>; setSelectedLayerIds: Dispatch>; }; type UseImageCanvasAssetCanvasBridgeOptions = { assetPointerDragRef: RefObject; suppressAssetClickRef: RefObject; assets: EditorAsset[]; assetFolders: EditorAssetFolder[]; layerCounterRef: MutableRefObject; viewport: CanvasViewport; canvasSize: { width: number; height: number }; resolveAssetFolderId: (clientX: number, clientY: number) => string | null; resolveCanvasPoint: (clientX: number, clientY: number) => CanvasPoint | null; getCanvasDropPoint: (clientX: number, clientY: number) => CanvasPoint; setAssetPointerDrag: Dispatch>; setActiveUploadFolderId: Dispatch>; setUploadDropTarget: Dispatch>; setHoveredLayerId: Dispatch>; updateAssetMoveDropFolder: (folderId: string | null) => void; moveAssetToFolder: (assetId: string, folderId: string) => void; captureCanvasHistory: () => void; appendCanvasLayersWithResources: (nextLayers: CanvasLayer[]) => void; selectSingleLayer: (layerId: string | null) => void; addUploadedFiles: ( files: FileList | File[], options: UploadFilesToCanvasOptions, ) => void; }; export function useImageCanvasAssetLayerCleanup({ layers, setLayers, setSelectedLayerId, setSelectedLayerIds, }: UseImageCanvasAssetLayerCleanupOptions) { return useCallback( (deletedAssets: EditorAsset[]) => { if (!deletedAssets.length) { return; } setLayers((currentLayers) => currentLayers.filter( (layer) => !deletedAssets.some((asset) => isLayerLinkedToAsset(layer, asset)), ), ); setSelectedLayerIds((currentIds) => currentIds.filter((layerId) => layers.every( (layer) => layer.id !== layerId || !deletedAssets.some((asset) => isLayerLinkedToAsset(layer, asset), ), ), ), ); setSelectedLayerId((currentId) => { if (!currentId) { return currentId; } const currentLayer = layers.find((layer) => layer.id === currentId); return currentLayer && deletedAssets.some((asset) => isLayerLinkedToAsset(currentLayer, asset)) ? null : currentId; }); }, [layers, setLayers, setSelectedLayerId, setSelectedLayerIds], ); } export function useImageCanvasAssetCanvasBridge({ assetPointerDragRef, suppressAssetClickRef, assets, assetFolders, layerCounterRef, viewport, canvasSize, resolveAssetFolderId, resolveCanvasPoint, getCanvasDropPoint, setAssetPointerDrag, setActiveUploadFolderId, setUploadDropTarget, setHoveredLayerId, updateAssetMoveDropFolder, moveAssetToFolder, captureCanvasHistory, appendCanvasLayersWithResources, selectSingleLayer, addUploadedFiles, }: UseImageCanvasAssetCanvasBridgeOptions) { const addAssetLayer = useCallback( (asset: EditorAsset, position?: CanvasPoint) => { setActiveUploadFolderId(asset.folderId); layerCounterRef.current += 1; const nextLayer = createLayerFromAsset( asset, layerCounterRef.current, viewport, { x: position?.x ?? canvasSize.width / 2, y: position?.y ?? canvasSize.height / 2, }, ); captureCanvasHistory(); appendCanvasLayersWithResources([nextLayer]); selectSingleLayer(nextLayer.id); setHoveredLayerId(null); }, [ appendCanvasLayersWithResources, canvasSize.height, canvasSize.width, captureCanvasHistory, layerCounterRef, selectSingleLayer, setActiveUploadFolderId, setHoveredLayerId, viewport, ], ); useImageCanvasAssetPointerDragBridge({ assetPointerDragRef, suppressAssetClickRef, assets, resolveAssetFolderId, resolveCanvasPoint, setAssetPointerDrag, setUploadDropTarget, updateAssetMoveDropFolder, moveAssetToFolder, addAssetLayer, }); const canvasDropWorkflow = useImageCanvasCanvasDropWorkflow({ assets, assetFolders, setUploadDropTarget, updateAssetMoveDropFolder, getCanvasDropPoint, addAssetLayer, addUploadedFiles, }); return useMemo( () => ({ addAssetLayer, ...canvasDropWorkflow, }), [addAssetLayer, canvasDropWorkflow], ); }