Files
MyReader/electron/preload.ts
T

85 lines
3.5 KiB
TypeScript
Raw Normal View History

2026-05-15 16:35:31 +08:00
import { contextBridge, ipcRenderer } from 'electron'
import type {
ListDirResult,
OpenFileResult,
OpenFolderResult,
OpenImageResult,
SaveDialogResult
} from './ipc-types.js'
export interface MyReaderApi {
openFileDialog: () => Promise<OpenFileResult>
openFolderDialog: () => Promise<OpenFolderResult>
openImageDialog: () => Promise<OpenImageResult>
saveFileDialog: (defaultPath?: string) => Promise<SaveDialogResult>
readFile: (filePath: string) => Promise<string>
writeFile: (filePath: string, content: string) => Promise<void>
listDirectory: (dirPath: string) => Promise<ListDirResult>
parentDirectory: (dirPath: string) => Promise<string>
/** 相对当前 Markdown 文件解析内链 href → 绝对路径(外链原样返回) */
resolveRelativePath: (baseFilePath: string, href: string) => Promise<string>
openExternal: (url: string) => Promise<void>
defaultDirectory: () => Promise<string>
deleteFile: (filePath: string) => Promise<void>
renamePath: (oldPath: string, newName: string) => Promise<{ newPath: string }>
allowClose: () => void
onRequestClose: (handler: () => void) => () => void
onMenuAction: (handler: (action: string) => void) => () => void
2026-05-18 14:13:16 +08:00
onOpenFiles: (handler: (paths: string[]) => void) => () => void
2026-05-15 16:35:31 +08:00
}
const api: MyReaderApi = {
openFileDialog: () => ipcRenderer.invoke('myreader:open-file-dialog'),
openFolderDialog: () => ipcRenderer.invoke('myreader:open-folder-dialog'),
openImageDialog: () => ipcRenderer.invoke('myreader:open-image-dialog'),
saveFileDialog: (defaultPath?: string) => ipcRenderer.invoke('myreader:save-dialog', defaultPath),
readFile: (filePath: string) => ipcRenderer.invoke('myreader:read-file', filePath),
writeFile: (filePath: string, content: string) =>
ipcRenderer.invoke('myreader:write-file', filePath, content),
listDirectory: (dirPath: string) => ipcRenderer.invoke('myreader:list-directory', dirPath),
parentDirectory: (dirPath: string) => ipcRenderer.invoke('myreader:parent-directory', dirPath),
resolveRelativePath: (baseFilePath: string, href: string) =>
ipcRenderer.invoke('myreader:resolve-relative-path', baseFilePath, href),
openExternal: (url: string) => ipcRenderer.invoke('myreader:open-external', url),
defaultDirectory: () => ipcRenderer.invoke('myreader:default-directory'),
deleteFile: (filePath: string) => ipcRenderer.invoke('myreader:delete-file', filePath),
renamePath: (oldPath: string, newName: string) =>
ipcRenderer.invoke('myreader:rename-path', oldPath, newName),
allowClose: () => {
ipcRenderer.send('myreader:allow-close')
},
onRequestClose: (handler: () => void) => {
const listener = (): void => {
handler()
}
ipcRenderer.on('myreader:request-close', listener)
return () => {
ipcRenderer.removeListener('myreader:request-close', listener)
}
},
onMenuAction: (handler: (action: string) => void) => {
const listener = (_e: unknown, action: string): void => {
handler(action)
}
ipcRenderer.on('myreader:menu', listener)
return () => {
ipcRenderer.removeListener('myreader:menu', listener)
}
2026-05-18 14:13:16 +08:00
},
onOpenFiles: (handler: (paths: string[]) => void) => {
const listener = (_e: unknown, paths: string[]): void => {
handler(paths)
}
ipcRenderer.on('myreader:open-files', listener)
return () => {
ipcRenderer.removeListener('myreader:open-files', listener)
}
2026-05-15 16:35:31 +08:00
}
}
try {
contextBridge.exposeInMainWorld('myreader', api)
} catch (e) {
console.error('[MyReader] preload contextBridge failed', e)
}