From 972d2fe946e054a362956d7c121774c9daf637c4 Mon Sep 17 00:00:00 2001 From: xmk23333 Date: Mon, 8 Dec 2025 22:32:14 +0800 Subject: [PATCH] fix: add missing await keywords and refactor duplicate code --- src/main/config/override.ts | 4 +-- src/main/config/smartOverride.ts | 32 +++++------------ src/main/core/manager.ts | 19 +--------- src/main/index.ts | 30 ++++------------ src/main/resolve/backup.ts | 62 +++++++++++--------------------- src/main/utils/init.ts | 10 +++--- 6 files changed, 42 insertions(+), 115 deletions(-) diff --git a/src/main/config/override.ts b/src/main/config/override.ts index 7e7e1ea..16db1a0 100644 --- a/src/main/config/override.ts +++ b/src/main/config/override.ts @@ -40,7 +40,7 @@ export async function addOverrideItem(item: Partial): Promise): Promise { smartCollectorSize ) - // 检查是否已存在 Smart 覆写配置 - const existingOverride = await getOverrideItem(SMART_OVERRIDE_ID) - - if (existingOverride) { - // 如果已存在,更新配置 - await addOverrideItem({ - id: SMART_OVERRIDE_ID, - name: 'Smart Core Override', - type: 'local', - ext: 'js', - global: true, - file: template - }) - } else { - // 如果不存在,创建新的覆写配置 - await addOverrideItem({ - id: SMART_OVERRIDE_ID, - name: 'Smart Core Override', - type: 'local', - ext: 'js', - global: true, - file: template - }) - } + await addOverrideItem({ + id: SMART_OVERRIDE_ID, + name: 'Smart Core Override', + type: 'local', + ext: 'js', + global: true, + file: template + }) } catch (error) { await overrideLogger.error('Failed to create Smart override', error) throw error diff --git a/src/main/core/manager.ts b/src/main/core/manager.ts index bc7dbd2..d076930 100644 --- a/src/main/core/manager.ts +++ b/src/main/core/manager.ts @@ -499,24 +499,7 @@ async function checkProfile(): Promise { } export async function checkTunPermissions(): Promise { - const { core = 'mihomo' } = await getAppConfig() - const corePath = mihomoCorePath(core) - - try { - if (process.platform === 'win32') { - return await checkAdminPrivileges() - } - - if (process.platform === 'darwin' || process.platform === 'linux') { - const { stat } = await import('fs/promises') - const stats = await stat(corePath) - return (stats.mode & 0o4000) !== 0 && stats.uid === 0 - } - } catch { - return false - } - - return false + return checkMihomoCorePermissions() } export async function grantTunPermissions(): Promise { diff --git a/src/main/index.ts b/src/main/index.ts index 12711bb..4ba2fb3 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -7,7 +7,7 @@ import { quitWithoutCore, startCore, stopCore, checkAdminRestartForTun, checkHig import { triggerSysProxy } from './sys/sysproxy' import icon from '../../resources/icon.png?asset' import { createTray, hideDockIcon, showDockIcon } from './resolve/tray' -import { init, initBasic } from './utils/init' +import { init, initBasic, safeShowErrorBox } from './utils/init' import { join } from 'path' import { initShortcut } from './resolve/shortcut' import { spawn, exec } from 'child_process' @@ -23,24 +23,6 @@ import i18next from 'i18next' import { logger } from './utils/logger' import { initWebdavBackupScheduler } from './resolve/backup' -// 错误处理 -function showSafeErrorBox(titleKey: string, message: string): void { - let title: string - try { - title = i18next.t(titleKey) - if (!title || title === titleKey) throw new Error('Translation not ready') - } catch { - const isZh = app.getLocale().startsWith('zh') - const fallbacks: Record = { - 'common.error.initFailed': { zh: '应用初始化失败', en: 'Application initialization failed' }, - 'mihomo.error.coreStartFailed': { zh: '内核启动出错', en: 'Core start failed' }, - 'profiles.error.importFailed': { zh: '配置导入失败', en: 'Profile import failed' }, - 'common.error.adminRequired': { zh: '需要管理员权限', en: 'Administrator privileges required' } - } - title = fallbacks[titleKey] ? (isZh ? fallbacks[titleKey].zh : fallbacks[titleKey].en) : (isZh ? '错误' : 'Error') - } - dialog.showErrorBox(title, message) -} async function fixUserDataPermissions(): Promise { if (process.platform !== 'darwin') return @@ -80,7 +62,7 @@ async function initApp(): Promise { initApp() .catch((e) => { - showSafeErrorBox('common.error.initFailed', `${e}`) + safeShowErrorBox('common.error.initFailed', `${e}`) app.quit() }) @@ -150,7 +132,7 @@ async function checkHighPrivilegeCoreEarly(): Promise { await restartAsAdmin(false) process.exit(0) } catch (error) { - showSafeErrorBox('common.error.adminRequired', `${error}`) + safeShowErrorBox('common.error.adminRequired', `${error}`) process.exit(1) } } else { @@ -234,7 +216,7 @@ app.whenReady().then(async () => { } await initI18n({ lng: appConfig.language }) } catch (e) { - showSafeErrorBox('common.error.initFailed', `${e}`) + safeShowErrorBox('common.error.initFailed', `${e}`) app.quit() } @@ -247,7 +229,7 @@ app.whenReady().then(async () => { await checkAdminRestartForTun() }) } catch (e) { - showSafeErrorBox('mihomo.error.coreStartFailed', `${e}`) + safeShowErrorBox('mihomo.error.coreStartFailed', `${e}`) } try { await startMonitor() @@ -303,7 +285,7 @@ async function handleDeepLink(url: string): Promise { new Notification({ title: i18next.t('profiles.notification.importSuccess') }).show() break } catch (e) { - showSafeErrorBox('profiles.error.importFailed', `${url}\n${e}`) + safeShowErrorBox('profiles.error.importFailed', `${url}\n${e}`) } } } diff --git a/src/main/resolve/backup.ts b/src/main/resolve/backup.ts index 1eb3bdf..639b484 100644 --- a/src/main/resolve/backup.ts +++ b/src/main/resolve/backup.ts @@ -21,7 +21,13 @@ import i18next from 'i18next' let backupCronJob: Cron | null = null -export async function webdavBackup(): Promise { +interface WebDAVContext { + client: ReturnType['createClient']> + webdavDir: string + webdavMaxBackups: number +} + +async function getWebDAVClient(): Promise { const { createClient } = await import('webdav/dist/node/index.js') const { webdavUrl = '', @@ -30,6 +36,17 @@ export async function webdavBackup(): Promise { webdavDir = 'clash-party', webdavMaxBackups = 0 } = await getAppConfig() + + const client = createClient(webdavUrl, { + username: webdavUsername, + password: webdavPassword + }) + + return { client, webdavDir, webdavMaxBackups } +} + +export async function webdavBackup(): Promise { + const { client, webdavDir, webdavMaxBackups } = await getWebDAVClient() const zip = new AdmZip() zip.addLocalFile(appConfigPath()) @@ -44,10 +61,6 @@ export async function webdavBackup(): Promise { const date = new Date() const zipFileName = `${process.platform}_${dayjs(date).format('YYYY-MM-DD_HH-mm-ss')}.zip` - const client = createClient(webdavUrl, { - username: webdavUsername, - password: webdavPassword - }) try { await client.createDirectory(webdavDir) } catch { @@ -92,36 +105,14 @@ export async function webdavBackup(): Promise { } export async function webdavRestore(filename: string): Promise { - const { createClient } = await import('webdav/dist/node/index.js') - const { - webdavUrl = '', - webdavUsername = '', - webdavPassword = '', - webdavDir = 'clash-party' - } = await getAppConfig() - - const client = createClient(webdavUrl, { - username: webdavUsername, - password: webdavPassword - }) + const { client, webdavDir } = await getWebDAVClient() const zipData = await client.getFileContents(`${webdavDir}/${filename}`) const zip = new AdmZip(zipData as Buffer) zip.extractAllTo(dataDir(), true) } export async function listWebdavBackups(): Promise { - const { createClient } = await import('webdav/dist/node/index.js') - const { - webdavUrl = '', - webdavUsername = '', - webdavPassword = '', - webdavDir = 'clash-party' - } = await getAppConfig() - - const client = createClient(webdavUrl, { - username: webdavUsername, - password: webdavPassword - }) + const { client, webdavDir } = await getWebDAVClient() const files = await client.getDirectoryContents(webdavDir, { glob: '*.zip' }) if (Array.isArray(files)) { return files.map((file) => file.basename) @@ -131,18 +122,7 @@ export async function listWebdavBackups(): Promise { } export async function webdavDelete(filename: string): Promise { - const { createClient } = await import('webdav/dist/node/index.js') - const { - webdavUrl = '', - webdavUsername = '', - webdavPassword = '', - webdavDir = 'clash-party' - } = await getAppConfig() - - const client = createClient(webdavUrl, { - username: webdavUsername, - password: webdavPassword - }) + const { client, webdavDir } = await getWebDAVClient() await client.deleteFile(`${webdavDir}/${filename}`) } diff --git a/src/main/utils/init.ts b/src/main/utils/init.ts index 844d021..1bad56c 100644 --- a/src/main/utils/init.ts +++ b/src/main/utils/init.ts @@ -42,7 +42,7 @@ import { } from '../config' import { app, dialog } from 'electron' import { startSSIDCheck } from '../sys/ssid' -import i18next from '../../shared/i18n' +import i18next, { resources } from '../../shared/i18n' import { initLogger } from './logger' let isInitBasicCompleted = false @@ -54,11 +54,9 @@ export function safeShowErrorBox(titleKey: string, message: string): void { title = i18next.t(titleKey) if (!title || title === titleKey) throw new Error('Translation not ready') } catch { - const isZh = process.env.LANG?.startsWith('zh') || process.env.LC_ALL?.startsWith('zh') - const fallbacks: Record = { - 'mihomo.error.coreStartFailed': { zh: '内核启动出错', en: 'Core start failed' } - } - title = fallbacks[titleKey] ? (isZh ? fallbacks[titleKey].zh : fallbacks[titleKey].en) : (isZh ? '错误' : 'Error') + const isZh = app.getLocale().startsWith('zh') + const lang = isZh ? resources['zh-CN'].translation : resources['en-US'].translation + title = lang[titleKey] || (isZh ? '错误' : 'Error') } dialog.showErrorBox(title, message) }