80 lines
4.2 KiB
TypeScript
80 lines
4.2 KiB
TypeScript
/**
|
||
* Electron 预加载脚本
|
||
*
|
||
* 作用:在上下文隔离(contextIsolation)环境下,通过 contextBridge 向渲染进程暴露
|
||
* 受控的桌面能力 API(window.electronAPI)。渲染进程无法直接访问 Node/Electron,
|
||
* 只能调用这里明确列出的方法,保证安全边界。
|
||
*
|
||
* 渲染层对应的类型声明见 src/types/electron.d.ts(两边需保持同步)。
|
||
*/
|
||
import { contextBridge, ipcRenderer } from 'electron'
|
||
import type { IpcRendererEvent } from 'electron'
|
||
|
||
/** 订阅主进程事件的通用封装:返回取消订阅函数,方便组件卸载时清理 */
|
||
function subscribe<T>(channel: string, callback: (payload: T) => void): () => void {
|
||
const listener = (_event: IpcRendererEvent, payload: T) => callback(payload)
|
||
ipcRenderer.on(channel, listener)
|
||
return () => {
|
||
ipcRenderer.removeListener(channel, listener)
|
||
}
|
||
}
|
||
|
||
const electronAPI = {
|
||
/** 当前运行平台(win32/darwin/linux),渲染层可用于平台差异化处理 */
|
||
platform: process.platform,
|
||
|
||
// ---------- 应用信息 ----------
|
||
/** 获取应用版本号(package.json version,设置弹窗展示用) */
|
||
getVersion: (): Promise<string> => ipcRenderer.invoke('app:get-version'),
|
||
|
||
// ---------- 窗口 ----------
|
||
/** 显示并聚焦主窗口 */
|
||
focusWindow: (): Promise<void> => ipcRenderer.invoke('win:focus'),
|
||
/** 设置任务栏未读角标;count=0 清除。角标图片由渲染层 canvas 生成(主进程无 DOM) */
|
||
setBadge: (count: number, dataURL?: string): Promise<void> =>
|
||
ipcRenderer.invoke('win:set-badge', count, dataURL || ''),
|
||
/** 请求任务栏闪烁提醒(仅窗口未聚焦时生效,聚焦后自动停止) */
|
||
flashFrame: (): Promise<void> => ipcRenderer.invoke('win:flash'),
|
||
|
||
// ---------- 系统通知 ----------
|
||
/** 发送系统级通知(点击通知会显示并聚焦主窗口) */
|
||
notify: (options: { title: string; body: string }): Promise<void> =>
|
||
ipcRenderer.invoke('app:notify', options),
|
||
|
||
// ---------- 开机自启与应用设置 ----------
|
||
/** 查询是否已设置开机自启 */
|
||
getAutoLaunch: (): Promise<boolean> => ipcRenderer.invoke('app:get-auto-launch'),
|
||
/** 设置开机自启,返回设置后的实际状态 */
|
||
setAutoLaunch: (enable: boolean): Promise<boolean> => ipcRenderer.invoke('app:set-auto-launch', enable),
|
||
/** 读取应用本地设置(closeToTray 等) */
|
||
getAppSettings: (): Promise<{ closeToTray: boolean }> => ipcRenderer.invoke('app:get-settings'),
|
||
/** 增量更新应用本地设置,返回更新后的完整设置 */
|
||
setAppSettings: (patch: Partial<{ closeToTray: boolean }>): Promise<{ closeToTray: boolean }> =>
|
||
ipcRenderer.invoke('app:set-settings', patch),
|
||
|
||
// ---------- 文件下载 ----------
|
||
/** 下载文件:走主进程弹系统"另存为"对话框(file:// 下 <a download> 跨域失效的替代方案) */
|
||
downloadFile: (url: string, fileName: string): Promise<void> =>
|
||
ipcRenderer.invoke('download:start', url, fileName),
|
||
/** 订阅下载完成事件(state: completed/cancelled/interrupted),返回取消订阅函数 */
|
||
onDownloadDone: (
|
||
callback: (payload: { state: string; fileName: string; savePath: string }) => void
|
||
): (() => void) => subscribe('download:done', callback),
|
||
/** 在系统文件管理器中显示指定文件(下载完成 toast 的"打开文件夹"操作) */
|
||
showItemInFolder: (fullPath: string): Promise<void> =>
|
||
ipcRenderer.invoke('shell:show-item-in-folder', fullPath),
|
||
|
||
// ---------- 应用内更新 ----------
|
||
/** 检查更新(结果通过 onUpdateStatus 推送) */
|
||
checkForUpdate: (): Promise<void> => ipcRenderer.invoke('updater:check'),
|
||
/** 开始下载更新包(进度通过 onUpdateStatus 推送) */
|
||
downloadUpdate: (): Promise<void> => ipcRenderer.invoke('updater:download'),
|
||
/** 退出并安装已下载的更新 */
|
||
quitAndInstall: (): Promise<void> => ipcRenderer.invoke('updater:install'),
|
||
/** 订阅更新状态事件(checking/available/not-available/downloading/downloaded/error/dev) */
|
||
onUpdateStatus: (callback: (payload: Record<string, unknown>) => void): (() => void) =>
|
||
subscribe('updater:status', callback),
|
||
}
|
||
|
||
contextBridge.exposeInMainWorld('electronAPI', electronAPI)
|