'init'
Some checks failed
Upstream Sync / Sync latest commits from upstream repo (push) Has been cancelled
Some checks failed
Upstream Sync / Sync latest commits from upstream repo (push) Has been cancelled
This commit is contained in:
224
electron/src/main/appHost.ts
Normal file
224
electron/src/main/appHost.ts
Normal file
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* Electron app 模块:开机启动、跳转列表、关于面板、日志路径、角标、优雅重启、指标等。
|
||||
* 文档:https://www.electronjs.org/docs/latest/api/app
|
||||
*/
|
||||
import { app, BrowserWindow, ipcMain, shell } from 'electron'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
const VALID_NAV = new Set(['desk', 'record', 'network', 'proxy', 'system', 'wechat'])
|
||||
|
||||
export function parseNavFromArgv(argv: string[]): string | null {
|
||||
for (const a of argv) {
|
||||
const m = /^--nav=(.+)$/.exec(a)
|
||||
if (!m) continue
|
||||
const id = m[1].trim()
|
||||
if (VALID_NAV.has(id)) return id
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/** 须在 app.ready 之前调用(Windows Toast / 任务栏分组) */
|
||||
export function setAppUserModelIdEarly(): void {
|
||||
if (process.platform !== 'win32') return
|
||||
try {
|
||||
app.setAppUserModelId('com.douyin.recorder.console')
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
function readPackageJsonField(field: 'description' | 'version'): string {
|
||||
try {
|
||||
const candidates = [
|
||||
path.join(app.getAppPath(), 'package.json'),
|
||||
path.join(process.cwd(), 'package.json'),
|
||||
]
|
||||
for (const p of candidates) {
|
||||
if (fs.existsSync(p)) {
|
||||
const j = JSON.parse(fs.readFileSync(p, 'utf-8')) as Record<string, unknown>
|
||||
const v = j[field]
|
||||
if (typeof v === 'string') return v
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
/** ready 后立即调用 */
|
||||
export function applyAppHostBootstrap(getBackendRoot: () => string): void {
|
||||
try {
|
||||
const logDir = path.join(app.getPath('userData'), 'logs')
|
||||
app.setAppLogsPath(logDir)
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
|
||||
const ver = app.getVersion()
|
||||
const desc = readPackageJsonField('description') || '直播录制与转播控制台'
|
||||
app.setAboutPanelOptions({
|
||||
applicationName: app.getName(),
|
||||
applicationVersion: ver,
|
||||
copyright: `Copyright © ${new Date().getFullYear()}`,
|
||||
credits: desc,
|
||||
})
|
||||
|
||||
if (process.env.WEB2_SECURE_DNS === '1') {
|
||||
try {
|
||||
app.configureHostResolver({ secureDnsMode: 'automatic' })
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
const proxy = process.env.WEB2_ELECTRON_GLOBAL_PROXY?.trim()
|
||||
if (proxy) {
|
||||
try {
|
||||
void app.setProxy({ proxyRules: proxy })
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
try {
|
||||
app.setUserTasks([
|
||||
{
|
||||
program: process.execPath,
|
||||
arguments: '--nav=desk',
|
||||
title: '工作台',
|
||||
description: '打开工作台仪表盘',
|
||||
iconPath: process.execPath,
|
||||
iconIndex: 0,
|
||||
},
|
||||
{
|
||||
program: process.execPath,
|
||||
arguments: '--nav=record',
|
||||
title: '录制',
|
||||
description: '打开录制与转播控制',
|
||||
iconPath: process.execPath,
|
||||
iconIndex: 0,
|
||||
},
|
||||
{
|
||||
program: process.execPath,
|
||||
arguments: '--nav=network',
|
||||
title: '网络',
|
||||
description: '网络与远程绑定',
|
||||
iconPath: process.execPath,
|
||||
iconIndex: 0,
|
||||
},
|
||||
])
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function registerAppHostIpcHandlers(getBackendRoot: () => string): void {
|
||||
ipcMain.removeHandler('app:get-login-item')
|
||||
ipcMain.handle('app:get-login-item', () => {
|
||||
try {
|
||||
return app.getLoginItemSettings()
|
||||
} catch {
|
||||
return { openAtLogin: false }
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.removeHandler('app:set-login-item')
|
||||
ipcMain.handle('app:set-login-item', (_evt, openAtLogin: unknown) => {
|
||||
if (typeof openAtLogin !== 'boolean') return { ok: false as const, error: '参数无效' }
|
||||
try {
|
||||
app.setLoginItemSettings({
|
||||
openAtLogin,
|
||||
path: process.execPath,
|
||||
args: [],
|
||||
})
|
||||
return { ok: true as const }
|
||||
} catch (e) {
|
||||
return { ok: false as const, error: e instanceof Error ? e.message : String(e) }
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.removeHandler('app:relaunch')
|
||||
ipcMain.handle('app:relaunch', () => {
|
||||
app.relaunch()
|
||||
app.exit(0)
|
||||
})
|
||||
|
||||
ipcMain.removeHandler('app:get-metrics')
|
||||
ipcMain.handle('app:get-metrics', () => {
|
||||
try {
|
||||
return app.getAppMetrics()
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.removeHandler('app:show-about')
|
||||
ipcMain.handle('app:show-about', () => {
|
||||
try {
|
||||
app.showAboutPanel()
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.removeHandler('app:set-badge')
|
||||
ipcMain.handle('app:set-badge', (_evt, count: unknown) => {
|
||||
const n = typeof count === 'number' && Number.isFinite(count) ? Math.max(0, Math.floor(count)) : 0
|
||||
try {
|
||||
if (process.platform === 'darwin' || process.platform === 'linux') {
|
||||
app.setBadgeCount(n)
|
||||
}
|
||||
} catch {
|
||||
/* Windows 无 dock 角标,忽略 */
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.removeHandler('app:get-paths')
|
||||
ipcMain.handle('app:get-paths', () => {
|
||||
const br = getBackendRoot()
|
||||
return {
|
||||
userData: app.getPath('userData'),
|
||||
logs: app.getPath('logs'),
|
||||
temp: app.getPath('temp'),
|
||||
backendRoot: br,
|
||||
backendConfig: path.join(br, 'config'),
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.removeHandler('app:add-recent-config')
|
||||
ipcMain.handle('app:add-recent-config', () => {
|
||||
const cfg = path.join(getBackendRoot(), 'config')
|
||||
try {
|
||||
if (fs.existsSync(cfg)) {
|
||||
app.addRecentDocument(cfg)
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.removeHandler('app:open-logs-folder')
|
||||
ipcMain.handle('app:open-logs-folder', async () => {
|
||||
const p = app.getPath('logs')
|
||||
try {
|
||||
await fs.promises.mkdir(p, { recursive: true })
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
const err = await shell.openPath(p)
|
||||
if (err) throw new Error(err)
|
||||
})
|
||||
}
|
||||
|
||||
export function sendNavToWindow(win: BrowserWindow, nav: string): void {
|
||||
if (!VALID_NAV.has(nav)) return
|
||||
try {
|
||||
win.webContents.send('app:nav', nav)
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user