refactor: 删除分屏功能 + 代码审计修复 + 安全加固

## 删除分屏功能
- 删除 ViewMode 'split' 类型,仅保留 editor/preview
- 删除 splitRatio 状态和 Resizer 组件
- 删除滚动同步模块 (scrollSync.ts, rehypeSourceLine.ts)
- 更新快捷键: Ctrl+1 编辑, Ctrl+2 预览

## Bug 修复
- 修复 Toast setTimeout 内存泄漏 (App.tsx)
- 修复 ModifiedBanner reload 更新错误标签 (改用 modifiedFilePath 匹配)
- 修复 FileWatcher error 未重置 isSelfWriting (file-watcher.ts)
- 修复另存为时未 stop watcher (ipc-handlers.ts)

## 死代码清理 (10 项)
- 删除 main/ipc-channels.ts (与 shared/ 重复)
- 删除 main/file-system.ts 未使用的 formatBytes
- 删除 constants.ts 6 个未使用常量
- 删除 fileUtils.ts 未使用的 formatBytes
- 删除 Icons.tsx 5 个未使用图标 (SplitView/ChevronUp/ChevronDown/X/ArrowUp/ArrowDown)
- 删除 useCodeMirror 未使用的 getContent/scrollTo
- 删除 TabBar 未使用的 menuRef
- 删除 Tab.scrollLeft/previewScrollTop 字段
- 删除 tabStore 未使用的 getTabIndex
- 删除 Toast/ModifiedBanner 多余 React import

## 安全加固
- ipc-handlers: 添加路径遍历防护 (validatePath 函数)
- preload: openExternal 仅允许 http/https 协议
- window-manager: 启用 sandbox: true
- preload: removeAllListeners 改为精确取消订阅 (返回 Unsubscribe 函数)

## 状态持久化
- activeTabId 持久化到 IndexedDB (刷新后恢复正确标签)
- sidebar 状态持久化到 IndexedDB (isVisible/sidebarWidth)

## 代码优化
- preload 使用 IPC_CHANNELS 常量替代硬编码字符串
- ipc-handlers _event 类型改为 IpcMainInvokeEvent
- settingsRepository 删除 splitRatio 字段
This commit is contained in:
thzxx
2026-05-28 13:42:11 +08:00
parent 3c6e4ac5ce
commit 9c92dcfa9d
37 changed files with 242 additions and 655 deletions
+5 -9
View File
@@ -1,11 +1,11 @@
import React from 'react'
import { FolderOpen, Save, SplitView, EditMode, PreviewMode, Moon, Sun } from '../Icons'
import { FolderOpen, Save, EditMode, PreviewMode, Moon, Sun } from '../Icons'
interface ToolbarProps {
onOpen: () => void
onSave: () => void
viewMode: 'split' | 'editor' | 'preview'
onViewModeChange: (mode: 'split' | 'editor' | 'preview') => void
viewMode: 'editor' | 'preview'
onViewModeChange: (mode: 'editor' | 'preview') => void
darkMode: boolean
onToggleDark: () => void
}
@@ -23,15 +23,11 @@ export function Toolbar({ onOpen, onSave, viewMode, onViewModeChange, darkMode,
<span></span>
</button>
<div className="toolbar-divider" />
<button className={`toolbar-btn ${viewMode === 'split' ? 'active' : ''}`} onClick={() => onViewModeChange('split')} title="编辑+预览 (Ctrl+1)">
<SplitView size={18} />
<span></span>
</button>
<button className={`toolbar-btn ${viewMode === 'editor' ? 'active' : ''}`} onClick={() => onViewModeChange('editor')} title="纯编辑 (Ctrl+2)">
<button className={`toolbar-btn ${viewMode === 'editor' ? 'active' : ''}`} onClick={() => onViewModeChange('editor')} title="编辑 (Ctrl+1)">
<EditMode size={18} />
<span></span>
</button>
<button className={`toolbar-btn ${viewMode === 'preview' ? 'active' : ''}`} onClick={() => onViewModeChange('preview')} title="预览 (Ctrl+3)">
<button className={`toolbar-btn ${viewMode === 'preview' ? 'active' : ''}`} onClick={() => onViewModeChange('preview')} title="预览 (Ctrl+2)">
<PreviewMode size={18} />
<span></span>
</button>