UNPKG

@neosjs/electron-toolkit

Version:

neosjs electron toolkit

1,360 lines (1,338 loc) 42.8 kB
/*! * @neosjs/electron-toolkit * Version: 1.0.1 * Copyright (c) 2021-PRESENT NeosJS * ReleaseTime: 2025/5/1 16:45:38 */ import { WEBCONTENTS_READY_FOR_IPC_SIGNAL, bytesToSize, formatToDate, ipcMainEvents, ipcUpdaterEvents, isFunction, version } from "../chunk-2MRZ2BGU.js"; import { init_esm_shims } from "../chunk-QTDD3S3N.js"; // src/main/index.ts init_esm_shims(); // src/main/core/AppManager.ts init_esm_shims(); import { app as app2 } from "electron"; import { EventEmitter } from "node:events"; // src/main/platform.ts init_esm_shims(); import { app } from "electron"; var is = { dev: !app.isPackaged, devMode: !!process.defaultApp }; var platform = { isWindows: process.platform === "win32", isMacOS: process.platform === "darwin", isLinux: process.platform === "linux", isMac: process.platform === "darwin", isWin: process.platform === "win32", isDev: !app.isPackaged, isDevMode: !!process.defaultApp }; // src/main/core/LoggerManager.ts init_esm_shims(); import logger from "electron-log"; var env = process.env.NODE_ENV; logger.initialize(); logger.transports.file.fileName = `${formatToDate(/* @__PURE__ */ new Date())}_${env}.log`; logger.transports.file.level = "info"; logger.transports.file.maxSize = 5 * 1024 * 1024; logger.transports.console.format = `[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] {text}`; logger.transports.console.level = "info"; var getLogger = (name) => logger.scope(name); logger.info("=================================="); // src/main/core/AppManager.ts var AppManager = class _AppManager extends EventEmitter { static instance = {}; maxListeners; static logger; constructor() { super(); this.maxListeners = 20; _AppManager.logger = getLogger("AppManager"); _AppManager.logger.info("\u521D\u59CB\u5316 AppManager \u6A21\u5757"); } static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _AppManager(); } return this.instance; } // 是否是开发模式 isDevMode() { return !!process.defaultApp; } // 是否准备好 isReady() { return app2.isReady(); } // 重新启动 relaunch() { app2.relaunch(); } // 退出 quit() { app2.quit(); } // 退出 exit(code = 0) { app2.exit(code); } // 获取应用名称 getName() { return app2.getName(); } // 设置应用名称 setName(name) { if (!name) return; app2.setName(name); } // 获取应用路径 getPath() { return app2.getAppPath(); } // 获取应用路径 getPathByName(name) { if (!name) return ""; return app2.getPath(name); } // 设置应用日志路径 setLogsPath(path2) { if (!path2) return; app2.setAppLogsPath(path2); } // 设置应用路径 setPath(name, path2) { if (!name || !path2) return; app2.setPath(name, path2); } // 获取应用版本 getVersion() { return app2.getVersion(); } // 设置应用用户模型ID setUserModelId(id) { if (platform.isWindows) { app2.setAppUserModelId(platform.isDev ? process.execPath : id); } } // 设置应用自动启动 setAutoLaunch(auto) { if (platform.isLinux) return false; const isOpenAtLogin = () => { return app2.getLoginItemSettings().openAtLogin; }; if (isOpenAtLogin() !== auto) { app2.setLoginItemSettings({ openAtLogin: auto }); return isOpenAtLogin() === auto; } else { return true; } } // 获取应用区域 getLocale() { return app2.getLocale(); } // 获取应用区域代码 getLocaleCountryCode() { return app2.getLocaleCountryCode(); } // 获取系统区域 getSystemLocale() { return app2.getSystemLocale(); } // 获取系统区域语言 getPreferredSystemLanguages() { return app2.getPreferredSystemLanguages(); } }; // src/main/core/AutoLaunchManager.ts init_esm_shims(); import { app as app3 } from "electron"; var AutoLaunchManager = class _AutoLaunchManager { static instance = {}; static logger; constructor() { _AutoLaunchManager.logger = getLogger("AutoLaunchManager"); _AutoLaunchManager.logger.info("\u521D\u59CB\u5316 AutoLaunchManager \u6A21\u5757"); } static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _AutoLaunchManager(); } return this.instance; } enable() { return new Promise((resolve) => { const enabled = app3.getLoginItemSettings({ args: ["--opened-at-login=1"] }).openAtLogin; if (enabled) { resolve(); } app3.setLoginItemSettings({ args: ["--opened-at-login=1"], openAtLogin: true }); resolve(); }); } disable() { return new Promise((resolve) => { app3.setLoginItemSettings({ openAtLogin: false }); resolve(); }); } isEnabled() { return new Promise((resolve) => { const enabled = app3.getLoginItemSettings({ args: ["--opened-at-login=1"] }).openAtLogin; resolve(enabled); }); } }; // src/main/core/DevtoolManager.ts init_esm_shims(); import { VUEJS_DEVTOOLS, installExtension } from "electron-devtools-installer"; var DevtoolManager = class _DevtoolManager { static instance = {}; static logger; constructor() { _DevtoolManager.logger = getLogger("DevtoolManager"); _DevtoolManager.logger.info("\u521D\u59CB\u5316 DevtoolManager \u6A21\u5757"); } static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _DevtoolManager(); } return this.instance; } /** * 安装开发者工具 * @returns {Promise<void>} */ async setupDevTools() { try { await installExtension(VUEJS_DEVTOOLS, { loadExtensionOptions: { allowFileAccess: true } }); _DevtoolManager.logger.info(`\u5B89\u88C5 Vue DevTools \u6210\u529F`); } catch (error) { _DevtoolManager.logger.warn(`\u5B89\u88C5 Vue DevTools \u5931\u8D25:`, error); } } }; // src/main/core/DownloadManager.ts init_esm_shims(); import extName from "ext-name"; import { EventEmitter as EventEmitter3 } from "node:events"; import { extname, isAbsolute, join } from "node:path"; import { BrowserWindow as BrowserWindow3, app as app4, shell } from "electron"; import { unusedFilenameSync } from "unused-filename"; // src/shared/types.ts init_esm_shims(); // src/main/core/IpcManager.ts init_esm_shims(); import { BrowserWindow as BrowserWindow2, ipcMain } from "electron"; import { EventEmitter as EventEmitter2 } from "node:events"; // src/main/core/WindowManager.ts init_esm_shims(); import { BrowserWindow } from "electron"; var WindowManager = class _WindowManager { static instance = {}; static ipc; static logger; browserWindow = null; constructor() { _WindowManager.logger = getLogger("WindowManager"); _WindowManager.logger.info("\u521D\u59CB\u5316 WindowManager \u6A21\u5757"); _WindowManager.ipc = IpcManager.getInstance(); } /** * 获取单例 */ static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _WindowManager(); } return this.instance; } /** * 监听渲染进程事件 */ static onRendererEvent() { _WindowManager.ipc.on("SET_WINDOW_SIZE" /* SET_WINDOW_SIZE */, (event, size) => { const win = BrowserWindow.fromWebContents(event.sender); if (!win) return; win.setSize(size.width, size.height); }); _WindowManager.ipc.on("SET_WINDOW_ABLE" /* SET_WINDOW_ABLE */, (event, data) => { const { type, flag, win = null } = data; const window_ = win || BrowserWindow.fromWebContents(event.sender); if (!type || !window_) return; switch (type) { case "maximize": window_.setMaximizable(flag); break; case "minimize": window_.setMinimizable(flag); break; case "close": window_.setClosable(flag); break; case "move": window_.setMovable(flag); break; case "resize": window_.setResizable(flag); break; case "fullscreen": window_.setFullScreenable(flag); break; default: break; } }); } /** * 监听窗口快捷键 * @param {BrowserWindow | null} window 窗口 * @param {ShortcutOptions} shortcutOptions 快捷键选项 */ static onWindowShortcuts(window, shortcutOptions) { if (!window) return; const { webContents } = window; const { escToCloseWindow = false, zoom = false } = shortcutOptions || {}; webContents.on("before-input-event", (event, input) => { if (input.type === "keyDown") { if (!is.dev) { if (input.code === "KeyR" && (input.control || input.meta)) event.preventDefault(); if (input.code === "KeyI" && (input.alt && input.meta || input.control && input.shift)) { event.preventDefault(); } } else { if (input.code === "F12") { if (webContents.isDevToolsOpened()) { webContents.closeDevTools(); } else { webContents.openDevTools({ mode: "undocked" }); console.log("Open dev tool..."); } } } if (escToCloseWindow) { if (input.code === "Escape" && input.key !== "Process") { window.close(); event.preventDefault(); } } if (!zoom) { if (input.code === "Minus" && (input.control || input.meta)) event.preventDefault(); if (input.code === "Equal" && input.shift && (input.control || input.meta)) event.preventDefault(); } } }); } // 注册无边框窗口IPC static registerFramelessWindowIpc() { this.ipc.on("invoke" /* INVOKE */, (event, action) => { const win = BrowserWindow.fromWebContents(event.sender); if (!win) return; switch (action) { case "show": win.show(); break; case "showInactive": win.showInactive(); break; case "min": win.minimize(); break; case "max": win.maximize(); break; case "unmax": win.isMaximized() && win.unmaximize(); break; case "close": win.close(); break; case "toggleFullscreen": win.setFullScreen(!win.isFullScreen()); break; case "exitFullscreen": win.setFullScreen(false); break; case "fullScreen": win.setFullScreen(true); break; case "center": win.center(); break; default: break; } }); } /** * 设置浏览器窗口 * @param {BrowserWindow | null} window 窗口 */ setBrowserWindow(window) { this.browserWindow = window; } /** * 初始化 * @param {BrowserWindow | null} window 窗口 * @param {ShortcutOptions} shortcutOptions 快捷键选项 */ setupWindowManager(window, shortcutOptions) { this.setBrowserWindow(window); const win = this.browserWindow || window; _WindowManager.registerFramelessWindowIpc(); _WindowManager.onWindowShortcuts(win, shortcutOptions); _WindowManager.onRendererEvent(); } }; // src/main/core/IpcManager.ts var IpcManager = class _IpcManager extends EventEmitter2 { readyWebContents = /* @__PURE__ */ new WeakSet(); messageQueue = /* @__PURE__ */ new WeakMap(); static instance = {}; maxListeners; logger; constructor() { super(); this.maxListeners = 20; this.logger = getLogger("IpcManager"); this.logger.info("\u521D\u59CB\u5316 IpcManager \u6A21\u5757"); ipcMain.removeAllListeners(WEBCONTENTS_READY_FOR_IPC_SIGNAL); ipcMainEvents.forEach((event) => { ipcMain.removeAllListeners(event); ipcMain.on(event, (...args) => { this.emit(event, ...args); }); }); ipcMain.on(WEBCONTENTS_READY_FOR_IPC_SIGNAL, (event) => { this.logger.info("webContents\u5DF2\u7ECF\u51C6\u5907\u597D"); this.readyWebContents.add(event.sender); const queue = this.messageQueue.get(event.sender); this.messageQueue.delete(event.sender); if (!queue) return; for (const item of queue) { this.send(item[0], item[1], event.sender); } }); } static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _IpcManager(); } return this.instance; } /** * 发送消息 * @param {IpcEvents} channel 事件名 * @param {Array<any>} args 参数 * @param {WebContents} target 目标 */ send(channel, args, target) { const _target = target || WindowManager.getInstance().browserWindow?.webContents; if (!_target) { const win = BrowserWindow2.getFocusedWindow(); if (win) this.send(channel, args, win?.webContents); return; } const _args = args || []; if (!this.readyWebContents.has(_target)) { const existing = this.messageQueue.get(_target) || []; this.messageQueue.set(_target, [...existing, [channel, args]]); return; } _target.isDestroyed() || _target.send(channel, ..._args); } /** * 监听消息 * @param {IpcEvents} channel 事件名 * @param {Function} listener 监听器 */ handle(channel, listener) { ipcMain.removeHandler(channel); ipcMain.handle(channel, listener); } /** * 监听消息一次 * @param {IpcEvents} channel 事件名 * @param {Function} listener 监听器 */ handleOnce(channel, listener) { ipcMain.handleOnce(channel, listener); } /** * 发送消息 * @param {IpcEvents} channel 事件名 * @param {any} message 消息 * @param {MessagePortMain[]} transfer 传输 * @param {Electron.WebContents} target 目标 */ postMessage(channel, message, transfer, target) { const _target = target || WindowManager.getInstance().browserWindow?.webContents; if (!_target) { const window = BrowserWindow2.getFocusedWindow(); window?.webContents.postMessage(channel, message, transfer); return; } _target.postMessage(channel, message, transfer); } }; // src/main/core/DownloadManager.ts var DownloadManager = class _DownloadManager extends EventEmitter3 { static instance = {}; downloadItems = /* @__PURE__ */ new Set(); maxListeners; static logger; constructor() { super(); this.maxListeners = 20; _DownloadManager.logger = getLogger("DownloadManager"); _DownloadManager.logger.info("\u521D\u59CB\u5316 DownloadManager \u6A21\u5757"); this.setupDownloadManager(); } /** * 获取单例 */ static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _DownloadManager(); } return this.instance; } setupDownloadManager() { const ipcManager = IpcManager.getInstance(); ipcManager.handle("DESTROY" /* DESTROY */, () => { this.downloadItems = /* @__PURE__ */ new Set(); this.removeAllListeners(); }); ipcManager.handle("START_DOWNLOAD" /* START_DOWNLOAD */, async (event, url, options) => { const win = BrowserWindow3.getFocusedWindow(); if (!win) return _DownloadManager.logger.error("\u6CA1\u6709\u627E\u5230\u7A97\u53E3"); try { await this.start(win, url, { ...options, onStart: (info) => { !win.isDestroyed() && event?.sender?.send(encodeURI(url), info, "start"); }, onCancel: (item) => { !win.isDestroyed() && event?.sender?.send(encodeURI(url), item, "cancel"); }, onProgress: (progress) => { !win.isDestroyed() && event?.sender?.send(encodeURI(url), progress, "progress"); }, onPause: (item) => { !win.isDestroyed() && event?.sender?.send(encodeURI(url), item, "pause"); }, onComplete: (info) => { !win.isDestroyed() && event?.sender?.send(encodeURI(url), info, "complete"); }, onFail: (item) => { !win.isDestroyed() && event?.sender?.send(encodeURI(url), item, "fail"); } }); return encodeURI(url); } catch (error) { console.error(error); return ""; } }); ipcManager.on("PAUSE_DOWNLOAD" /* PAUSE_DOWNLOAD */, (_event, fileUrl) => { this.pause(fileUrl); }); ipcManager.on("RESUME_DOWNLOAD" /* RESUME_DOWNLOAD */, (_event, fileUrl) => { this.resume(fileUrl); }); ipcManager.on("CANCEL_DOWNLOAD" /* CANCEL_DOWNLOAD */, (_event, fileUrl) => { this.cancel(fileUrl); }); } /** * 获取文件名 * @param {string} name 文件名 * @param {string} mime 文件类型 * @returns {string} 文件名 */ getFilenameFromMime(name, mime) { const extensions = extName.mime(mime); if (extensions.length !== 1) return name; return `${name}.${extensions[0].ext}`; } /** * 注册监听 * @param {Electron.Session} session 会话 * @param {DownloadOptions} options 选项 */ registerListener(session2, options) { return new Promise((resolve, reject) => { let receivedBytes = 0; let completedBytes = 0; let totalBytes = 0; const activeDownloadItems = () => this.downloadItems.size; const progressDownloadItems = () => receivedBytes / totalBytes; options = { showBadge: true, showProgressBar: true, ...options }; const listener = (_event, item, webContents) => { this.downloadItems.add(item); totalBytes += item.getTotalBytes(); const window_ = BrowserWindow3.fromWebContents(webContents); if (!window_) throw new Error("\u83B7\u53D6\u7A97\u53E3\u5931\u8D25"); if (options.directory && !isAbsolute(options.directory)) throw new Error("`directory` \u9009\u9879\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84"); const { overwrite, saveAs, onProgress, onComplete, onStart, onCancel, onFail, onPause, onTotalProgress, showProgressBar, showBadge, unregisterWhenDone, openFolderWhenDone } = options; const directory = options.directory ?? AppManager.getInstance().getPathByName("downloads" /* DOWNLOADS */); let filePath; if (options.filename) { filePath = join(directory, options.filename); } else { const filename = item.getFilename(); const name = extname(filename) ? filename : this.getFilenameFromMime(filename, item.getMimeType()); filePath = overwrite ? join(directory, name) : unusedFilenameSync(join(directory, name)); } const errorMessage = options.errorMessage ?? "\u4E0B\u8F7D {fileName} \u5931\u8D25"; if (saveAs) { item.setSaveDialogOptions({ defaultPath: filePath, ...options.dialogOptions }); } else { item.setSavePath(filePath); } item.on("updated", (_event2, state) => { receivedBytes = completedBytes; for (const item2 of this.downloadItems) { receivedBytes += item2.getReceivedBytes(); } if (showBadge && ["darwin", "linux"].includes(process.platform)) { app4.badgeCount = activeDownloadItems(); } if (!window_.isDestroyed() && showProgressBar) { window_.setProgressBar(progressDownloadItems()); } if (state === "interrupted") { _DownloadManager.logger.info("\u4E0B\u8F7D\u4E2D\u65AD\uFF0C\u53EF\u4EE5\u6062\u590D"); } else if (state === "progressing") { if (item.isPaused()) { _DownloadManager.logger.info("\u4E0B\u8F7D\u6682\u505C"); if (isFunction(onPause)) { onPause({ filename: item.getFilename(), filePath: item.getSavePath(), fileSize: item.getReceivedBytes(), mimeType: item.getMimeType(), fileUrl: item.getURL(), percent: item.getPercentComplete(), percentBytes: progressDownloadItems(), transferredBytes: receivedBytes, totalBytes, speed: item.getCurrentBytesPerSecond() }); } } else { if (isFunction(onProgress)) { const itemTransferredBytes = item.getReceivedBytes(); const itemTotalBytes = item.getTotalBytes(); onProgress({ filename: item.getFilename(), filePath: item.getSavePath(), fileSize: item.getReceivedBytes(), mimeType: item.getMimeType(), fileUrl: item.getURL(), percent: item.getPercentComplete(), percentBytes: itemTotalBytes ? itemTransferredBytes / itemTotalBytes : 0, transferredBytes: itemTransferredBytes, totalBytes: itemTotalBytes, speed: item.getCurrentBytesPerSecond() }); } if (isFunction(onTotalProgress)) { onTotalProgress({ filename: item.getFilename(), filePath: item.getSavePath(), fileSize: item.getReceivedBytes(), mimeType: item.getMimeType(), fileUrl: item.getURL(), percent: progressDownloadItems(), transferredBytes: receivedBytes, totalBytes, speed: item.getCurrentBytesPerSecond() }); } } } }); item.on("done", (_event2, state) => { completedBytes += item.getTotalBytes(); this.downloadItems.delete(item); if (showBadge && ["darwin", "linux"].includes(process.platform)) { app4.badgeCount = activeDownloadItems(); } if (!window_.isDestroyed() && !activeDownloadItems()) { window_.setProgressBar(-1); receivedBytes = 0; completedBytes = 0; totalBytes = 0; } if (unregisterWhenDone) !window_.isDestroyed() && session2.removeListener("will-download", listener); if (state === "cancelled") { _DownloadManager.logger.info("\u4E0B\u8F7D\u53D6\u6D88"); if (isFunction(onCancel)) { onCancel({ filename: item.getFilename(), filePath: item.getSavePath(), fileSize: item.getReceivedBytes(), mimeType: item.getMimeType(), fileUrl: item.getURL() }); } } else if (state === "interrupted") { _DownloadManager.logger.info("\u4E0B\u8F7D\u4E2D\u65AD"); if (isFunction(onFail)) onFail(new Error(errorMessage)); reject(new Error(errorMessage)); } else if (state === "completed") { _DownloadManager.logger.info("\u4E0B\u8F7D\u5B8C\u6210"); const savePath = item.getSavePath(); if (process.platform === "darwin") app4?.dock?.downloadFinished(savePath); if (openFolderWhenDone) shell.showItemInFolder(savePath); if (isFunction(onComplete)) { onComplete({ filename: item.getFilename(), filePath: savePath, fileSize: item.getReceivedBytes(), mimeType: item.getMimeType(), fileUrl: item.getURL() }); } resolve({ filename: item.getFilename(), filePath: savePath, fileSize: item.getReceivedBytes(), mimeType: item.getMimeType(), fileUrl: item.getURL() }); } }); if (isFunction(onStart)) { onStart({ filename: item.getFilename(), filePath: item.getSavePath(), fileSize: item.getTotalBytes(), mimeType: item.getMimeType(), fileUrl: item.getURL() }); } }; session2.on("will-download", listener); }); } /** * 下载 * @param {Electron.BrowserWindow} window_ 窗口 * @param {string} url 下载地址 * @param {DownloadOptions} options 选项 * @returns {Promise<any>} 返回值 */ async start(window_, url, options) { return new Promise((resolve, reject) => { options = { ...options, unregisterWhenDone: true }; this.registerListener(window_.webContents.session, options).then((item) => { resolve(item); }).catch((error) => { reject(error); }); window_.webContents.downloadURL(url); resolve(url); }); } /** * 暂停 * @param {string} fileUrl 下载地址 */ pause(fileUrl) { this.downloadItems.forEach((item) => { if (item.getURL() === fileUrl && !item.isPaused()) { item.pause(); } }); } /** * 恢复 * @param {string} fileUrl 下载地址 */ resume(fileUrl) { this.downloadItems.forEach((item) => { if (item.getURL() === fileUrl && item.isPaused()) { item.resume(); } }); } /** * 取消 * @param {string} fileUrl 下载地址 */ cancel(fileUrl) { this.downloadItems.forEach((item) => { if (item.getURL() === fileUrl && !["interrupted", "cancelled", "completed"].includes(item.getState())) { this.downloadItems.delete(item); item.cancel(); } }); } }; // src/main/core/EnergyManager.ts init_esm_shims(); import { powerSaveBlocker } from "electron"; var psbId; var EnergyManager = class _EnergyManager { static instance = {}; static logger; constructor() { _EnergyManager.logger = getLogger("EnergyManager"); _EnergyManager.logger.info("\u521D\u59CB\u5316 EnergyManager \u6A21\u5757"); } static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _EnergyManager(); } return this.instance; } startPowerSaveBlocker() { if (psbId && powerSaveBlocker.isStarted(psbId)) return; psbId = powerSaveBlocker.start("prevent-display-sleep"); _EnergyManager.logger.info("\u542F\u52A8\u7701\u7535\u62E6\u622A\u5668"); } stopPowerSaveBlocker() { if (typeof psbId === "undefined" || !powerSaveBlocker.isStarted(psbId)) return; powerSaveBlocker.stop(psbId); _EnergyManager.logger.info("\u505C\u6B62\u7701\u7535\u62E6\u622A\u5668"); psbId = void 0; } }; // src/main/core/FileManager.ts init_esm_shims(); import { app as app5, dialog, shell as shell2 } from "electron"; import * as fs from "fs-extra"; import { exec } from "node:child_process"; import * as path from "node:path"; var FileManager = class _FileManager { static instance = {}; static ipc; static logger; constructor() { _FileManager.logger = getLogger("FileManager"); _FileManager.logger.info("\u521D\u59CB\u5316 FileManager \u6A21\u5757"); _FileManager.ipc = IpcManager.getInstance(); _FileManager.setupFileManager(); } static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _FileManager(); } return this.instance; } /** * 启动文件监听 */ static setupFileManager() { _FileManager.ipc.on("OPEN_PATH_SYNC" /* OPEN_PATH_SYNC */, (_event, path2) => { let bat = null; if (process.platform === "win32") { path2 = path2.replace(/\\/, "\\"); path2 = path2.replace(/\//g, "\\"); bat = exec(`start "" "${path2}"`); } if (process.platform === "darwin") { bat = exec(`open "${path2}"`, (err) => { err && dialog.showErrorBox("\u9519\u8BEF", "\u6253\u5F00\u6587\u4EF6\u5931\u8D25"); }); } if (!bat) return false; bat.stdout?.on("data", () => { bat.kill(); }); bat.stderr?.on("data", () => { bat.kill(); }); return true; }); _FileManager.ipc.handle("OPEN_PATH_ASYNC" /* OPEN_PATH_ASYNC */, (_event, path2) => { return shell2.openPath(path2); }); _FileManager.ipc.on("PATH_EXISTS" /* PATH_EXISTS */, (event, path2) => { event.returnValue = fs.existsSync(path2); }); _FileManager.ipc.handle( "CLEANUP_DIRECTORY" /* CLEANUP_DIRECTORY */, (_, dir) => this.cleanupDirectory(dir) ); _FileManager.ipc.handle( "DELETE_USER_DATA" /* DELETE_USER_DATA */, (_, name) => this.deleteUserData(name) ); _FileManager.ipc.handle("SAVE_FILE" /* SAVE_FILE */, (_event, filePath, content) => { return this.saveFile(filePath, content); }); _FileManager.ipc.handle("REMOVE_FILE" /* REMOVE_FILE */, (_event, filePath) => { return this.removeFile(filePath); }); } /** * 清理目录 * @param {string} dir 目录 * @returns {Promise<boolean>} 是否清理成功 */ static cleanupDirectory = async (dir) => { if (dir) { if (fs.existsSync(dir)) { try { await fs.remove(dir); return true; } catch (error) { console.warn(`cleanupDirectory: Failed to clean directory`, error); } } } return false; }; /** * 删除用户数据 * @param {string} name 用户数据名称 * @returns {Promise<boolean>} 是否删除成功 */ static deleteUserData = async (name) => { const appData = path.join(app5.getPath("appData"), name); console.log(`Cleanup: Deleting data dir ${appData}`); return await this.cleanupDirectory(appData); }; /** * 保存文件 * @param {string} filePath 文件路径 * @param {string} content 文件内容 * @returns {Promise<void>} 保存结果 */ static saveFile = async (filePath, content) => { try { return await fs.outputFile(filePath, content, { encoding: "utf-8" }); } catch (error) { console.log(`saveFile: Could not save ${filePath}`, error); } }; /** * 删除文件 * @param {string} filePath 文件路径 * @returns {Promise<void>} 删除结果 */ static removeFile = async (filePath) => { try { return await fs.remove(filePath); } catch (error) { console.log(`removeFile: Could not remove ${filePath}`, error); } }; }; // src/main/core/MediaManager.ts init_esm_shims(); import { systemPreferences } from "electron"; var MediaManager = class _MediaManager { static instance; static logger; static ipc; constructor() { _MediaManager.logger = getLogger("MediaManager"); _MediaManager.logger.info("\u521D\u59CB\u5316 MediaManager \u6A21\u5757"); _MediaManager.ipc = IpcManager.getInstance(); _MediaManager.setupMediaManager(); } static getInstance() { if (!_MediaManager.instance) { _MediaManager.instance = new _MediaManager(); } return _MediaManager.instance; } /** * 初始化事件处理 */ static setupMediaManager() { _MediaManager.ipc.handle("GET_MEDIA_ACCESS_STATUS" /* GET_MEDIA_ACCESS_STATUS */, (_event, args) => { return this.getMediaAccessStatus(args); }); _MediaManager.ipc.handle("ASK_FOR_MEDIA_ACCESS" /* ASK_FOR_MEDIA_ACCESS */, (_event, args) => { return this.askForMediaAccess(args); }); } /** * 获取媒体访问权限状态 * @param {MediaType} mediaType - 媒体类型 * @returns {MediaAccessStatus} - 媒体访问权限状态 */ static getMediaAccessStatus(mediaType) { return systemPreferences.getMediaAccessStatus(mediaType); } /** * 请求媒体访问权限(摄像头、麦克风) * macOS 需要请求权限 * @param {RequestMediaAccessType} mediaType - 媒体类型 * @returns {Promise<boolean>} - 是否请求成功 */ static askForMediaAccess(mediaType) { return systemPreferences.askForMediaAccess(mediaType); } }; // src/main/core/StorageManager.ts init_esm_shims(); import { app as app6, session } from "electron"; var StorageManager = class _StorageManager { static instance = {}; static logger; constructor() { _StorageManager.logger = getLogger("StorageManager"); _StorageManager.logger.info("\u521D\u59CB\u5316 StorageManager \u6A21\u5757"); _StorageManager.setupStorageManager(); } static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _StorageManager(); } return this.instance; } /** * 初始化事件处理 */ static setupStorageManager() { const ipcManager = IpcManager.getInstance(); ipcManager.handle("CLEAN_CACHE" /* CLEAN_CACHE */, async () => { this.logger.info("\u6E05\u7406\u7CFB\u7EDF\u7F13\u5B58"); return await session.defaultSession.clearCache(); }); ipcManager.on("CLEAN_STORAGE" /* CLEAN_STORAGE */, async (_event, options) => { this.logger.info("\u6E05\u7406\u7CFB\u7EDF\u5B58\u50A8"); await session.defaultSession.clearStorageData({ storages: ["serviceworkers", "filesystem", "shadercache", "websql", "indexdb", "cookies", "localstorage"] }); app6.relaunch(options); app6.exit(); }); } }; // src/main/core/SystemManager.ts init_esm_shims(); import { app as app7, globalShortcut, shell as shell3, systemPreferences as systemPreferences2 } from "electron"; import os from "node:os"; var SystemManager = class _SystemManager { static instance = {}; static appName; static env; static ipc; static logger; constructor() { _SystemManager.logger = getLogger("SystemManager"); _SystemManager.logger.info("\u521D\u59CB\u5316 SystemManager \u6A21\u5757"); _SystemManager.appName = AppManager.getInstance().getName(); _SystemManager.env = process.env.NODE_ENV; _SystemManager.ipc = IpcManager.getInstance(); _SystemManager.ignoreCertificateErrors(); _SystemManager.setUserAgent(); _SystemManager.setupSystemManager(); } static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _SystemManager(); } return this.instance; } /** * 初始化事件处理 */ static setupSystemManager() { _SystemManager.ipc.handle("GET_SYSTEM_THEME" /* GET_SYSTEM_THEME */, () => { return this.getSystemTheme(); }); _SystemManager.ipc.handle("GET_SYSTEM_INFO" /* GET_SYSTEM_INFO */, () => { return this.getSystemInfo(); }); _SystemManager.ipc.handle("OPEN_URL" /* OPEN_URL */, (_event, url) => { try { const { protocol } = new URL(url); if (["http:", "https:"].includes(protocol)) { return shell3.openExternal(url); } _SystemManager.logger.error(`\u6253\u5F00\u5916\u90E8\u94FE\u63A5\u9519\u8BEF\u3002\u65E0\u6548\u7684URL: ${url}`); return false; } catch { _SystemManager.logger.error(`\u6253\u5F00\u5916\u90E8\u94FE\u63A5\u9519\u8BEF\u3002\u65E0\u6548\u7684URL: ${url}`); return false; } }); } /** * 设置UserAgent */ static setUserAgent() { const platform2 = process.platform; const ua = app7.userAgentFallback; app7.userAgentFallback = `${ua} ${this.appName}/${this.env} ${this.appName}/${platform2}`; } /** * 注册快捷键 * @param {RegisterShortcut} shortcuts - 快捷键对象 */ registerShortcut(shortcuts) { if (!AppManager.getInstance().isReady) return; Object.entries(shortcuts).forEach(([key, value]) => { globalShortcut.register(key, value); }); } /** * 注销快捷键 */ unRegisterAllShortcut() { globalShortcut.unregisterAll(); } /** * 是否系统资源 */ systemRelease() { this.unRegisterAllShortcut(); } /** * 忽略SSL证书错误 */ static ignoreCertificateErrors() { app7.commandLine.appendSwitch("ignore-certificate-errors"); } /** * 获取系统信息 */ static getSystemInfo() { let appUsageCPU = 0; let appUsageMem = 0; const processMetrics = app7.getAppMetrics(); const processMetricsLength = processMetrics.length; for (let i = 0; i < processMetricsLength; i++) { const processMetric = processMetrics[i]; appUsageCPU += processMetric.cpu.percentCPUUsage; appUsageMem += processMetric.memory.workingSetSize; } const res = { username: os.userInfo().username, uptime: os.uptime(), arch: os.arch(), appUsageMem: bytesToSize(appUsageMem * 1024), appUsageCPU: `${appUsageCPU.toFixed(2)}%`, cpuModel: `${os.cpus()[0].model} (${os.cpus().length})`, usageMem: bytesToSize(os.totalmem() - os.freemem()), platform: platform.isMac || platform.isMacOS ? "Mac" : "Windows", osVersion: os.release(), totalMem: bytesToSize(os.totalmem()), appVersion: AppManager.getInstance().getVersion() }; return res; } /** * 获取系统主题 * macOS 获取系统主题 * @returns {Appearance} - 系统主题 */ static getSystemTheme() { return systemPreferences2.getEffectiveAppearance(); } }; // src/main/core/UpdaterManager.ts init_esm_shims(); import electronUpdater from "electron-updater"; var getAutoUpdater = () => { const { autoUpdater } = electronUpdater; return autoUpdater; }; var UpdaterManager = class _UpdaterManager { static instance = {}; static logger; static ipcManager; static updater; autoCheckData; // private isChecking: boolean = false constructor() { _UpdaterManager.logger = getLogger("UpdaterManager"); _UpdaterManager.logger.info("\u521D\u59CB\u5316 UpdaterManager \u6A21\u5757"); _UpdaterManager.ipcManager = IpcManager.getInstance(); _UpdaterManager.updater = getAutoUpdater(); _UpdaterManager.updater.forceDevUpdateConfig = true; _UpdaterManager.updater.logger = _UpdaterManager.logger; this.autoCheckData = { checkEnable: false, userCheck: false }; } /** * 获取实例 * @returns {UpdaterManager} 更新器管理器实例 */ static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _UpdaterManager(); } return this.instance; } /** * 设置更新器 * @param {UpdaterOptions} options 更新器选项 */ setupUpdaterManager(options) { _UpdaterManager.updater.autoDownload = options.autoDownload ?? false; _UpdaterManager.updater.allowDowngrade = options.allowDowngrade ?? true; _UpdaterManager.updater.autoRunAppAfterInstall = options.autoRunAppAfterInstall ?? true; _UpdaterManager.updater.autoInstallOnAppQuit = options.autoInstallOnAppQuit ?? true; this.autoCheckData = { checkEnable: options.checkEnable ?? false, userCheck: false }; ipcUpdaterEvents.forEach((event) => { _UpdaterManager.updater.removeAllListeners(event); _UpdaterManager.updater.on(event, (result) => { _UpdaterManager.ipcManager.send(event, [result]); }); }); _UpdaterManager.onRendererListener(); } /** * 设置渲染进程监听 */ static onRendererListener() { _UpdaterManager.ipcManager.handle("CHECK_FOR_UPDATES" /* CHECK_FOR_UPDATES */, (_event, url) => { _UpdaterManager.checkForUpdates(url); }); _UpdaterManager.ipcManager.handle("INSTALL_UPDATE" /* INSTALL_UPDATE */, (_event) => { _UpdaterManager.updater.quitAndInstall(); }); !_UpdaterManager.updater.autoDownload && _UpdaterManager.ipcManager.handle("DOWNLOAD_UPDATE" /* DOWNLOAD_UPDATE */, (_event) => { _UpdaterManager.downloadUpdate(); }); _UpdaterManager.ipcManager.handle("AUTO_CHECK_FOR_UPDATES" /* AUTO_CHECK_FOR_UPDATES */, (_event, url) => { _UpdaterManager.autoCheckForUpdates(url); }); } /** * 设置更新源 * @param {string} url 更新源 */ static setFeedURL(url) { _UpdaterManager.logger.info("\u8BBE\u7F6E\u66F4\u65B0\u6E90", url); _UpdaterManager.updater.setFeedURL(url); } /** * 自动更新 * @param {string} url 更新源 */ static autoCheckForUpdates(url) { if (!url) { return _UpdaterManager.ipcManager.send("error" /* UPDATE_ERROR */, ["\u66F4\u65B0\u6E90\u4E0D\u80FD\u4E3A\u7A7A"]); } _UpdaterManager.updater.autoDownload = true; _UpdaterManager.setFeedURL(url); _UpdaterManager.updater.checkForUpdatesAndNotify(); } /** * 检查更新 * @param {string} url 更新源 */ static checkForUpdates(url) { if (!url) { return _UpdaterManager.ipcManager.send("error" /* UPDATE_ERROR */, ["\u66F4\u65B0\u6E90\u4E0D\u80FD\u4E3A\u7A7A"]); } _UpdaterManager.setFeedURL(url); _UpdaterManager.updater.checkForUpdates().catch((err) => { _UpdaterManager.logger.info("\u7F51\u7EDC\u8FDE\u63A5\u95EE\u9898", err); return _UpdaterManager.ipcManager.send("error" /* UPDATE_ERROR */, ["\u68C0\u6D4B\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5"]); }); } /** * 下载更新 */ static downloadUpdate() { _UpdaterManager.updater.downloadUpdate(); } }; // src/main/index.ts var MainManager = class _MainManager { version = version; static instance = {}; // 单例 app; // 应用管理器 downloader; // 下载管理器 ipc; // ipc管理器 system; // 系统管理器 logger; // 日志管理器 autoLaunch; // 自动启动管理器 energy; // 能源管理器 window; // 窗口管理器 storage; // 存储管理器 media; // 媒体管理器 file; // 文件管理器 updater; // 更新管理器 devtool; // 开发者工具管理器 constructor() { this.logger = getLogger("NeosjsElectron"); this.app = AppManager.getInstance(); this.ipc = IpcManager.getInstance(); this.window = WindowManager.getInstance(); this.downloader = DownloadManager.getInstance(); this.system = SystemManager.getInstance(); this.autoLaunch = AutoLaunchManager.getInstance(); this.energy = EnergyManager.getInstance(); this.storage = StorageManager.getInstance(); this.media = MediaManager.getInstance(); this.file = FileManager.getInstance(); this.updater = UpdaterManager.getInstance(); this.devtool = DevtoolManager.getInstance(); } // 获取单例 static getInstance() { if (Object.keys(this.instance).length === 0) { this.instance = new _MainManager(); } return this.instance; } init(options = { browserWindow: null }) { const { updater = {}, browserWindow = null, shortcutOptions = {} } = options; this.window.setupWindowManager(browserWindow, shortcutOptions); this.updater.setupUpdaterManager(updater); this.logger.info("\u521D\u59CB\u5316 NeosElectron \u5B8C\u6210"); } }; var mainManager = MainManager.getInstance(); var main_default = mainManager; export { main_default as default };