@neosjs/electron-toolkit
Version:
neosjs electron toolkit
1,360 lines (1,338 loc) • 42.8 kB
JavaScript
/*!
* @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
};