From 073978d3cabdfa2c3deb688fb4523b0548a48efb Mon Sep 17 00:00:00 2001 From: thzxx Date: Sat, 15 Aug 2026 21:18:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20v0.6.2=20=E2=80=94=20sqlark=200.7.4=20?= =?UTF-8?q?=E5=8D=87=E7=BA=A7(KVStore)=20+=2014=20=E9=A1=B9=E7=BC=BA?= =?UTF-8?q?=E9=99=B7=E4=BF=AE=E5=A4=8D=20+=20=E5=A4=9A=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - chore: 升级 @metona-team/metona-sqlark 0.4.4 → 0.7.4,存储后端迁移 KVStore 引擎(内存索引+快照/日志,OPFS 落盘,jsdom 回退 memory), 启动时自动删除旧 IndexedDB 库(aria-MarkLiteV2 / Dexie MarkLite), 不做向下兼容 - fix: 保存竞态 — 快照比对后才清 isModified,防止保存期间的新输入被 误清标记导致永不落盘(自动保存与手动保存均修复) - fix: 另存为后标签重绑新路径(此前 Ctrl+S/自动保存仍写回旧文件), 并同步最近文件与快照持久化 - fix: tabSwitched 只依赖活动文件路径(此前每次击键都触发 IPC 并 重启主进程文件 watcher) - fix: 主进程关闭兜底超时 5s→12s(长于 confirm 10s,防强杀丢编辑) - fix: 外部修改检测覆盖非活动标签,banner 显示文件名, 标签有未保存修改时显式提示不再静默 - fix: 导入备份后 flush + closeDatabase 再 reload(防 OPFS 未落盘丢数据), 导入整体事务原子化(防半导入状态) - fix: 文档大纲跳过代码块内标题;切换标签恢复光标位置 - fix: 首次启动主题跟随系统偏好(settings 无记录时 load 返回 null) - fix: watcher error 恢复时重置 isSelfWriting,防外部修改通知被永久吞掉 - fix: 打开失败路径(最近文件/文件树/打开对话框)显式提示 - fix: 保存时保留原文件编码(UTF-16 LE/BE BOM 同编码写回) - feat: 多文件搜索 — dir:search IPC + SearchPanel 弹层 + Ctrl+Shift+F, 文件夹内递归搜索(大小写/正则,结果定位到行) - feat: 标签恢复时与磁盘 mtime 比对,自动同步磁盘最新内容 - test: 新增 outlineUtils(6) / searchInDir(7) / updateTabFilePath(2) 测试 - docs: README/DESIGN 同步 kv 后端与版本号 v0.6.2 --- DESIGN.md | 15 +- README.md | 6 +- docs/metona-sqlark-demo.html | 43 ++++- docs/metona-sqlark-docs.html | 133 ++++++++++--- package.json | 5 +- src/main/__tests__/searchInDir.test.ts | 71 +++++++ src/main/file-system.ts | 124 +++++++++++- src/main/file-watcher.ts | 4 + src/main/index.ts | 4 +- src/main/ipc-handlers.ts | 20 +- src/preload/index.ts | 2 + src/renderer/App.tsx | 72 ++++++- .../components/AboutDialog/AboutDialog.tsx | 2 +- src/renderer/components/Editor/Editor.tsx | 12 +- src/renderer/components/Icons.tsx | 19 ++ .../ModifiedBanner/ModifiedBanner.tsx | 5 +- .../__tests__/outlineUtils.test.ts | 48 +++++ .../components/OutlinePanel/outlineUtils.ts | 35 +++- .../components/SearchPanel/SearchPanel.tsx | 171 ++++++++++++++++ src/renderer/components/SearchPanel/index.ts | 1 + src/renderer/components/Sidebar/Sidebar.tsx | 8 + src/renderer/components/Toolbar/Toolbar.tsx | 26 ++- .../__tests__/recentFiles.integration.test.ts | 5 +- src/renderer/db/backupRepository.ts | 15 +- src/renderer/db/schema.ts | 95 +++++++-- src/renderer/db/settingsRepository.ts | 12 +- src/renderer/hooks/useAutoSave.ts | 15 +- src/renderer/hooks/useFileOperations.ts | 32 ++- src/renderer/hooks/useFileWatch.ts | 10 +- src/renderer/hooks/useKeyboard.ts | 9 +- src/renderer/hooks/useSettingsInit.ts | 12 +- .../stores/__tests__/tabStore.test.ts | 26 +++ src/renderer/stores/tabStore.ts | 44 +++++ src/renderer/styles/global.css | 182 ++++++++++++++++++ src/renderer/types/ipc.ts | 4 + src/shared/constants.ts | 2 +- src/shared/ipc-channels.ts | 1 + src/shared/types.ts | 24 +++ 38 files changed, 1191 insertions(+), 123 deletions(-) create mode 100644 src/main/__tests__/searchInDir.test.ts create mode 100644 src/renderer/components/OutlinePanel/__tests__/outlineUtils.test.ts create mode 100644 src/renderer/components/SearchPanel/SearchPanel.tsx create mode 100644 src/renderer/components/SearchPanel/index.ts diff --git a/DESIGN.md b/DESIGN.md index c209e98..551d7d0 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -22,7 +22,7 @@ MarkLite 是一款轻量级的 Windows 本地 Markdown 编辑器桌面应用程 | 类型系统 | TypeScript | v5.6 | 全量类型安全 | | 编辑器 | MetonaEditor | v0.4.0 | 零依赖 Markdown 编辑器,三模式视图 + 插件系统 | | 状态管理 | Zustand | v5 | 轻量级状态管理 | -| 持久化 | MetonaSqlark (IndexedDB) | v0.4.1 | 标签页状态 / 用户设置 / 最近文件(AriaEngine) | +| 持久化 | MetonaSqlark | v0.7.4 | 标签页状态 / 用户设置 / 最近文件(AriaEngine + KVStore,OPFS 落盘;v0.6.2 起不再使用 IndexedDB,旧库启动时自动删除) | | Markdown 解析 | MetonaEditor 内置解析器 | v0.4.0 | 零依赖,GFM + 脚注 + 数学公式 + mermaid | | 代码高亮 | MetonaEditor 内置高亮器 | v0.4.0 | 零依赖,16 种语言 | | Toast | @metona-team/metona-toast | v0.5.0 | 通知提示组件 | @@ -162,11 +162,13 @@ interface SidebarState { } ``` -## 4. 数据持久化 — IndexedDB +## 4. 数据持久化 — MetonaSqlark (KVStore) v0.5.0: 由 Dexie.js 迁移至 MetonaSqlark(AriaEngine:自研 LSM-Tree + WAL + MVCC 存储引擎,对标 SQLite)。 MetonaSqlark 的 create() 为异步,采用懒加载单例(getDb()), 表结构幂等创建(查表名后 defineTable),数据库名更换为 MarkLiteV2(旧 Dexie 数据已放弃)。 +v0.6.2: sqlark 升级 0.7.4,存储后端改用自研 KVStore(内存索引 + 快照/日志,OPFS 落盘); +旧 IndexedDB 库在启动时自动删除,不做向下兼容。 ### 4.1 数据库 Schema @@ -175,11 +177,11 @@ MetonaSqlark 的 create() 为异步,采用懒加载单例(getDb()), let dbPromise: Promise | null = null export function getDb(): Promise { if (!dbPromise) { - dbPromise = MetonaSqlark.create({ + dbPromise = create({ name: 'MarkLiteV2', mode: 'aria', // AriaEngine: LSM-Tree + WAL + MVCC 快照隔离 - diskEngine: 'indexeddb', // 底层存储后端(indexeddb | opfs | memory) - version: 1, + diskEngine: 'kv', // v0.6.2: 自研 KVStore 后端(OPFS 落盘;jsdom 测试回退 memory) + version: 0, // AriaEngine 忽略版本号 }).then(async (db) => { if (!(await db.getTableNames()).includes('tabSnapshots')) { await db.defineTable('tabSnapshots', { id: { type: 'string', primaryKey: true }, ... }) @@ -221,6 +223,7 @@ export function getDb(): Promise { | `dir:openDialog` | 无 | `string \| null` | 打开文件夹选择对话框 | | `dir:watch` | `dirPath` | `void` | 监听目录变化 | | `dir:unwatch` | 无 | `void` | 停止监听目录变化 | +| `dir:search` | `{ dirPath, query, caseSensitive?, useRegex? }` | `SearchInDirResult` | v0.6.2: 文件夹内多文件内容搜索 | ### 5.2 主进程 → 渲染进程(send) @@ -405,7 +408,7 @@ npm run build:portable # 便携版(免安装) |------|------|------| | react / react-dom | ^18.3 | UI 框架 | | zustand | ^5.0 | 状态管理 | -| @metona-team/metona-sqlark | 0.4.1 | 前端关系型数据库(AriaEngine) | +| @metona-team/metona-sqlark | 0.7.4 | 前端关系型数据库(AriaEngine + KVStore,OPFS) | | nanoid | ^5.0 | 唯一 ID 生成 | | @metona-team/metona-editor | 0.4.0 | Markdown 编辑器(内置解析器 + 高亮) | | @metona-team/metona-toast | 0.5.0 | Toast 通知组件 | diff --git a/README.md b/README.md index f6dbb84..7af6ac6 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ TypeScript React License - Version + Version

@@ -38,6 +38,7 @@ | 🔔 **文件监听** | 外部修改文件时自动提示,支持重新加载或忽略 | | 💾 **文件保存** | 保存 / 另存为,支持 .md / .markdown / .txt 格式 | | 🔍 **搜索替换** | Ctrl+F 搜索、Ctrl+H 替换,支持正则表达式、大小写敏感 | +| 🔎 **多文件搜索** | Ctrl+Shift+F 在已打开文件夹内递归搜索内容,结果定位到行 | | 📁 **文件树** | 侧边栏浏览项目目录,点击打开文件,目录变化自动刷新 | | 📊 **Mermaid 图表** | 代码块中渲染 Mermaid 流程图 / 时序图 / 甘特图等 | | 💾 **状态持久化** | 标签页状态、用户设置通过 MetonaSqlark(AriaEngine)持久化,关闭后可恢复 | @@ -134,6 +135,7 @@ npm run test:coverage | `Ctrl + Shift + S` | 另存为 | | `Ctrl + F` | 搜索 | | `Ctrl + H` | 搜索并替换 | +| `Ctrl + Shift + F` | 多文件搜索(当前文件夹内) | | `Ctrl + Z` / `Ctrl + Y` | 撤销 / 重做 | | `Ctrl + B` / `Ctrl + I` | 粗体 / 斜体(编辑器内置) | | `Ctrl + E` / `Ctrl + K` / `Ctrl + Q` | 行内代码 / 链接 / 引用(编辑器内置) | @@ -149,7 +151,7 @@ npm run test:coverage | 类型系统 | [TypeScript](https://www.typescriptlang.org/) v5.6 | 全量类型安全 | | 编辑器 | [MetonaEditor](https://git.metona.cn/MetonaTeam/MetonaEditor) v0.4.1 | 内置解析器 + 高亮,三模式视图 + 浮动格式栏 + Zen 模式 + 插件系统 | | 状态管理 | [Zustand](https://zustand-demo.pmnd.rs/) v5 | 轻量级状态管理 | -| 持久化 | [MetonaSqlark](https://git.metona.cn/MetonaTeam/MetonaSqlark) v0.4.4 (IndexedDB, AriaEngine) | 标签页状态 & 用户设置持久化 | +| 持久化 | [MetonaSqlark](https://git.metona.cn/MetonaTeam/MetonaSqlark) v0.7.4 (AriaEngine + KVStore/OPFS) | 标签页状态 & 用户设置持久化 | | Markdown 解析 | MetonaEditor 内置解析器 | 零依赖:GFM / 脚注 / 数学公式 / Mermaid | | 代码高亮 | MetonaEditor 内置高亮器 | 零依赖,16 种语言 | | Toast | [@metona-team/metona-toast](https://git.metona.cn/MetonaTeam/-/packages/npm/@metona-team%2Fmetona-toast) v0.5.0 | 通知提示组件 | diff --git a/docs/metona-sqlark-demo.html b/docs/metona-sqlark-demo.html index 6e414d8..1259c4c 100644 --- a/docs/metona-sqlark-demo.html +++ b/docs/metona-sqlark-demo.html @@ -3,7 +3,7 @@ -🧪 在线演示 — MetonaSqlark v0.4.4 +🧪 在线演示 — MetonaSqlark v0.7.4