Files
MarkLite/src/renderer/hooks/useDragDrop.ts
T

74 lines
2.3 KiB
TypeScript

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<FileReader>) => {
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])
}