M0-M11 狩夜人笔记初始实现:11里程碑+86测试

This commit is contained in:
hunter-dev
2026-08-24 20:35:22 +08:00
commit 3ebd33536b
106 changed files with 10490 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
// IPC handlers — 主进程侧通道注册(类型链约束于 @hunter/shared)
import nodePath from 'node:path';
import { ipcMain, shell, dialog, clipboard } from 'electron';
import { IPC } from '@hunter/shared';
import type { VaultService } from '../services/vault-service.js';
import { buildGraphData } from '../services/graph-builder.js';
export function registerIpc(vault: VaultService) {
const fs2 = () => {
if (!vault.fileService) throw new Error('vault not initialized');
return vault.fileService;
};
ipcMain.handle(IPC.vaultList, async () => vault.getMeta());
ipcMain.handle(IPC.vaultSwitch, async (_e, p: { root: string }) => vault.switch(p.root));
ipcMain.handle(IPC.vaultSetDefault, async (_e, p: { root: string }) => { await vault.setDefaultRoot(p.root); });
ipcMain.handle(IPC.vaultPick, async () => vault.pickAndSwitch());
ipcMain.handle(IPC.treeList, async () => fs2().listTree());
ipcMain.handle(IPC.treeRefresh, async () => fs2().listTree());
ipcMain.handle(IPC.fileCreate, async (_e, p: { basePath: string; name: string; isFolder: boolean }) =>
fs2().create(p.basePath, p.name, p.isFolder));
ipcMain.handle(IPC.fileRename, async (_e, p: { from: string; toName: string }) =>
fs2().rename(p.from, p.toName));
ipcMain.handle(IPC.fileMove, async (_e, p: { src: string; destDir: string }) =>
fs2().move(p.src, p.destDir));
ipcMain.handle(IPC.fileDelete, async (_e, p: { path: string; recursive: boolean }) =>
fs2().delete(p.path, p.recursive));
ipcMain.handle(IPC.fileImport, async (_e, p: { sources: string[]; destDir: string }) => {
// 若 sources 为空,弹出系统选择对话框
let sources = p.sources;
if (sources.length === 0) {
const r = await dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'], filters: [{ name: 'Markdown', extensions: ['md'] }] });
if (r.canceled) return { ok: [], failed: [] };
sources = r.filePaths;
}
return fs2().importFiles(sources, p.destDir);
});
ipcMain.handle(IPC.docRead, async (_e, p: { path: string }) => fs2().readDoc(p.path));
ipcMain.handle(IPC.docWrite, async (_e, p: { path: string; meta: any; body: string }) =>
fs2().writeDoc({ path: p.path, meta: p.meta, body: p.body }));
ipcMain.handle(IPC.search, async (_e, p: { query: string }) => vault.searchService?.search(p.query) ?? []);
ipcMain.handle(IPC.tagStats, async () => vault.searchService?.tagStats() ?? []);
ipcMain.handle(IPC.graph, async () => {
const fs2 = vault.fileService;
if (!fs2) return { nodes: [], edges: [] };
const tree = await fs2.listTree();
return buildGraphData(fs2.getRoot(), tree);
});
ipcMain.handle(IPC.copyMd, async (_e, p: { path: string }) => {
const fs2 = vault.fileService; if (!fs2) return '';
const { body } = await fs2.readDoc(p.path);
clipboard.writeText(body);
return body;
});
ipcMain.handle(IPC.docReveal, async (_e, p: { path: string }) => {
const fs2 = vault.fileService;
if (!fs2) return;
shell.showItemInFolder(nodePath.join(fs2.getRoot(), p.path));
});
}