feat(electron): main process, vault, search index, links, import, capture
Vault on plain .md files with FTS5 index, link rewriting, canvas files, history/trash/backup, link previews, image fetch, tasks and unlinked mentions, Notion/Obsidian importer, quick-capture window and shortcut. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0b5f8bfa8b
commit
313c41f867
16 files changed
+2706
-15
No files matched your search
@@ -0,0 +1,109 @@
|
||||
'use strict';
|
||||
// The only bridge between the page and the file system. Everything goes through ipcMain handlers in main.cjs.
|
||||
const { contextBridge, ipcRenderer } = require('electron');
|
||||
|
||||
const invoke = (channel, ...args) => ipcRenderer.invoke(channel, ...args);
|
||||
|
||||
contextBridge.exposeInMainWorld('vault', {
|
||||
platform: process.platform,
|
||||
get: () => invoke('vault:get'),
|
||||
list: () => invoke('vault:list'),
|
||||
pick: (kind) => invoke('vault:pick', kind),
|
||||
read: (id) => invoke('vault:read', id),
|
||||
write: (id, meta, body) => invoke('vault:write', id, meta, body),
|
||||
duplicate: (id) => invoke('vault:duplicate', id),
|
||||
create: (parent, title, meta, body) => invoke('vault:create', parent, title, meta, body),
|
||||
createMany: (parent, items) => invoke('vault:createMany', parent, items),
|
||||
createCanvas: (parent, title) => invoke('vault:createCanvas', parent, title),
|
||||
listTemplates: () => invoke('vault:listTemplates'),
|
||||
getTemplate: (name) => invoke('vault:getTemplate', name),
|
||||
openTemplatesFolder: () => invoke('vault:openTemplates'),
|
||||
rename: (id, title) => invoke('vault:rename', id, title),
|
||||
move: (id, parent) => invoke('vault:move', id, parent),
|
||||
renameHeading: (id, from, to) => invoke('vault:renameHeading', id, from, to),
|
||||
tasks: () => invoke('vault:tasks'),
|
||||
setTask: (id, line, text, done) => invoke('vault:setTask', id, line, text, done),
|
||||
unlinked: (id) => invoke('vault:unlinked', id),
|
||||
linkMention: (id, target) => invoke('vault:linkMention', id, target),
|
||||
openCapture: () => invoke('capture:open'),
|
||||
takeCaptures: () => invoke('capture:take'),
|
||||
onCapture(cb) {
|
||||
const listener = () => cb();
|
||||
ipcRenderer.on('capture:ping', listener);
|
||||
return () => ipcRenderer.removeListener('capture:ping', listener);
|
||||
},
|
||||
renameTag: (from, to) => invoke('vault:renameTag', from, to),
|
||||
exportVaultZip: () => invoke('export:vaultZip'),
|
||||
importNotes: (kind) => invoke('vault:import', kind),
|
||||
clipPage: (url) => invoke('web:clip', url),
|
||||
backlinks: (id) => invoke('vault:backlinks', id),
|
||||
graph: () => invoke('vault:graph'),
|
||||
keepVersion: (id) => invoke('vault:keepVersion', id),
|
||||
listHistory: (id) => invoke('vault:listHistory', id),
|
||||
readHistory: (id, ts) => invoke('vault:readHistory', id, ts),
|
||||
restoreHistory: (id, ts) => invoke('vault:restoreHistory', id, ts),
|
||||
saveImage: (id, name, bytes) => invoke('vault:saveImage', id, name, bytes),
|
||||
saveImageFromUrl: (id, url) => invoke('vault:saveImageFromUrl', id, url),
|
||||
pickImage: (id) => invoke('vault:pickImage', id),
|
||||
pickFile: (id) => invoke('vault:pickFile', id),
|
||||
openFile: (id, src) => invoke('vault:openFile', id, src),
|
||||
mediaUrl: (id, src) => `notes-media://vault/${encodeURIComponent(id)}?src=${encodeURIComponent(src)}`,
|
||||
remove: (id) => invoke('vault:remove', id),
|
||||
trash: () => invoke('vault:trash'),
|
||||
restore: (entry) => invoke('vault:restore', entry),
|
||||
purge: (entry) => invoke('vault:purge', entry),
|
||||
search: (q) => invoke('vault:search', q),
|
||||
reveal: (id) => invoke('vault:reveal', id),
|
||||
filePath: (id) => invoke('vault:filePath', id),
|
||||
saveExport: (name, content) => invoke('export:save', name, content),
|
||||
savePdf: (name, title, html) => invoke('export:pdf', name, title, html),
|
||||
print: () => ipcRenderer.send('export:print'),
|
||||
linkPreview: (url) => invoke('web:preview', url),
|
||||
saveCanvasImage: (name, kind, html, width, height) => invoke('export:canvas', name, kind, html, width, height),
|
||||
getSettings: () => invoke('settings:get'),
|
||||
setSettings: (patch) => invoke('settings:set', patch),
|
||||
getSpellcheck: () => invoke('spell:get'),
|
||||
setSpellcheck: (enabled, langs) => invoke('spell:set', enabled, langs),
|
||||
spellWords: () => invoke('spell:words'),
|
||||
addSpellWord: (word) => invoke('spell:addWord', word),
|
||||
removeSpellWord: (word) => invoke('spell:removeWord', word),
|
||||
backupNow: () => invoke('backup:now'),
|
||||
backupInfo: () => invoke('backup:info'),
|
||||
pickBackupFolder: () => invoke('backup:pickFolder'),
|
||||
revealBackups: () => invoke('backup:reveal'),
|
||||
onNav(cb) {
|
||||
const listener = (_e, dir) => cb(dir);
|
||||
ipcRenderer.on('nav:go', listener);
|
||||
return () => ipcRenderer.removeListener('nav:go', listener);
|
||||
},
|
||||
onChanged(cb) {
|
||||
const listener = (_e, ids) => cb(ids);
|
||||
ipcRenderer.on('vault:changed', listener);
|
||||
return () => ipcRenderer.removeListener('vault:changed', listener);
|
||||
},
|
||||
minimize: () => ipcRenderer.send('win:minimize'),
|
||||
toggleMaximize: () => ipcRenderer.send('win:toggleMaximize'),
|
||||
close: () => ipcRenderer.send('win:close'),
|
||||
isMaximized: () => invoke('win:isMaximized'),
|
||||
onMaximized(cb) {
|
||||
const listener = (_e, v) => cb(v);
|
||||
ipcRenderer.on('win:maximized', listener);
|
||||
return () => ipcRenderer.removeListener('win:maximized', listener);
|
||||
},
|
||||
onContextMenu(cb) {
|
||||
const listener = (_e, info) => cb(info);
|
||||
ipcRenderer.on('app:context-menu', listener);
|
||||
return () => ipcRenderer.removeListener('app:context-menu', listener);
|
||||
},
|
||||
editAction: (action) => ipcRenderer.send('edit:do', action),
|
||||
copyImageAt: (x, y) => ipcRenderer.send('edit:copyImageAt', x, y),
|
||||
replaceMisspelling: (word) => ipcRenderer.send('edit:replaceMisspelling', word),
|
||||
addToDictionary: (word) => ipcRenderer.send('edit:addToDictionary', word),
|
||||
onFlush(cb) {
|
||||
const listener = async () => {
|
||||
try { await cb(); } finally { ipcRenderer.send('app:flushed'); }
|
||||
};
|
||||
ipcRenderer.on('app:flush', listener);
|
||||
return () => ipcRenderer.removeListener('app:flush', listener);
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user