import { useCallback, useRef } from 'react' import { useTabStore } from '../stores/tabStore' import { useEditorStore } from '../stores/editorStore' import { recentFilesRepository } from '../db/recentFilesRepository' import { logError } from '../lib/errorHandler' import { showToast } from '../lib/toast' /** * AR-01: 从 App.tsx 提取的文件操作逻辑 * UX-02: 添加 loading 状态指示 * v0.1.9: handleSave 添加防重入锁,避免编辑器 onSave + 全局 Ctrl+S 双重触发 */ export function useFileOperations() { const createTab = useTabStore(s => s.createTab) const getActiveTab = useTabStore(s => s.getActiveTab) const setLoading = useEditorStore(s => s.setLoading) // 防重入:onSave 回调 + 全局 Ctrl+S handler 可能在 300ms 内双重触发 const savingGate = useRef(false) const handleOpenFile = useCallback(async (): Promise => { try { if (!window.electronAPI) return setLoading('file-open', true) const result = await window.electronAPI.openFile() if (result && 'filePath' in result) { createTab(result.filePath, result.content) if (result.filePath) recentFilesRepository.add(result.filePath) setTimeout(() => useTabStore.getState().saveToDB(), 100) } } catch (error) { logError('打开文件失败', error) showToast('打开文件失败', 'error') } finally { setLoading('file-open', false) } }, [createTab, setLoading]) const handleSave = useCallback(async (): Promise => { // 防重入:300ms 内忽略重复调用(编辑器 onSave + 全局 Ctrl+S 双重触发) if (savingGate.current) return savingGate.current = true try { const tab = getActiveTab() if (!tab || !window.electronAPI) return const result = await window.electronAPI.saveFile({ filePath: tab.filePath, content: tab.content }) if (result.success) { useTabStore.getState().setModified(tab.id, false) showToast('已保存', 'success') } } catch (error) { logError('保存文件失败', error) showToast('保存失败', 'error') } finally { // 300ms 后释放锁,允许下次保存 setTimeout(() => { savingGate.current = false }, 300) } }, [getActiveTab]) const handleSaveAs = useCallback(async (): Promise => { try { const tab = getActiveTab() if (!tab || !window.electronAPI) return const result = await window.electronAPI.saveFileAs({ content: tab.content }) if (result.success) { useTabStore.getState().setModified(tab.id, false) showToast('已保存', 'success') } } catch (error) { logError('另存为失败', error) showToast('另存为失败', 'error') } }, [getActiveTab]) const handleOpenRecent = useCallback(async (filePath: string): Promise => { if (!window.electronAPI) return setLoading('file-open', true) try { const result = await window.electronAPI.readFile(filePath) if (result.success && result.content !== undefined) { createTab(filePath, result.content) recentFilesRepository.add(filePath) setTimeout(() => useTabStore.getState().saveToDB(), 100) } } finally { setLoading('file-open', false) } }, [createTab, setLoading]) return { handleOpenFile, handleSave, handleSaveAs, handleOpenRecent } }