fix: resolve async/null-safety issues in lifecycle, config and ipc modules

This commit is contained in:
xmk23333 2026-01-01 10:33:01 +08:00
parent 9e5d11c3c8
commit 3097019e9e
8 changed files with 74 additions and 59 deletions

View File

@ -54,9 +54,12 @@ export async function addOverrideItem(item: Partial<IOverrideItem>): Promise<voi
export async function removeOverrideItem(id: string): Promise<void> { export async function removeOverrideItem(id: string): Promise<void> {
const config = await getOverrideConfig() const config = await getOverrideConfig()
const item = await getOverrideItem(id) const item = await getOverrideItem(id)
config.items = config.items?.filter((item) => item.id !== id) if (!item) return
config.items = config.items?.filter((i) => i.id !== id)
await setOverrideConfig(config) await setOverrideConfig(config)
await rm(overridePath(id, item?.ext || 'js')) if (existsSync(overridePath(id, item.ext))) {
await rm(overridePath(id, item.ext))
}
} }
export async function createOverride(item: Partial<IOverrideItem>): Promise<IOverrideItem> { export async function createOverride(item: Partial<IOverrideItem>): Promise<IOverrideItem> {

View File

@ -368,13 +368,17 @@ export async function getProfile(id: string | undefined): Promise<IMihomoConfig>
// attachment;filename=xxx.yaml; filename*=UTF-8''%xx%xx%xx // attachment;filename=xxx.yaml; filename*=UTF-8''%xx%xx%xx
function parseFilename(str: string): string { function parseFilename(str: string): string {
if (str.match(/filename\*=.*''/)) { if (str.match(/filename\*=.*''/)) {
const filename = decodeURIComponent(str.split(/filename\*=.*''/)[1]) const parts = str.split(/filename\*=.*''/)
return filename if (parts[1]) {
} else { return decodeURIComponent(parts[1])
const filename = str.split('filename=')[1]
return filename
} }
} }
const parts = str.split('filename=')
if (parts[1]) {
return parts[1].replace(/^["']|["']$/g, '')
}
return 'Remote File'
}
// subscription-userinfo: upload=1234; download=2234; total=1024000; expire=2218532293 // subscription-userinfo: upload=1234; download=2234; total=1024000; expire=2218532293
function parseSubinfo(str: string): ISubscriptionUserInfo { function parseSubinfo(str: string): ISubscriptionUserInfo {

View File

@ -25,8 +25,8 @@ import { createLogger } from '../utils/logger'
const factoryLogger = createLogger('Factory') const factoryLogger = createLogger('Factory')
let runtimeConfigStr: string let runtimeConfigStr: string = ''
let runtimeConfig: IMihomoConfig let runtimeConfig: IMihomoConfig = {} as IMihomoConfig
// 辅助函数:处理带偏移量的规则 // 辅助函数:处理带偏移量的规则
function processRulesWithOffset(ruleStrings: string[], currentRules: string[], isAppend = false) { function processRulesWithOffset(ruleStrings: string[], currentRules: string[], isAppend = false) {

View File

@ -14,8 +14,7 @@ done
${process.argv.join(' ')} & disown ${process.argv.join(' ')} & disown
exit exit
` `
spawn('sh', ['-c', `"${script}"`], { spawn('sh', ['-c', script], {
shell: true,
detached: true, detached: true,
stdio: 'ignore' stdio: 'ignore'
}) })
@ -57,7 +56,7 @@ export function setupPlatformSpecifics(): void {
export function setupAppLifecycle(): void { export function setupAppLifecycle(): void {
app.on('before-quit', async (e) => { app.on('before-quit', async (e) => {
e.preventDefault() e.preventDefault()
triggerSysProxy(false) await triggerSysProxy(false)
await stopCore() await stopCore()
app.exit() app.exit()
}) })

View File

@ -10,14 +10,15 @@ import axios from 'axios'
import fs from 'fs' import fs from 'fs'
import { proxyLogger } from '../utils/logger' import { proxyLogger } from '../utils/logger'
let defaultBypass: string[]
let triggerSysProxyTimer: NodeJS.Timeout | null = null let triggerSysProxyTimer: NodeJS.Timeout | null = null
const helperSocketPath = '/tmp/mihomo-party-helper.sock' const helperSocketPath = '/tmp/mihomo-party-helper.sock'
if (process.platform === 'linux') const defaultBypass: string[] = (() => {
defaultBypass = ['localhost', '127.0.0.1', '192.168.0.0/16', '10.0.0.0/8', '172.16.0.0/12', '::1'] switch (process.platform) {
if (process.platform === 'darwin') case 'linux':
defaultBypass = [ return ['localhost', '127.0.0.1', '192.168.0.0/16', '10.0.0.0/8', '172.16.0.0/12', '::1']
case 'darwin':
return [
'127.0.0.1', '127.0.0.1',
'192.168.0.0/16', '192.168.0.0/16',
'10.0.0.0/8', '10.0.0.0/8',
@ -27,8 +28,8 @@ if (process.platform === 'darwin')
'*.crashlytics.com', '*.crashlytics.com',
'<local>' '<local>'
] ]
if (process.platform === 'win32') case 'win32':
defaultBypass = [ return [
'localhost', 'localhost',
'127.*', '127.*',
'192.168.*', '192.168.*',
@ -51,6 +52,10 @@ if (process.platform === 'win32')
'172.31.*', '172.31.*',
'<local>' '<local>'
] ]
default:
return ['localhost', '127.0.0.1', '192.168.0.0/16', '10.0.0.0/8', '172.16.0.0/12', '::1']
}
})()
export async function triggerSysProxy(enable: boolean): Promise<void> { export async function triggerSysProxy(enable: boolean): Promise<void> {
if (net.isOnline()) { if (net.isOnline()) {

View File

@ -213,8 +213,12 @@ async function cleanup(): Promise<void> {
// logs // logs
const { maxLogDays = 7 } = await getAppConfig() const { maxLogDays = 7 } = await getAppConfig()
const logs = await readdir(logDir()) const logs = await readdir(logDir())
const datePattern = /^\d{4}-\d{2}-\d{2}/
for (const log of logs) { for (const log of logs) {
const date = new Date(log.split('.')[0]) const match = log.match(datePattern)
if (!match) continue
const date = new Date(match[0])
if (isNaN(date.getTime())) continue
const diff = Date.now() - date.getTime() const diff = Date.now() - date.getTime()
if (diff > maxLogDays * 24 * 60 * 60 * 1000) { if (diff > maxLogDays * 24 * 60 * 60 * 1000) {
try { try {

View File

@ -118,7 +118,7 @@ function setupWindowEvents(
}) })
window.on('session-end', async () => { window.on('session-end', async () => {
triggerSysProxy(false) await triggerSysProxy(false)
await stopCore() await stopCore()
}) })

View File

@ -196,10 +196,11 @@ export const writeTheme = (theme: string, css: string): Promise<void> =>
invoke('writeTheme', theme, css) invoke('writeTheme', theme, css)
let applyThemeRunning = false let applyThemeRunning = false
const applyThemeWaitList: string[] = [] let pendingTheme: string | null = null
export async function applyTheme(theme: string): Promise<void> { export async function applyTheme(theme: string): Promise<void> {
if (applyThemeRunning) { if (applyThemeRunning) {
applyThemeWaitList.push(theme) pendingTheme = theme
return return
} }
applyThemeRunning = true applyThemeRunning = true
@ -207,14 +208,13 @@ export async function applyTheme(theme: string): Promise<void> {
await invoke<void>('applyTheme', theme) await invoke<void>('applyTheme', theme)
} finally { } finally {
applyThemeRunning = false applyThemeRunning = false
if (applyThemeWaitList.length > 0) { if (pendingTheme !== null) {
const nextTheme = applyThemeWaitList.shift() const nextTheme = pendingTheme
if (nextTheme) { pendingTheme = null
await applyTheme(nextTheme) await applyTheme(nextTheme)
} }
} }
} }
}
// Tray // Tray
export const showTrayIcon = (): Promise<void> => invoke('showTrayIcon') export const showTrayIcon = (): Promise<void> => invoke('showTrayIcon')