'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); } });