mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 05:00:30 +08:00
fix format and lint
This commit is contained in:
parent
b7d6ea8e7a
commit
54bb819e28
@ -1,4 +0,0 @@
|
|||||||
node_modules
|
|
||||||
dist
|
|
||||||
out
|
|
||||||
.gitignore
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
extends: [
|
|
||||||
'eslint:recommended',
|
|
||||||
'plugin:react/recommended',
|
|
||||||
'plugin:react/jsx-runtime',
|
|
||||||
'@electron-toolkit/eslint-config-ts/recommended',
|
|
||||||
'@electron-toolkit/eslint-config-prettier'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
48
eslint.config.cjs
Normal file
48
eslint.config.cjs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
const js = require('@eslint/js')
|
||||||
|
const react = require('eslint-plugin-react')
|
||||||
|
const { configs } = require('@electron-toolkit/eslint-config-ts')
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
ignores: ['**/node_modules/**', '**/dist/**', '**/out/**', '**/extra/**']
|
||||||
|
},
|
||||||
|
|
||||||
|
js.configs.recommended,
|
||||||
|
...configs.recommended,
|
||||||
|
|
||||||
|
{
|
||||||
|
files: ['**/*.{js,jsx,ts,tsx}'],
|
||||||
|
plugins: {
|
||||||
|
react: react
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
...react.configs.recommended.rules,
|
||||||
|
...react.configs['jsx-runtime'].rules
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
react: {
|
||||||
|
version: 'detect'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
languageOptions: {
|
||||||
|
...react.configs.recommended.languageOptions
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
files: ['**/*.cjs', '**/*.mjs', '**/tailwind.config.js', '**/postcss.config.js'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-require-imports': 'off',
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 'off'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-unused-vars': 0,
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'warn'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import AdmZip from 'adm-zip'
|
import AdmZip from 'adm-zip'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|||||||
@ -9,9 +9,7 @@ import {
|
|||||||
} from './version-utils.mjs'
|
} from './version-utils.mjs'
|
||||||
|
|
||||||
const chat_id = '@MihomoPartyChannel'
|
const chat_id = '@MihomoPartyChannel'
|
||||||
const pkg = readFileSync('package.json', 'utf-8')
|
|
||||||
const changelog = readFileSync('changelog.md', 'utf-8')
|
const changelog = readFileSync('changelog.md', 'utf-8')
|
||||||
const { version: packageVersion } = JSON.parse(pkg)
|
|
||||||
|
|
||||||
// 获取处理后的版本号
|
// 获取处理后的版本号
|
||||||
const version = getProcessedVersion()
|
const version = getProcessedVersion()
|
||||||
|
|||||||
@ -7,9 +7,7 @@ import {
|
|||||||
generateDownloadLinksMarkdown
|
generateDownloadLinksMarkdown
|
||||||
} from './version-utils.mjs'
|
} from './version-utils.mjs'
|
||||||
|
|
||||||
const pkg = readFileSync('package.json', 'utf-8')
|
|
||||||
let changelog = readFileSync('changelog.md', 'utf-8')
|
let changelog = readFileSync('changelog.md', 'utf-8')
|
||||||
const { version: packageVersion } = JSON.parse(pkg)
|
|
||||||
|
|
||||||
// 获取处理后的版本号
|
// 获取处理后的版本号
|
||||||
const version = getProcessedVersion()
|
const version = getProcessedVersion()
|
||||||
|
|||||||
@ -78,7 +78,7 @@ export async function createOverride(item: Partial<IOverrideItem>): Promise<IOve
|
|||||||
},
|
},
|
||||||
responseType: 'text'
|
responseType: 'text'
|
||||||
})
|
})
|
||||||
const data = res.data
|
const data = res.data as string
|
||||||
await setOverride(id, newItem.ext, data)
|
await setOverride(id, newItem.ext, data)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@ -418,7 +418,9 @@ export async function convertMrsRuleset(filePath: string, behavior: string): Pro
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
try {
|
try {
|
||||||
await unlink(tempFilePath)
|
await unlink(tempFilePath)
|
||||||
} catch {}
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ let runtimeConfig: IMihomoConfig
|
|||||||
// 辅助函数:处理带偏移量的规则
|
// 辅助函数:处理带偏移量的规则
|
||||||
function processRulesWithOffset(ruleStrings: string[], currentRules: string[], isAppend = false) {
|
function processRulesWithOffset(ruleStrings: string[], currentRules: string[], isAppend = false) {
|
||||||
const normalRules: string[] = []
|
const normalRules: string[] = []
|
||||||
let rules = [...currentRules]
|
const rules = [...currentRules]
|
||||||
|
|
||||||
ruleStrings.forEach((ruleStr) => {
|
ruleStrings.forEach((ruleStr) => {
|
||||||
const parts = ruleStr.split(',')
|
const parts = ruleStr.split(',')
|
||||||
@ -65,7 +65,7 @@ export async function generateProfile(): Promise<void> {
|
|||||||
controlSniff = true,
|
controlSniff = true,
|
||||||
useNameserverPolicy
|
useNameserverPolicy
|
||||||
} = await getAppConfig()
|
} = await getAppConfig()
|
||||||
let currentProfile = await overrideProfile(current, await getProfile(current))
|
const currentProfile = await overrideProfile(current, await getProfile(current))
|
||||||
let controledMihomoConfig = await getControledMihomoConfig()
|
let controledMihomoConfig = await getControledMihomoConfig()
|
||||||
|
|
||||||
// 根据开关状态过滤控制配置
|
// 根据开关状态过滤控制配置
|
||||||
@ -132,7 +132,7 @@ export async function generateProfile(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('读取或应用规则文件时出错:', error)
|
console.error('读取或应用规则文件时出错:', error)
|
||||||
}
|
}
|
||||||
|
|
||||||
const profile = deepMerge(currentProfile, controledMihomoConfig)
|
const profile = deepMerge(currentProfile, controledMihomoConfig)
|
||||||
|
|||||||
@ -330,8 +330,8 @@ async function cleanupWindowsNamedPipes(): Promise<void> {
|
|||||||
process.kill(pid, 0)
|
process.kill(pid, 0)
|
||||||
process.kill(pid, 'SIGTERM')
|
process.kill(pid, 'SIGTERM')
|
||||||
await managerLogger.info(`Terminated process ${pid} to free pipe`)
|
await managerLogger.info(`Terminated process ${pid} to free pipe`)
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
if (error.code !== 'ESRCH') {
|
if ((error as { code?: string })?.code !== 'ESRCH') {
|
||||||
await managerLogger.warn(`Failed to terminate process ${pid}:`, error)
|
await managerLogger.warn(`Failed to terminate process ${pid}:`, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,8 +351,8 @@ async function cleanupWindowsNamedPipes(): Promise<void> {
|
|||||||
process.kill(pid, 0)
|
process.kill(pid, 0)
|
||||||
process.kill(pid, 'SIGTERM')
|
process.kill(pid, 'SIGTERM')
|
||||||
await managerLogger.info(`Terminated process ${pid} to free pipe`)
|
await managerLogger.info(`Terminated process ${pid} to free pipe`)
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
if (error.code !== 'ESRCH') {
|
if ((error as { code?: string })?.code !== 'ESRCH') {
|
||||||
await managerLogger.warn(`Failed to terminate process ${pid}:`, error)
|
await managerLogger.warn(`Failed to terminate process ${pid}:`, error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -589,8 +589,8 @@ export async function checkAdminPrivileges(): Promise<boolean> {
|
|||||||
await execPromise('chcp 65001 >nul 2>&1 && fltmc', { encoding: 'utf8' })
|
await execPromise('chcp 65001 >nul 2>&1 && fltmc', { encoding: 'utf8' })
|
||||||
await managerLogger.info('Admin privileges confirmed via fltmc')
|
await managerLogger.info('Admin privileges confirmed via fltmc')
|
||||||
return true
|
return true
|
||||||
} catch (fltmcError: any) {
|
} catch (fltmcError: unknown) {
|
||||||
const errorCode = fltmcError?.code || 0
|
const errorCode = (fltmcError as { code?: number })?.code || 0
|
||||||
await managerLogger.debug(`fltmc failed with code ${errorCode}, trying net session as fallback`)
|
await managerLogger.debug(`fltmc failed with code ${errorCode}, trying net session as fallback`)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -598,8 +598,8 @@ export async function checkAdminPrivileges(): Promise<boolean> {
|
|||||||
await execPromise('chcp 65001 >nul 2>&1 && net session', { encoding: 'utf8' })
|
await execPromise('chcp 65001 >nul 2>&1 && net session', { encoding: 'utf8' })
|
||||||
await managerLogger.info('Admin privileges confirmed via net session')
|
await managerLogger.info('Admin privileges confirmed via net session')
|
||||||
return true
|
return true
|
||||||
} catch (netSessionError: any) {
|
} catch (netSessionError: unknown) {
|
||||||
const netErrorCode = netSessionError?.code || 0
|
const netErrorCode = (netSessionError as { code?: number })?.code || 0
|
||||||
await managerLogger.debug(
|
await managerLogger.debug(
|
||||||
`Both fltmc and net session failed, no admin privileges. Error codes: fltmc=${errorCode}, net=${netErrorCode}`
|
`Both fltmc and net session failed, no admin privileges. Error codes: fltmc=${errorCode}, net=${netErrorCode}`
|
||||||
)
|
)
|
||||||
@ -618,7 +618,8 @@ export async function showTunPermissionDialog(): Promise<boolean> {
|
|||||||
|
|
||||||
const title = i18next.t('tun.permissions.title') || '需要管理员权限'
|
const title = i18next.t('tun.permissions.title') || '需要管理员权限'
|
||||||
const message =
|
const message =
|
||||||
i18next.t('tun.permissions.message') || '启用TUN模式需要管理员权限,是否现在重启应用获取权限?'
|
i18next.t('tun.permissions.message') ||
|
||||||
|
'启用 TUN 模式需要管理员权限,是否现在重启应用获取权限?'
|
||||||
const confirmText = i18next.t('common.confirm') || '确认'
|
const confirmText = i18next.t('common.confirm') || '确认'
|
||||||
const cancelText = i18next.t('common.cancel') || '取消'
|
const cancelText = i18next.t('common.cancel') || '取消'
|
||||||
|
|
||||||
@ -834,7 +835,9 @@ async function checkHighPrivilegeMihomoProcess(): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundProcesses) {
|
if (!foundProcesses) {
|
||||||
|
|||||||
@ -5,13 +5,13 @@ import { getAppConfig } from '../config'
|
|||||||
export async function subStoreSubs(): Promise<ISubStoreSub[]> {
|
export async function subStoreSubs(): Promise<ISubStoreSub[]> {
|
||||||
const { useCustomSubStore = false, customSubStoreUrl = '' } = await getAppConfig()
|
const { useCustomSubStore = false, customSubStoreUrl = '' } = await getAppConfig()
|
||||||
const baseUrl = useCustomSubStore ? customSubStoreUrl : `http://127.0.0.1:${subStorePort}`
|
const baseUrl = useCustomSubStore ? customSubStoreUrl : `http://127.0.0.1:${subStorePort}`
|
||||||
const res = await chromeRequest.get(`${baseUrl}/api/subs`, { responseType: 'json' })
|
const res = await chromeRequest.get<{ data: ISubStoreSub[] }>(`${baseUrl}/api/subs`, { responseType: 'json' })
|
||||||
return res.data.data as ISubStoreSub[]
|
return res.data.data
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function subStoreCollections(): Promise<ISubStoreSub[]> {
|
export async function subStoreCollections(): Promise<ISubStoreSub[]> {
|
||||||
const { useCustomSubStore = false, customSubStoreUrl = '' } = await getAppConfig()
|
const { useCustomSubStore = false, customSubStoreUrl = '' } = await getAppConfig()
|
||||||
const baseUrl = useCustomSubStore ? customSubStoreUrl : `http://127.0.0.1:${subStorePort}`
|
const baseUrl = useCustomSubStore ? customSubStoreUrl : `http://127.0.0.1:${subStorePort}`
|
||||||
const res = await chromeRequest.get(`${baseUrl}/api/collections`, { responseType: 'json' })
|
const res = await chromeRequest.get<{ data: ISubStoreSub[] }>(`${baseUrl}/api/collections`, { responseType: 'json' })
|
||||||
return res.data.data as ISubStoreSub[]
|
return res.data.data
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export async function checkUpdate(): Promise<IAppVersion | undefined> {
|
|||||||
responseType: 'text'
|
responseType: 'text'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
const latest = parse(res.data) as IAppVersion
|
const latest = parse(res.data as string) as IAppVersion
|
||||||
const currentVersion = app.getVersion()
|
const currentVersion = app.getVersion()
|
||||||
if (compareVersions(latest.version, currentVersion) > 0) {
|
if (compareVersions(latest.version, currentVersion) > 0) {
|
||||||
return latest
|
return latest
|
||||||
@ -94,7 +94,7 @@ export async function downloadAndInstallUpdate(version: string): Promise<void> {
|
|||||||
'Content-Type': 'application/octet-stream'
|
'Content-Type': 'application/octet-stream'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
await writeFile(path.join(dataDir(), file), res.data)
|
await writeFile(path.join(dataDir(), file), res.data as string | Buffer)
|
||||||
}
|
}
|
||||||
if (file.endsWith('.exe')) {
|
if (file.endsWith('.exe')) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { floatingWindowLogger } from '../utils/logger'
|
|||||||
|
|
||||||
export let floatingWindow: BrowserWindow | null = null
|
export let floatingWindow: BrowserWindow | null = null
|
||||||
|
|
||||||
function logError(message: string, error?: any): void {
|
function logError(message: string, error?: unknown): void {
|
||||||
floatingWindowLogger.log(`FloatingWindow Error: ${message}`, error).catch(() => {})
|
floatingWindowLogger.log(`FloatingWindow Error: ${message}`, error).catch(() => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -395,7 +395,7 @@ export async function createTray(): Promise<void> {
|
|||||||
image.setTemplateImage(true)
|
image.setTemplateImage(true)
|
||||||
tray?.setImage(image)
|
tray?.setImage(image)
|
||||||
})
|
})
|
||||||
// macOS 默认行为: 左键显示窗口, 右键显示菜单
|
// macOS 默认行为:左键显示窗口,右键显示菜单
|
||||||
tray?.addListener('click', async () => {
|
tray?.addListener('click', async () => {
|
||||||
if (swapTrayClick) {
|
if (swapTrayClick) {
|
||||||
await updateTrayMenu()
|
await updateTrayMenu()
|
||||||
@ -537,7 +537,7 @@ export function updateTrayIconImmediate(sysProxyEnabled: boolean, tunEnabled: bo
|
|||||||
tray.setImage(iconPath)
|
tray.setImage(iconPath)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('更新托盘图标失败:', error)
|
console.error('更新托盘图标失败:', error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -560,6 +560,6 @@ export async function updateTrayIcon(): Promise<void> {
|
|||||||
tray.setImage(iconPath)
|
tray.setImage(iconPath)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('更新托盘图标失败:', error)
|
console.error('更新托盘图标失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { triggerAutoProxy, triggerManualProxy } from '@mihomo-party/sysproxy'
|
|||||||
import { getAppConfig, getControledMihomoConfig } from '../config'
|
import { getAppConfig, getControledMihomoConfig } from '../config'
|
||||||
import { pacPort, startPacServer, stopPacServer } from '../resolve/server'
|
import { pacPort, startPacServer, stopPacServer } from '../resolve/server'
|
||||||
import { promisify } from 'util'
|
import { promisify } from 'util'
|
||||||
import { execFile } from 'child_process'
|
import { exec, execFile } from 'child_process'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { resourcesFilesDir } from '../utils/dirs'
|
import { resourcesFilesDir } from '../utils/dirs'
|
||||||
import { net } from 'electron'
|
import { net } from 'electron'
|
||||||
@ -164,8 +164,6 @@ function isSocketFileExists(): boolean {
|
|||||||
async function requestSocketRecreation(): Promise<void> {
|
async function requestSocketRecreation(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// Send SIGUSR1 signal to helper process to recreate socket
|
// Send SIGUSR1 signal to helper process to recreate socket
|
||||||
const { exec } = require('child_process')
|
|
||||||
const { promisify } = require('util')
|
|
||||||
const execPromise = promisify(exec)
|
const execPromise = promisify(exec)
|
||||||
|
|
||||||
// Use osascript with administrator privileges (same pattern as grantTunPermissions)
|
// Use osascript with administrator privileges (same pattern as grantTunPermissions)
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export interface RequestOptions {
|
|||||||
maxRedirects?: number
|
maxRedirects?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Response<T = any> {
|
export interface Response<T = unknown> {
|
||||||
data: T
|
data: T
|
||||||
status: number
|
status: number
|
||||||
statusText: string
|
statusText: string
|
||||||
@ -29,7 +29,7 @@ export interface Response<T = any> {
|
|||||||
* Make HTTP request using Chromium's network stack (via electron.net)
|
* Make HTTP request using Chromium's network stack (via electron.net)
|
||||||
* This provides better compatibility, HTTP/2 support, and system certificate integration
|
* This provides better compatibility, HTTP/2 support, and system certificate integration
|
||||||
*/
|
*/
|
||||||
export async function request<T = any>(
|
export async function request<T = unknown>(
|
||||||
url: string,
|
url: string,
|
||||||
options: RequestOptions = {}
|
options: RequestOptions = {}
|
||||||
): Promise<Response<T>> {
|
): Promise<Response<T>> {
|
||||||
@ -45,7 +45,7 @@ export async function request<T = any>(
|
|||||||
} = options
|
} = options
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let sessionToUse = session.defaultSession
|
let sessionToUse: Electron.Session | undefined = session.defaultSession
|
||||||
let tempPartition: string | null = null
|
let tempPartition: string | null = null
|
||||||
|
|
||||||
// Set up proxy if specified
|
// Set up proxy if specified
|
||||||
@ -64,7 +64,7 @@ export async function request<T = any>(
|
|||||||
if (tempPartition) {
|
if (tempPartition) {
|
||||||
// Note: Electron doesn't provide session.destroy(), but temporary sessions
|
// Note: Electron doesn't provide session.destroy(), but temporary sessions
|
||||||
// will be garbage collected when no longer referenced
|
// will be garbage collected when no longer referenced
|
||||||
sessionToUse = null as any
|
sessionToUse = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ export async function request<T = any>(
|
|||||||
if (timeoutId) clearTimeout(timeoutId)
|
if (timeoutId) clearTimeout(timeoutId)
|
||||||
|
|
||||||
const buffer = Buffer.concat(chunks)
|
const buffer = Buffer.concat(chunks)
|
||||||
let data: any
|
let data: unknown
|
||||||
|
|
||||||
try {
|
try {
|
||||||
switch (responseType) {
|
switch (responseType) {
|
||||||
@ -141,25 +141,25 @@ export async function request<T = any>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
data,
|
data: data as T,
|
||||||
status: statusCode,
|
status: statusCode,
|
||||||
statusText: statusMessage,
|
statusText: statusMessage,
|
||||||
headers: responseHeaders,
|
headers: responseHeaders,
|
||||||
url: url
|
url: url
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error: unknown) {
|
||||||
reject(new Error(`Failed to parse response: ${error}`))
|
reject(new Error(`Failed to parse response: ${String(error)}`))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
res.on('error', (error) => {
|
res.on('error', (error: unknown) => {
|
||||||
cleanup()
|
cleanup()
|
||||||
if (timeoutId) clearTimeout(timeoutId)
|
if (timeoutId) clearTimeout(timeoutId)
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
req.on('error', (error) => {
|
req.on('error', (error: unknown) => {
|
||||||
cleanup()
|
cleanup()
|
||||||
if (timeoutId) clearTimeout(timeoutId)
|
if (timeoutId) clearTimeout(timeoutId)
|
||||||
reject(error)
|
reject(error)
|
||||||
@ -182,9 +182,9 @@ export async function request<T = any>(
|
|||||||
|
|
||||||
req.end()
|
req.end()
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error: unknown) => {
|
||||||
cleanup()
|
cleanup()
|
||||||
reject(new Error(`Failed to setup proxy: ${error}`))
|
reject(new Error(`Failed to setup proxy: ${String(error)}`))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@ export async function request<T = any>(
|
|||||||
/**
|
/**
|
||||||
* Convenience method for GET requests
|
* Convenience method for GET requests
|
||||||
*/
|
*/
|
||||||
export const get = <T = any>(
|
export const get = <T = unknown>(
|
||||||
url: string,
|
url: string,
|
||||||
options?: Omit<RequestOptions, 'method' | 'body'>
|
options?: Omit<RequestOptions, 'method' | 'body'>
|
||||||
): Promise<Response<T>> => request<T>(url, { ...options, method: 'GET' })
|
): Promise<Response<T>> => request<T>(url, { ...options, method: 'GET' })
|
||||||
@ -200,9 +200,9 @@ export const get = <T = any>(
|
|||||||
/**
|
/**
|
||||||
* Convenience method for POST requests
|
* Convenience method for POST requests
|
||||||
*/
|
*/
|
||||||
export const post = <T = any>(
|
export const post = <T = unknown>(
|
||||||
url: string,
|
url: string,
|
||||||
data: any,
|
data: unknown,
|
||||||
options?: Omit<RequestOptions, 'method' | 'body'>
|
options?: Omit<RequestOptions, 'method' | 'body'>
|
||||||
): Promise<Response<T>> => {
|
): Promise<Response<T>> => {
|
||||||
const body = typeof data === 'string' ? data : JSON.stringify(data)
|
const body = typeof data === 'string' ? data : JSON.stringify(data)
|
||||||
@ -216,9 +216,9 @@ export const post = <T = any>(
|
|||||||
/**
|
/**
|
||||||
* Convenience method for PUT requests
|
* Convenience method for PUT requests
|
||||||
*/
|
*/
|
||||||
export const put = <T = any>(
|
export const put = <T = unknown>(
|
||||||
url: string,
|
url: string,
|
||||||
data: any,
|
data: unknown,
|
||||||
options?: Omit<RequestOptions, 'method' | 'body'>
|
options?: Omit<RequestOptions, 'method' | 'body'>
|
||||||
): Promise<Response<T>> => {
|
): Promise<Response<T>> => {
|
||||||
const body = typeof data === 'string' ? data : JSON.stringify(data)
|
const body = typeof data === 'string' ? data : JSON.stringify(data)
|
||||||
@ -232,7 +232,7 @@ export const put = <T = any>(
|
|||||||
/**
|
/**
|
||||||
* Convenience method for DELETE requests
|
* Convenience method for DELETE requests
|
||||||
*/
|
*/
|
||||||
export const del = <T = any>(
|
export const del = <T = unknown>(
|
||||||
url: string,
|
url: string,
|
||||||
options?: Omit<RequestOptions, 'method' | 'body'>
|
options?: Omit<RequestOptions, 'method' | 'body'>
|
||||||
): Promise<Response<T>> => request<T>(url, { ...options, method: 'DELETE' })
|
): Promise<Response<T>> => request<T>(url, { ...options, method: 'DELETE' })
|
||||||
@ -240,9 +240,9 @@ export const del = <T = any>(
|
|||||||
/**
|
/**
|
||||||
* Convenience method for PATCH requests
|
* Convenience method for PATCH requests
|
||||||
*/
|
*/
|
||||||
export const patch = <T = any>(
|
export const patch = <T = unknown>(
|
||||||
url: string,
|
url: string,
|
||||||
data: any,
|
data: unknown,
|
||||||
options?: Omit<RequestOptions, 'method' | 'body'>
|
options?: Omit<RequestOptions, 'method' | 'body'>
|
||||||
): Promise<Response<T>> => {
|
): Promise<Response<T>> => {
|
||||||
const body = typeof data === 'string' ? data : JSON.stringify(data)
|
const body = typeof data === 'string' ? data : JSON.stringify(data)
|
||||||
|
|||||||
@ -141,7 +141,7 @@ export async function installMihomoCore(version: string): Promise<void> {
|
|||||||
console.log(`[GitHub] Installing mihomo core version ${version}`)
|
console.log(`[GitHub] Installing mihomo core version ${version}`)
|
||||||
|
|
||||||
const plat = platform()
|
const plat = platform()
|
||||||
let arch = process.arch
|
const arch = process.arch
|
||||||
|
|
||||||
// 映射平台和架构到 GitHub Release 文件名
|
// 映射平台和架构到 GitHub Release 文件名
|
||||||
const key = `${plat}-${arch}`
|
const key = `${plat}-${arch}`
|
||||||
|
|||||||
@ -14,13 +14,13 @@ class Logger {
|
|||||||
return new Date().toISOString()
|
return new Date().toISOString()
|
||||||
}
|
}
|
||||||
|
|
||||||
private formatLogMessage(level: LogLevel, message: string, error?: any): string {
|
private formatLogMessage(level: LogLevel, message: string, error?: unknown): string {
|
||||||
const timestamp = this.formatTimestamp()
|
const timestamp = this.formatTimestamp()
|
||||||
const errorStr = error ? `: ${error}` : ''
|
const errorStr = error ? `: ${String(error)}` : ''
|
||||||
return `[${timestamp}] [${level.toUpperCase()}] [${this.moduleName}] ${message}${errorStr}\n`
|
return `[${timestamp}] [${level.toUpperCase()}] [${this.moduleName}] ${message}${errorStr}\n`
|
||||||
}
|
}
|
||||||
|
|
||||||
private async writeToFile(level: LogLevel, message: string, error?: any): Promise<void> {
|
private async writeToFile(level: LogLevel, message: string, error?: unknown): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const appLogPath = logPath()
|
const appLogPath = logPath()
|
||||||
const logMessage = this.formatLogMessage(level, message, error)
|
const logMessage = this.formatLogMessage(level, message, error)
|
||||||
@ -35,7 +35,7 @@ class Logger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private logToConsole(level: LogLevel, message: string, error?: any): void {
|
private logToConsole(level: LogLevel, message: string, error?: unknown): void {
|
||||||
const prefix = `[${this.moduleName}] ${message}`
|
const prefix = `[${this.moduleName}] ${message}`
|
||||||
|
|
||||||
switch (level) {
|
switch (level) {
|
||||||
@ -54,28 +54,28 @@ class Logger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async debug(message: string, error?: any): Promise<void> {
|
async debug(message: string, error?: unknown): Promise<void> {
|
||||||
await this.writeToFile('debug', message, error)
|
await this.writeToFile('debug', message, error)
|
||||||
this.logToConsole('debug', message, error)
|
this.logToConsole('debug', message, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
async info(message: string, error?: any): Promise<void> {
|
async info(message: string, error?: unknown): Promise<void> {
|
||||||
await this.writeToFile('info', message, error)
|
await this.writeToFile('info', message, error)
|
||||||
this.logToConsole('info', message, error)
|
this.logToConsole('info', message, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
async warn(message: string, error?: any): Promise<void> {
|
async warn(message: string, error?: unknown): Promise<void> {
|
||||||
await this.writeToFile('warn', message, error)
|
await this.writeToFile('warn', message, error)
|
||||||
this.logToConsole('warn', message, error)
|
this.logToConsole('warn', message, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
async error(message: string, error?: any): Promise<void> {
|
async error(message: string, error?: unknown): Promise<void> {
|
||||||
await this.writeToFile('error', message, error)
|
await this.writeToFile('error', message, error)
|
||||||
this.logToConsole('error', message, error)
|
this.logToConsole('error', message, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 兼容原有的 logFloatingWindow 函数签名
|
// 兼容原有的 logFloatingWindow 函数签名
|
||||||
async log(message: string, error?: any): Promise<void> {
|
async log(message: string, error?: unknown): Promise<void> {
|
||||||
if (error) {
|
if (error) {
|
||||||
await this.error(message, error)
|
await this.error(message, error)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { GenIcon } from 'react-icons'
|
import { GenIcon, IconBaseProps } from 'react-icons'
|
||||||
|
|
||||||
function MihomoIcon(props: any): React.JSX.Element {
|
function MihomoIcon(props: IconBaseProps): React.JSX.Element {
|
||||||
return GenIcon({
|
return GenIcon({
|
||||||
tag: 'svg',
|
tag: 'svg',
|
||||||
attr: { viewBox: '0 0 58 61.53' },
|
attr: { viewBox: '0 0 58 61.53' },
|
||||||
|
|||||||
@ -332,7 +332,7 @@ const ConnectionTable: React.FC<Props> = ({
|
|||||||
const handleSort = useCallback(
|
const handleSort = useCallback(
|
||||||
(columnKey: string) => {
|
(columnKey: string) => {
|
||||||
let newDirection: 'asc' | 'desc' = 'asc'
|
let newDirection: 'asc' | 'desc' = 'asc'
|
||||||
let newColumn = columnKey
|
const newColumn = columnKey
|
||||||
|
|
||||||
if (sortColumn === columnKey) {
|
if (sortColumn === columnKey) {
|
||||||
newDirection = sortDirection === 'asc' ? 'desc' : 'asc'
|
newDirection = sortDirection === 'asc' ? 'desc' : 'asc'
|
||||||
|
|||||||
@ -140,7 +140,7 @@ const EditInfoModal: React.FC<Props> = (props) => {
|
|||||||
value={values.interval?.toString() ?? ''}
|
value={values.interval?.toString() ?? ''}
|
||||||
onValueChange={(v) => {
|
onValueChange={(v) => {
|
||||||
// 输入限制
|
// 输入限制
|
||||||
if (/^[\d\s*\-,\/]*$/.test(v)) {
|
if (/^[\d\s*\-,/]*$/.test(v)) {
|
||||||
// 纯数字
|
// 纯数字
|
||||||
if (/^\d+$/.test(v)) {
|
if (/^\d+$/.test(v)) {
|
||||||
setValues({ ...values, interval: parseInt(v, 10) || 0 })
|
setValues({ ...values, interval: parseInt(v, 10) || 0 })
|
||||||
|
|||||||
@ -411,8 +411,7 @@ interface RuleListItemProps {
|
|||||||
onRemove: (index: number) => void
|
onRemove: (index: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const RuleListItem = memo<RuleListItemProps>(
|
const RuleListItemBase: React.FC<RuleListItemProps> = ({
|
||||||
({
|
|
||||||
rule,
|
rule,
|
||||||
originalIndex,
|
originalIndex,
|
||||||
isDeleted,
|
isDeleted,
|
||||||
@ -496,8 +495,9 @@ const RuleListItem = memo<RuleListItemProps>(
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
(prevProps, nextProps) => {
|
|
||||||
|
const RuleListItem = memo(RuleListItemBase, (prevProps, nextProps) => {
|
||||||
return (
|
return (
|
||||||
prevProps.rule === nextProps.rule &&
|
prevProps.rule === nextProps.rule &&
|
||||||
prevProps.originalIndex === nextProps.originalIndex &&
|
prevProps.originalIndex === nextProps.originalIndex &&
|
||||||
@ -505,8 +505,9 @@ const RuleListItem = memo<RuleListItemProps>(
|
|||||||
prevProps.isPrependOrAppend === nextProps.isPrependOrAppend &&
|
prevProps.isPrependOrAppend === nextProps.isPrependOrAppend &&
|
||||||
prevProps.rulesLength === nextProps.rulesLength
|
prevProps.rulesLength === nextProps.rulesLength
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
RuleListItem.displayName = 'RuleListItem'
|
||||||
|
|
||||||
const EditRulesModal: React.FC<Props> = (props) => {
|
const EditRulesModal: React.FC<Props> = (props) => {
|
||||||
const { id, onClose } = props
|
const { id, onClose } = props
|
||||||
@ -563,7 +564,7 @@ const EditRulesModal: React.FC<Props> = (props) => {
|
|||||||
const content = await getProfileStr(id)
|
const content = await getProfileStr(id)
|
||||||
setProfileContent(content)
|
setProfileContent(content)
|
||||||
|
|
||||||
const parsed = yaml.load(content) as any
|
const parsed = yaml.load(content) as Record<string, unknown> | undefined
|
||||||
let initialRules: RuleItem[] = []
|
let initialRules: RuleItem[] = []
|
||||||
|
|
||||||
if (parsed && parsed.rules && Array.isArray(parsed.rules)) {
|
if (parsed && parsed.rules && Array.isArray(parsed.rules)) {
|
||||||
@ -593,11 +594,19 @@ const EditRulesModal: React.FC<Props> = (props) => {
|
|||||||
|
|
||||||
// 添加代理组和代理名称
|
// 添加代理组和代理名称
|
||||||
if (Array.isArray(parsed['proxy-groups'])) {
|
if (Array.isArray(parsed['proxy-groups'])) {
|
||||||
groups.push(...parsed['proxy-groups'].map((group: any) => group?.name).filter(Boolean))
|
groups.push(
|
||||||
|
...((parsed['proxy-groups'] as Array<Record<string, unknown>>)
|
||||||
|
.map((group) => (group && typeof group['name'] === 'string' ? (group['name'] as string) : ''))
|
||||||
|
.filter(Boolean) as string[])
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(parsed['proxies'])) {
|
if (Array.isArray(parsed['proxies'])) {
|
||||||
groups.push(...parsed['proxies'].map((proxy: any) => proxy?.name).filter(Boolean))
|
groups.push(
|
||||||
|
...((parsed['proxies'] as Array<Record<string, unknown>>)
|
||||||
|
.map((proxy) => (proxy && typeof proxy['name'] === 'string' ? (proxy['name'] as string) : ''))
|
||||||
|
.filter(Boolean) as string[])
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预置出站 https://wiki.metacubex.one/config/proxies/built-in/
|
// 预置出站 https://wiki.metacubex.one/config/proxies/built-in/
|
||||||
@ -710,7 +719,7 @@ const EditRulesModal: React.FC<Props> = (props) => {
|
|||||||
}
|
}
|
||||||
} catch (ruleError) {
|
} catch (ruleError) {
|
||||||
// 规则文件读取失败
|
// 规则文件读取失败
|
||||||
console.debug('规则文件读取失败:', ruleError)
|
console.debug('规则文件读取失败:', ruleError)
|
||||||
setRules(initialRules)
|
setRules(initialRules)
|
||||||
// 清空规则标记
|
// 清空规则标记
|
||||||
setPrependRules(new Set())
|
setPrependRules(new Set())
|
||||||
|
|||||||
@ -22,8 +22,7 @@ function delayColor(delay: number): 'primary' | 'success' | 'warning' | 'danger'
|
|||||||
return 'warning'
|
return 'warning'
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProxyItem: React.FC<Props> = React.memo(
|
const ProxyItemBase: React.FC<Props> = (props) => {
|
||||||
(props) => {
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const {
|
const {
|
||||||
mutateProxies,
|
mutateProxies,
|
||||||
@ -61,10 +60,7 @@ const ProxyItem: React.FC<Props> = React.memo(
|
|||||||
})
|
})
|
||||||
}, [proxy.name, group.testUrl, onProxyDelay, mutateProxies])
|
}, [proxy.name, group.testUrl, onProxyDelay, mutateProxies])
|
||||||
|
|
||||||
const fixed = useMemo(
|
const fixed = useMemo(() => group.fixed && group.fixed === proxy.name, [group.fixed, proxy.name])
|
||||||
() => group.fixed && group.fixed === proxy.name,
|
|
||||||
[group.fixed, proxy.name]
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
@ -177,8 +173,9 @@ const ProxyItem: React.FC<Props> = React.memo(
|
|||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
(prevProps, nextProps) => {
|
|
||||||
|
const ProxyItem = React.memo(ProxyItemBase, (prevProps, nextProps) => {
|
||||||
// 必要时重新渲染
|
// 必要时重新渲染
|
||||||
return (
|
return (
|
||||||
prevProps.proxy.name === nextProps.proxy.name &&
|
prevProps.proxy.name === nextProps.proxy.name &&
|
||||||
@ -188,8 +185,7 @@ const ProxyItem: React.FC<Props> = React.memo(
|
|||||||
prevProps.group.fixed === nextProps.group.fixed &&
|
prevProps.group.fixed === nextProps.group.fixed &&
|
||||||
prevProps.isGroupTesting === nextProps.isGroupTesting
|
prevProps.isGroupTesting === nextProps.isGroupTesting
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
ProxyItem.displayName = 'ProxyItem'
|
ProxyItem.displayName = 'ProxyItem'
|
||||||
|
|
||||||
|
|||||||
@ -208,7 +208,7 @@ const GeneralConfig: React.FC = () => {
|
|||||||
type="number"
|
type="number"
|
||||||
value={autoQuitWithoutCoreDelay.toString()}
|
value={autoQuitWithoutCoreDelay.toString()}
|
||||||
onValueChange={async (v: string) => {
|
onValueChange={async (v: string) => {
|
||||||
let num = parseInt(v)
|
const num = parseInt(v)
|
||||||
await patchAppConfig({ autoQuitWithoutCoreDelay: num })
|
await patchAppConfig({ autoQuitWithoutCoreDelay: num })
|
||||||
}}
|
}}
|
||||||
onBlur={async (e) => {
|
onBlur={async (e) => {
|
||||||
|
|||||||
@ -59,7 +59,7 @@ const MihomoConfig: React.FC = () => {
|
|||||||
type="number"
|
type="number"
|
||||||
value={(subscriptionTimeout / 1000)?.toString()}
|
value={(subscriptionTimeout / 1000)?.toString()}
|
||||||
onValueChange={async (v: string) => {
|
onValueChange={async (v: string) => {
|
||||||
let num = parseInt(v)
|
const num = parseInt(v)
|
||||||
await patchAppConfig({ subscriptionTimeout: num * 1000 })
|
await patchAppConfig({ subscriptionTimeout: num * 1000 })
|
||||||
}}
|
}}
|
||||||
onBlur={async (e) => {
|
onBlur={async (e) => {
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import React, { createContext, ReactNode, useContext } from 'react'
|
import React, { createContext, ReactNode, useContext } from 'react'
|
||||||
import { showError } from '@renderer/utils/error-display'
|
import { showError } from '@renderer/utils/error-display'
|
||||||
import { toast } from '@renderer/components/base/toast'
|
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
import {
|
import {
|
||||||
addProfileItem as add,
|
addProfileItem as add,
|
||||||
@ -104,7 +103,7 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child
|
|||||||
// 异步执行后台切换,不阻塞 UI
|
// 异步执行后台切换,不阻塞 UI
|
||||||
await pendingTask.current
|
await pendingTask.current
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const errorMsg = (e as any)?.message || String(e)
|
const errorMsg = (e as { message?: string })?.message || String(e)
|
||||||
// 处理 IPC 超时错误
|
// 处理 IPC 超时错误
|
||||||
if (errorMsg.includes('reply was never sent')) {
|
if (errorMsg.includes('reply was never sent')) {
|
||||||
setTimeout(() => mutateProfileConfig(), 1000)
|
setTimeout(() => mutateProfileConfig(), 1000)
|
||||||
|
|||||||
@ -363,7 +363,7 @@
|
|||||||
"sysproxy.pacEditor.title": "编辑 PAC 脚本",
|
"sysproxy.pacEditor.title": "编辑 PAC 脚本",
|
||||||
"sysproxy.bypass.title": "代理绕过",
|
"sysproxy.bypass.title": "代理绕过",
|
||||||
"sysproxy.bypass.addDefault": "添加默认代理绕过",
|
"sysproxy.bypass.addDefault": "添加默认代理绕过",
|
||||||
"sysproxy.bypass.placeholder": "例: *.baidu.com",
|
"sysproxy.bypass.placeholder": "例:*.baidu.com",
|
||||||
"tun.title": "虚拟网卡",
|
"tun.title": "虚拟网卡",
|
||||||
"tun.firewall.title": "重设防火墙",
|
"tun.firewall.title": "重设防火墙",
|
||||||
"tun.firewall.reset": "重设防火墙",
|
"tun.firewall.reset": "重设防火墙",
|
||||||
@ -378,7 +378,7 @@
|
|||||||
"tun.autoDetectInterface": "自动选择流量出口接口",
|
"tun.autoDetectInterface": "自动选择流量出口接口",
|
||||||
"tun.dnsHijack": "DNS 劫持",
|
"tun.dnsHijack": "DNS 劫持",
|
||||||
"tun.excludeAddress.title": "排除自定义网段",
|
"tun.excludeAddress.title": "排除自定义网段",
|
||||||
"tun.excludeAddress.placeholder": "例: 172.20.0.0/16",
|
"tun.excludeAddress.placeholder": "例:172.20.0.0/16",
|
||||||
"tun.notifications.coreAuthSuccess": "内核授权成功",
|
"tun.notifications.coreAuthSuccess": "内核授权成功",
|
||||||
"tun.notifications.firewallResetSuccess": "防火墙重设成功",
|
"tun.notifications.firewallResetSuccess": "防火墙重设成功",
|
||||||
"tun.permissions.title": "需要管理员权限",
|
"tun.permissions.title": "需要管理员权限",
|
||||||
|
|||||||
@ -363,7 +363,7 @@
|
|||||||
"sysproxy.pacEditor.title": "編輯 PAC 腳本",
|
"sysproxy.pacEditor.title": "編輯 PAC 腳本",
|
||||||
"sysproxy.bypass.title": "代理繞過",
|
"sysproxy.bypass.title": "代理繞過",
|
||||||
"sysproxy.bypass.addDefault": "添加默認代理繞過",
|
"sysproxy.bypass.addDefault": "添加默認代理繞過",
|
||||||
"sysproxy.bypass.placeholder": "例: *.baidu.com",
|
"sysproxy.bypass.placeholder": "例:*.baidu.com",
|
||||||
"tun.title": "虛擬網卡",
|
"tun.title": "虛擬網卡",
|
||||||
"tun.firewall.title": "重設防火牆",
|
"tun.firewall.title": "重設防火牆",
|
||||||
"tun.firewall.reset": "重設防火牆",
|
"tun.firewall.reset": "重設防火牆",
|
||||||
@ -378,7 +378,7 @@
|
|||||||
"tun.autoDetectInterface": "自動選擇流量出口接口",
|
"tun.autoDetectInterface": "自動選擇流量出口接口",
|
||||||
"tun.dnsHijack": "DNS 劫持",
|
"tun.dnsHijack": "DNS 劫持",
|
||||||
"tun.excludeAddress.title": "排除自定義網段",
|
"tun.excludeAddress.title": "排除自定義網段",
|
||||||
"tun.excludeAddress.placeholder": "例: 172.20.0.0/16",
|
"tun.excludeAddress.placeholder": "例:172.20.0.0/16",
|
||||||
"tun.notifications.coreAuthSuccess": "內核授權成功",
|
"tun.notifications.coreAuthSuccess": "內核授權成功",
|
||||||
"tun.notifications.firewallResetSuccess": "防火牆重設成功",
|
"tun.notifications.firewallResetSuccess": "防火牆重設成功",
|
||||||
"tun.permissions.title": "需要系統管理員權限",
|
"tun.permissions.title": "需要系統管理員權限",
|
||||||
|
|||||||
@ -314,7 +314,7 @@ const Mihomo: React.FC = () => {
|
|||||||
await restartCore()
|
await restartCore()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleConfigChangeWithRestart = async (key: string, value: any) => {
|
const handleConfigChangeWithRestart = async (key: string, value: unknown) => {
|
||||||
try {
|
try {
|
||||||
await patchAppConfig({ [key]: value })
|
await patchAppConfig({ [key]: value })
|
||||||
await restartCore()
|
await restartCore()
|
||||||
@ -334,8 +334,8 @@ const Mihomo: React.FC = () => {
|
|||||||
try {
|
try {
|
||||||
const data = await fetchMihomoTags(forceRefresh)
|
const data = await fetchMihomoTags(forceRefresh)
|
||||||
setTags(Array.isArray(data) ? data : [])
|
setTags(Array.isArray(data) ? data : [])
|
||||||
} catch (error) {
|
} catch (error: unknown) {
|
||||||
console.error('Failed to fetch tags:', error)
|
console.error('Failed to fetch tags:', String(error))
|
||||||
setTags([])
|
setTags([])
|
||||||
toast.error(t('mihomo.error.fetchTagsFailed'))
|
toast.error(t('mihomo.error.fetchTagsFailed'))
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
|
|
||||||
import { getPlatform, getVersion } from './ipc'
|
import { getPlatform, getVersion } from './ipc'
|
||||||
// const originError = console.error
|
// const originError = console.error
|
||||||
// const originWarn = console.warn
|
// const originWarn = console.warn
|
||||||
|
|||||||
@ -11,10 +11,10 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"baseUrl": ".",
|
"moduleResolution": "bundler",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@renderer/*": [
|
"@renderer/*": [
|
||||||
"src/renderer/src/*"
|
"./src/renderer/src/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user