import { useEffect, useCallback } from 'react' import { useTabStore } from '../stores/tabStore' import { isAllowedFile } from '../lib/fileUtils' import { MAX_FILE_SIZE } from '../lib/constants' import { logError } from '../lib/errorHandler' export function useDragDrop(showToast: (msg: string) => void) { const createTab = useTabStore(s => s.createTab) const handleDrop = useCallback(async (e: DragEvent) => { e.preventDefault() e.stopPropagation() const files = e.dataTransfer?.files if (!files) return let rejected = 0 for (const file of Array.from(files)) { // Electron adds a `path` property to File objects const electronFile = file as File & { path?: string } const filePath: string = electronFile.path || file.name if (!isAllowedFile(filePath)) { rejected++ continue } if (file.size > MAX_FILE_SIZE) { showToast(`"${file.name}" 过大,暂不支持超过 20MB 的文件`) continue } if (window.electronAPI) { try { const result = await window.electronAPI.readFile(filePath) if (result.success && result.content !== undefined) { createTab(filePath, result.content) } } catch (error) { logError('拖拽读取文件失败', error) } } else { const reader = new FileReader() reader.onload = (ev: ProgressEvent) => { const content = ev.target?.result as string createTab(file.name, content) } reader.readAsText(file) } } if (rejected > 0) { showToast(`仅支持 .md / .markdown / .txt 文件,已忽略 ${rejected} 个文件`) } }, [createTab, showToast]) useEffect(() => { const prevent = (e: DragEvent) => { e.preventDefault() e.stopPropagation() } document.addEventListener('dragenter', prevent) document.addEventListener('dragleave', prevent) document.addEventListener('dragover', prevent) document.addEventListener('drop', handleDrop) return () => { document.removeEventListener('dragenter', prevent) document.removeEventListener('dragleave', prevent) document.removeEventListener('dragover', prevent) document.removeEventListener('drop', handleDrop) } }, [handleDrop]) }