mirror of
https://github.com/viarotel-org/escrcpy.git
synced 2025-02-26 06:18:15 +01:00
158 lines
4.3 KiB
JavaScript
158 lines
4.3 KiB
JavaScript
import { app, BrowserWindow } from 'electron'
|
||
|
||
/**
|
||
* 确保 Electron 应用只运行一个实例的工具函数
|
||
* @typedef {Object} SingleInstanceOptions
|
||
* @property {Function} [onSecondInstance] - 当第二个实例启动时的回调函数
|
||
* @property {boolean} [enableSandbox=false] - 是否启用沙箱模式
|
||
* @property {Function} [onSuccess] - 成功获取单例锁后的回调函数
|
||
* @property {Function} [onShowWindow] - 主窗口已展示回调
|
||
* @property {boolean} [forceFocus=true] - 是否强制聚焦已存在的窗口
|
||
* @property {boolean} [silentMode=false] - 静默模式,不显示任何提示
|
||
* @property {Function} [onError] - 错误处理回调函数
|
||
*/
|
||
|
||
/**
|
||
* 第二个实例启动时的回调函数类型
|
||
* @callback OnSecondInstanceCallback
|
||
* @param {Event} event - Electron 事件对象
|
||
* @param {string[]} commandLine - 命令行参数数组
|
||
* @param {string} workingDirectory - 工作目录
|
||
* @param {BrowserWindow|null} mainWindow - 主窗口实例,如果存在的话
|
||
*/
|
||
|
||
/**
|
||
* 确保应用程序只运行单个实例
|
||
* @param {SingleInstanceOptions} options - 配置选项
|
||
* @returns {boolean} 是否成功获取单例锁
|
||
*
|
||
* @example
|
||
* // 基础使用
|
||
* ensureSingleInstance({
|
||
* onSuccess: () => {
|
||
* app.whenReady().then(createWindow)
|
||
* }
|
||
* });
|
||
*
|
||
* @example
|
||
* // 高级使用
|
||
* ensureSingleInstance({
|
||
* onSecondInstance: (event, commandLine, workingDirectory, mainWindow) => {
|
||
* if (mainWindow) {
|
||
* mainWindow.webContents.send('new-instance-launched', commandLine);
|
||
* }
|
||
* },
|
||
* onSuccess: () => {
|
||
* console.log('Successfully acquired lock');
|
||
* createWindow();
|
||
* },
|
||
* onError: (error) => {
|
||
* console.error('Error in single instance check:', error);
|
||
* },
|
||
* forceFocus: true,
|
||
* silentMode: false
|
||
* });
|
||
*
|
||
* @throws {Error} 如果在非 Electron 环境中调用
|
||
*/
|
||
function ensureSingleInstance(options = {}) {
|
||
// 参数解构与默认值设置
|
||
const {
|
||
onSecondInstance,
|
||
enableSandbox = false,
|
||
onSuccess,
|
||
onShowWindow,
|
||
onError,
|
||
forceFocus = true,
|
||
silentMode = false,
|
||
} = options
|
||
|
||
// 验证运行环境
|
||
if (!app || !BrowserWindow) {
|
||
const error = new Error('ensureSingleInstance must be called in Electron environment')
|
||
if (onError) {
|
||
onError(error)
|
||
return false
|
||
}
|
||
throw error
|
||
}
|
||
|
||
try {
|
||
// 沙箱模式检查
|
||
if (enableSandbox) {
|
||
!silentMode && console.log('Sandbox mode enabled, skipping single instance check')
|
||
onSuccess?.()
|
||
return true
|
||
}
|
||
|
||
// 请求单例锁
|
||
const gotTheLock = app.requestSingleInstanceLock()
|
||
|
||
// 如果无法获取锁,说明已有实例在运行
|
||
if (!gotTheLock) {
|
||
!silentMode && console.log('Application instance already running, quitting...')
|
||
app.quit()
|
||
return false
|
||
}
|
||
|
||
// 监听第二个实例的启动
|
||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||
try {
|
||
// 获取所有窗口
|
||
const windows = BrowserWindow.getAllWindows()
|
||
const mainWindow = windows.length ? windows[0] : null
|
||
|
||
// 处理窗口焦点
|
||
onShowWindow?.(mainWindow, commandLine)
|
||
|
||
if (mainWindow) {
|
||
if (mainWindow.isMinimized() || !mainWindow.isVisible()) {
|
||
mainWindow.show()
|
||
}
|
||
if (forceFocus) {
|
||
mainWindow.focus()
|
||
}
|
||
}
|
||
|
||
// 调用用户自定义的回调
|
||
onSecondInstance?.(event, commandLine, workingDirectory, mainWindow)
|
||
}
|
||
catch (error) {
|
||
!silentMode && console.error('Error handling second instance:', error)
|
||
onError?.(error)
|
||
}
|
||
})
|
||
|
||
// 调用成功回调
|
||
onSuccess?.()
|
||
return true
|
||
}
|
||
catch (error) {
|
||
!silentMode && console.error('Error in ensureSingleInstance:', error)
|
||
onError?.(error)
|
||
return false
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查当前是否为应用程序的主实例
|
||
* @returns {boolean} 如果是主实例返回 true,否则返回 false
|
||
*/
|
||
function isMainInstance() {
|
||
return app.requestSingleInstanceLock()
|
||
}
|
||
|
||
/**
|
||
* 释放单例锁,允许其他实例启动
|
||
* @returns {void}
|
||
*/
|
||
function releaseSingleInstanceLock() {
|
||
app.releaseSingleInstanceLock()
|
||
}
|
||
|
||
export {
|
||
ensureSingleInstance,
|
||
isMainInstance,
|
||
releaseSingleInstanceLock,
|
||
}
|