mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 05:00:30 +08:00
Compare commits
5 Commits
4dbf054334
...
e35fa316fc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e35fa316fc | ||
|
|
4bea1b93cc | ||
|
|
7089b3ca5b | ||
|
|
add4196dc5 | ||
|
|
78ec7f9822 |
@ -17,7 +17,7 @@
|
||||
<img width='90%' src="./images/preview.jpg">
|
||||
</div>
|
||||
|
||||
### 本项目由“[狗狗加速](https://party.dginv.click/#/register?code=ARdo0mXx)”赞助
|
||||
### 本项目认证稳定机场推荐:“[狗狗加速](https://party.dginv.click/#/register?code=ARdo0mXx)”
|
||||
##### [狗狗加速 —— 技术流机场 Doggygo VPN](https://party.dginv.click/#/register?code=ARdo0mXx)
|
||||
|
||||
- 高性能海外机场,稳定首选,海外团队,无跑路风险
|
||||
@ -30,10 +30,11 @@
|
||||
|
||||
### 特性
|
||||
|
||||
- [x] 一键 Smart Core 规则覆写,基于 AI 模型自动选择最优节点 详细介绍请看 [这里](https://mihomo.party/docs/guide/smart-core)
|
||||
- [x] 开箱即用,无需服务模式的 Tun
|
||||
- [x] 多种配色主题可选,UI 焕然一新
|
||||
- [x] 支持大部分 Mihomo 常用配置修改
|
||||
- [x] 内置稳定版和预览版 Mihomo 内核
|
||||
- [x] 支持大部分 Mihomo(Clash Meta) 常用配置修改
|
||||
- [x] 内置 Smart内核 与 Mihomo(Clash Meta) 内核
|
||||
- [x] 通过 WebDAV 一键备份和恢复配置
|
||||
- [x] 强大的覆写功能,任意修订配置文件
|
||||
- [x] 深度集成 Sub-Store,轻松管理订阅
|
||||
|
||||
16
changelog.md
16
changelog.md
@ -1,6 +1,9 @@
|
||||
## 1.8.5
|
||||
|
||||
**本次更新增加了大家期待已久的托盘图标根据代理状态实时变化颜色,系统代理为蓝色,虚拟网卡为绿色,双开为红色;完善 Smart 规则写,当原有规则中有 url-test 和 load-balance 组时,自动替换为 Smart 规则组;当没有 url-test 和 load-balance 时,增加 全局 Smart 规则组,接管全部流量**
|
||||
**🎉 本次更新增加了大家期待已久的托盘图标根据代理状态变化颜色,系统代理为蓝色,虚拟网卡为绿色,双开为红色
|
||||
⚡ 完善 Smart 规则写,当原有规则中有 url-test 和 load-balance 组时,自动替换为 Smart 规则组;当没有 url-test 和 load-balance 时,增加 全局 Smart 规则组,接管全部流量**
|
||||
|
||||
#### 新增 Smart Core 详细文档: [点击查看](https://mihomo.party/docs/guide/smart-core)
|
||||
|
||||
### 新功能 (Feat)
|
||||
- 支持 cron 表达式以自定义订阅更新频率(#766)
|
||||
@ -44,13 +47,4 @@
|
||||
|
||||
### 修复 (Fix)
|
||||
- 修复 DNS/嗅探覆写开关逻辑,修改设置不再会直接写入运行时配置,增加了“仅保存”按钮
|
||||
- 悬浮窗改为纯矩形,修复 windows 下兼容性问题带来的白边
|
||||
|
||||
## 1.8.2
|
||||
|
||||
**本次更新主要集中在重大内核更新和依赖升级后所产生的 bug 修复,解决了自1.7版以后首次安装无法启动的问题,推荐更新**
|
||||
|
||||
### 新功能 (Feat)
|
||||
- 重构 域名嗅探 卡片模块,改为“覆写”逻辑,当开关打开后,使用 嗅探覆写 设置中的配置覆盖订阅原始配置,关闭开关恢复订阅原始配置
|
||||
- 订阅/覆写卡片可右键呼出菜单
|
||||
- MacOS 下“轻触(tap)”触控板可进行开关操作(之前必须“按下(click)”)
|
||||
- 悬浮窗改为纯矩形,修复 windows 下兼容性问题带来的白边
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mihomo-party",
|
||||
"version": "1.8.5-dev",
|
||||
"version": "1.8.5",
|
||||
"description": "Mihomo Party",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "mihomo-party-org",
|
||||
|
||||
@ -375,9 +375,7 @@ export const TunStatus = async (): Promise<boolean> => {
|
||||
return config?.tun?.enable === true
|
||||
}
|
||||
|
||||
export async function getTrayIconStatus(): Promise<'white' | 'blue' | 'green' | 'red'> {
|
||||
const [sysProxyEnabled, tunEnabled] = await Promise.all([SysProxyStatus(), TunStatus()])
|
||||
|
||||
export function calculateTrayIconStatus(sysProxyEnabled: boolean, tunEnabled: boolean): 'white' | 'blue' | 'green' | 'red' {
|
||||
if (sysProxyEnabled && tunEnabled) {
|
||||
return 'red' // 系统代理 + TUN 同时启用(警告状态)
|
||||
} else if (sysProxyEnabled) {
|
||||
@ -387,4 +385,9 @@ export async function getTrayIconStatus(): Promise<'white' | 'blue' | 'green' |
|
||||
} else {
|
||||
return 'white' // 全关
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTrayIconStatus(): Promise<'white' | 'blue' | 'green' | 'red'> {
|
||||
const [sysProxyEnabled, tunEnabled] = await Promise.all([SysProxyStatus(), TunStatus()])
|
||||
return calculateTrayIconStatus(sysProxyEnabled, tunEnabled)
|
||||
}
|
||||
@ -9,6 +9,8 @@ import { existsSync } from 'fs'
|
||||
import os from 'os'
|
||||
import { exec, execSync, spawn } from 'child_process'
|
||||
import { promisify } from 'util'
|
||||
import { appLogger } from '../utils/logger'
|
||||
import { checkAdminPrivileges } from '../core/manager'
|
||||
|
||||
export async function checkUpdate(): Promise<IAppVersion | undefined> {
|
||||
const { 'mixed-port': mixedPort = 7890 } = await getControledMihomoConfig()
|
||||
@ -95,10 +97,45 @@ export async function downloadAndInstallUpdate(version: string): Promise<void> {
|
||||
await writeFile(path.join(dataDir(), file), res.data)
|
||||
}
|
||||
if (file.endsWith('.exe')) {
|
||||
spawn(path.join(dataDir(), file), ['/S', '--force-run'], {
|
||||
detached: true,
|
||||
stdio: 'ignore'
|
||||
}).unref()
|
||||
try {
|
||||
const installerPath = path.join(dataDir(), file)
|
||||
const isAdmin = await checkAdminPrivileges()
|
||||
|
||||
if (isAdmin) {
|
||||
await appLogger.info('Running installer with existing admin privileges')
|
||||
spawn(installerPath, ['/S', '--force-run'], {
|
||||
detached: true,
|
||||
stdio: 'ignore'
|
||||
}).unref()
|
||||
} else {
|
||||
// 提升权限安装
|
||||
const escapedPath = installerPath.replace(/'/g, "''")
|
||||
const args = ['/S', '--force-run']
|
||||
const argsString = args.map(arg => arg.replace(/'/g, "''")).join("', '")
|
||||
|
||||
const command = `powershell -Command "Start-Process -FilePath '${escapedPath}' -ArgumentList '${argsString}' -Verb RunAs -WindowStyle Hidden"`
|
||||
|
||||
await appLogger.info('Starting installer with elevated privileges')
|
||||
|
||||
const execPromise = promisify(exec)
|
||||
await execPromise(command, { windowsHide: true })
|
||||
|
||||
await appLogger.info('Installer started successfully with elevation')
|
||||
}
|
||||
} catch (installerError) {
|
||||
await appLogger.error('Failed to start installer, trying fallback', installerError)
|
||||
|
||||
// Fallback: 尝试使用shell.openPath打开安装包
|
||||
try {
|
||||
await shell.openPath(path.join(dataDir(), file))
|
||||
await appLogger.info('Opened installer with shell.openPath as fallback')
|
||||
} catch (fallbackError) {
|
||||
await appLogger.error('Fallback method also failed', fallbackError)
|
||||
const installerErrorMessage = installerError instanceof Error ? installerError.message : String(installerError)
|
||||
const fallbackErrorMessage = fallbackError instanceof Error ? fallbackError.message : String(fallbackError)
|
||||
throw new Error(`Failed to execute installer: ${installerErrorMessage}. Fallback also failed: ${fallbackErrorMessage}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (file.endsWith('.7z')) {
|
||||
await copyFile(path.join(resourcesFilesDir(), '7za.exe'), path.join(dataDir(), '7za.exe'))
|
||||
|
||||
@ -15,7 +15,7 @@ import pngIconBlue from '../../../resources/icon_blue.png?asset'
|
||||
import pngIconRed from '../../../resources/icon_red.png?asset'
|
||||
import pngIconGreen from '../../../resources/icon_green.png?asset'
|
||||
import templateIcon from '../../../resources/iconTemplate.png?asset'
|
||||
import { mihomoChangeProxy, mihomoCloseAllConnections, mihomoGroups, patchMihomoConfig, getTrayIconStatus } from '../core/mihomoApi'
|
||||
import { mihomoChangeProxy, mihomoCloseAllConnections, mihomoGroups, patchMihomoConfig, getTrayIconStatus, calculateTrayIconStatus } from '../core/mihomoApi'
|
||||
import { mainWindow, showMainWindow, triggerMainWindow } from '..'
|
||||
import { app, clipboard, ipcMain, Menu, nativeImage, shell, Tray } from 'electron'
|
||||
import { dataDir, logDir, mihomoCoreDir, mihomoWorkDir } from '../utils/dirs'
|
||||
@ -458,6 +458,27 @@ const getIconPaths = () => {
|
||||
}
|
||||
}
|
||||
|
||||
export function updateTrayIconImmediate(sysProxyEnabled: boolean, tunEnabled: boolean): void {
|
||||
if (!tray) return
|
||||
|
||||
const status = calculateTrayIconStatus(sysProxyEnabled, tunEnabled)
|
||||
const iconPaths = getIconPaths()
|
||||
const iconPath = iconPaths[status]
|
||||
|
||||
try {
|
||||
if (process.platform === 'darwin') {
|
||||
const icon = nativeImage.createFromPath(iconPath).resize({ height: 16 })
|
||||
tray.setImage(icon)
|
||||
} else if (process.platform === 'win32') {
|
||||
tray.setImage(iconPath)
|
||||
} else if (process.platform === 'linux') {
|
||||
tray.setImage(iconPath)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新托盘图标失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateTrayIcon(): Promise<void> {
|
||||
if (!tray) return
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ import {
|
||||
defaultProfileConfig
|
||||
} from './template'
|
||||
import yaml from 'yaml'
|
||||
import { mkdir, writeFile, rm, readdir, cp, stat } from 'fs/promises'
|
||||
import { mkdir, writeFile, rm, readdir, cp, stat, rename } from 'fs/promises'
|
||||
import { existsSync } from 'fs'
|
||||
import { exec } from 'child_process'
|
||||
import { promisify } from 'util'
|
||||
@ -218,6 +218,19 @@ async function cleanup(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
async function migrateSubStoreFiles(): Promise<void> {
|
||||
const oldJsPath = path.join(mihomoWorkDir(), 'sub-store.bundle.js')
|
||||
const newCjsPath = path.join(mihomoWorkDir(), 'sub-store.bundle.cjs')
|
||||
|
||||
if (existsSync(oldJsPath) && !existsSync(newCjsPath)) {
|
||||
try {
|
||||
await rename(oldJsPath, newCjsPath)
|
||||
} catch (error) {
|
||||
await initLogger.error('Failed to rename sub-store.bundle.js to sub-store.bundle.cjs', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function migration(): Promise<void> {
|
||||
const {
|
||||
siderOrder = [
|
||||
@ -334,6 +347,7 @@ export async function initBasic(): Promise<void> {
|
||||
await initDirs()
|
||||
await initConfig()
|
||||
await migration()
|
||||
await migrateSubStoreFiles()
|
||||
await initFiles()
|
||||
await cleanup()
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ import {
|
||||
import { getRuntimeConfig, getRuntimeConfigStr } from '../core/factory'
|
||||
import { listWebdavBackups, webdavBackup, webdavDelete, webdavRestore } from '../resolve/backup'
|
||||
import { getInterfaces } from '../sys/interface'
|
||||
import { closeTrayIcon, copyEnv, showTrayIcon, updateTrayIcon } from '../resolve/tray'
|
||||
import { closeTrayIcon, copyEnv, showTrayIcon, updateTrayIcon, updateTrayIconImmediate } from '../resolve/tray'
|
||||
import { registerShortcut } from '../resolve/shortcut'
|
||||
import { closeMainWindow, mainWindow, showMainWindow, triggerMainWindow } from '..'
|
||||
import {
|
||||
@ -260,6 +260,9 @@ export function registerIpcMainHandlers(): void {
|
||||
ipcMain.handle('showTrayIcon', () => ipcErrorWrapper(showTrayIcon)())
|
||||
ipcMain.handle('closeTrayIcon', () => ipcErrorWrapper(closeTrayIcon)())
|
||||
ipcMain.handle('updateTrayIcon', () => ipcErrorWrapper(updateTrayIcon)())
|
||||
ipcMain.handle('updateTrayIconImmediate', (_e, sysProxyEnabled, tunEnabled) => {
|
||||
updateTrayIconImmediate(sysProxyEnabled, tunEnabled)
|
||||
})
|
||||
ipcMain.handle('showMainWindow', showMainWindow)
|
||||
ipcMain.handle('closeMainWindow', closeMainWindow)
|
||||
ipcMain.handle('triggerMainWindow', triggerMainWindow)
|
||||
|
||||
@ -2,7 +2,8 @@ import { Button, Card, CardBody, CardFooter, Tooltip } from '@heroui/react'
|
||||
import BorderSwitch from '@renderer/components/base/border-swtich'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import { useAppConfig } from '@renderer/hooks/use-app-config'
|
||||
import { triggerSysProxy, updateTrayIcon } from '@renderer/utils/ipc'
|
||||
import { triggerSysProxy, updateTrayIcon, updateTrayIconImmediate } from '@renderer/utils/ipc'
|
||||
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
|
||||
import { AiOutlineGlobal } from 'react-icons/ai'
|
||||
import React from 'react'
|
||||
import { useSortable } from '@dnd-kit/sortable'
|
||||
@ -20,7 +21,9 @@ const SysproxySwitcher: React.FC<Props> = (props) => {
|
||||
const navigate = useNavigate()
|
||||
const match = location.pathname.includes('/sysproxy')
|
||||
const { appConfig, patchAppConfig } = useAppConfig()
|
||||
const { controledMihomoConfig } = useControledMihomoConfig()
|
||||
const { sysProxy, sysproxyCardStatus = 'col-span-1' } = appConfig || {}
|
||||
const { tun } = controledMihomoConfig || {}
|
||||
const { enable } = sysProxy || {}
|
||||
const {
|
||||
attributes,
|
||||
@ -35,8 +38,11 @@ const SysproxySwitcher: React.FC<Props> = (props) => {
|
||||
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
|
||||
const onChange = async (enable: boolean): Promise<void> => {
|
||||
const previousState = !enable
|
||||
const tunEnabled = tun?.enable ?? false
|
||||
|
||||
// 立即更新图标
|
||||
updateTrayIconImmediate(enable, tunEnabled)
|
||||
|
||||
// 立即更新UI
|
||||
try {
|
||||
await patchAppConfig({ sysProxy: { enable } })
|
||||
await triggerSysProxy(enable)
|
||||
@ -46,6 +52,8 @@ const SysproxySwitcher: React.FC<Props> = (props) => {
|
||||
await updateTrayIcon()
|
||||
} catch (e) {
|
||||
await patchAppConfig({ sysProxy: { enable: previousState } })
|
||||
// 回滚图标
|
||||
updateTrayIconImmediate(previousState, tunEnabled)
|
||||
alert(e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-c
|
||||
import BorderSwitch from '@renderer/components/base/border-swtich'
|
||||
import { TbDeviceIpadHorizontalBolt } from 'react-icons/tb'
|
||||
import { useLocation, useNavigate } from 'react-router-dom'
|
||||
import { restartCore, updateTrayIcon } from '@renderer/utils/ipc'
|
||||
import { restartCore, updateTrayIcon, updateTrayIconImmediate } from '@renderer/utils/ipc'
|
||||
import { useSortable } from '@dnd-kit/sortable'
|
||||
import { CSS } from '@dnd-kit/utilities'
|
||||
import React from 'react'
|
||||
@ -22,6 +22,7 @@ const TunSwitcher: React.FC<Props> = (props) => {
|
||||
const match = location.pathname.includes('/tun') || false
|
||||
const { appConfig } = useAppConfig()
|
||||
const { tunCardStatus = 'col-span-1' } = appConfig || {}
|
||||
const sysProxyEnabled = appConfig?.sysProxy?.enable ?? false
|
||||
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
|
||||
const { tun } = controledMihomoConfig || {}
|
||||
const { enable } = tun || {}
|
||||
@ -37,6 +38,7 @@ const TunSwitcher: React.FC<Props> = (props) => {
|
||||
})
|
||||
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
|
||||
const onChange = async (enable: boolean): Promise<void> => {
|
||||
updateTrayIconImmediate(sysProxyEnabled, enable)
|
||||
if (enable) {
|
||||
try {
|
||||
// 检查内核权限
|
||||
@ -54,9 +56,11 @@ const TunSwitcher: React.FC<Props> = (props) => {
|
||||
} catch (error) {
|
||||
console.error('Failed to restart as admin:', error)
|
||||
await window.electron.ipcRenderer.invoke('showErrorDialog', t('tun.permissions.failed'), String(error))
|
||||
updateTrayIconImmediate(sysProxyEnabled, false)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
updateTrayIconImmediate(sysProxyEnabled, false)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@ -66,6 +70,7 @@ const TunSwitcher: React.FC<Props> = (props) => {
|
||||
} catch (error) {
|
||||
console.warn('Permission grant failed:', error)
|
||||
await window.electron.ipcRenderer.invoke('showErrorDialog', t('tun.permissions.failed'), String(error))
|
||||
updateTrayIconImmediate(sysProxyEnabled, false)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,17 +55,18 @@ const UpdaterModal: React.FC<Props> = (props) => {
|
||||
</Button>
|
||||
</ModalHeader>
|
||||
<ModalBody className="h-full">
|
||||
<ReactMarkdown
|
||||
className="markdown-body select-text"
|
||||
components={{
|
||||
a: ({ ...props }) => <a target="_blank" className="text-primary" {...props} />,
|
||||
code: ({ children }) => <Code size="sm">{children}</Code>,
|
||||
h3: ({ ...props }) => <h3 className="text-lg font-bold" {...props} />,
|
||||
li: ({ children }) => <li className="list-disc list-inside">{children}</li>
|
||||
}}
|
||||
>
|
||||
{changelog}
|
||||
</ReactMarkdown>
|
||||
<div className="markdown-body select-text">
|
||||
<ReactMarkdown
|
||||
components={{
|
||||
a: ({ ...props }) => <a target="_blank" className="text-primary" {...props} />,
|
||||
code: ({ children }) => <Code size="sm">{children}</Code>,
|
||||
h3: ({ ...props }) => <h3 className="text-lg font-bold" {...props} />,
|
||||
li: ({ children }) => <li className="list-disc list-inside">{children}</li>
|
||||
}}
|
||||
>
|
||||
{changelog}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button size="sm" variant="light" onPress={onClose}>
|
||||
|
||||
@ -127,6 +127,8 @@
|
||||
"mihomo.smartCoreStrategy": "Strategy Mode",
|
||||
"mihomo.smartCoreStrategyStickySession": "Sticky Sessions",
|
||||
"mihomo.smartCoreStrategyRoundRobin": "Round Robin",
|
||||
"mihomo.smartCoreUseLightGBMTooltip": "Use pre-trained general model for quick node selection improvement, but may not suit your specific network environment",
|
||||
"mihomo.smartCoreCollectDataTooltip": "Collect your network usage data for training custom models better suited to your network environment (turn off if you don't know how to train models)",
|
||||
"mihomo.mixedPort": "Mixed Port",
|
||||
"mihomo.confirm": "Confirm",
|
||||
"mihomo.socksPort": "Socks Port",
|
||||
|
||||
@ -115,6 +115,17 @@
|
||||
"mihomo.selectCoreVersion": "انتخاب نسخه هسته",
|
||||
"mihomo.stableVersion": "نسخه پایدار",
|
||||
"mihomo.alphaVersion": "نسخه آلفا",
|
||||
"mihomo.smartVersion": "Smart",
|
||||
"mihomo.enableSmartCore": "فعالسازی Smart Core",
|
||||
"mihomo.enableSmartOverride": "استفاده از بازنویسی خودکار Smart",
|
||||
"mihomo.smartOverrideTooltip": "از اسکریپت بازنویسی هوشمند داخلی Party برای جایگزینی url-test و load-balance با گروه قواعد Smart استفاده کنید؛ اگر گروههای قواعد فوق وجود ندارند، تمام گرهها را از اشتراک استخراج کرده و قواعد پیشفرض را جایگزین کنید، برای کاربرانی که نمیخواهند دردسر باشند مناسب است، قابلیت با یک کلیک فعال میشود؛ اگر از حالت جهانی استفاده میکنید، لطفاً گره با نام 'Smart Group' را انتخاب کنید",
|
||||
"mihomo.smartCoreUseLightGBM": "استفاده از LightGBM",
|
||||
"mihomo.smartCoreCollectData": "جمعآوری دادهها",
|
||||
"mihomo.smartCoreStrategy": "حالت استراتژی",
|
||||
"mihomo.smartCoreStrategyStickySession": "نشستهای چسبنده",
|
||||
"mihomo.smartCoreStrategyRoundRobin": "نوبتی دایرهای",
|
||||
"mihomo.smartCoreUseLightGBMTooltip": "از مدل عمومی پیشآموزش دیده برای بهبود سریع انتخاب گره استفاده کنید، اما ممکن است برای محیط شبکه خاص شما مناسب نباشد",
|
||||
"mihomo.smartCoreCollectDataTooltip": "دادههای استفاده شبکه شما را برای آموزش مدلهای سفارشی متناسب با محیط شبکه شما جمعآوری کنید (اگر نمیدانید چگونه مدلها را آموزش دهید، آن را خاموش کنید)",
|
||||
"mihomo.mixedPort": "پورت ترکیبی",
|
||||
"mihomo.confirm": "تایید",
|
||||
"mihomo.socksPort": "پورت Socks",
|
||||
|
||||
@ -115,6 +115,17 @@
|
||||
"mihomo.selectCoreVersion": "Выберите версию ядра",
|
||||
"mihomo.stableVersion": "Стабильная",
|
||||
"mihomo.alphaVersion": "Альфа",
|
||||
"mihomo.smartVersion": "Smart",
|
||||
"mihomo.enableSmartCore": "Включить Smart ядро",
|
||||
"mihomo.enableSmartOverride": "Использовать автоматическое Smart переопределение правил",
|
||||
"mihomo.smartOverrideTooltip": "Использовать встроенный скрипт умного переопределения в Party для замены url-test и load-balance на Smart группы правил; если указанные группы правил отсутствуют, извлечь все узлы из подписки и заменить правила по умолчанию, подходит для пользователей, которые не хотят заморачиваться, функция действует одним кликом; если используется глобальный режим, выберите узел с именем 'Smart Group'",
|
||||
"mihomo.smartCoreUseLightGBM": "Использовать LightGBM",
|
||||
"mihomo.smartCoreCollectData": "Собирать данные",
|
||||
"mihomo.smartCoreStrategy": "Режим стратегии",
|
||||
"mihomo.smartCoreStrategyStickySession": "Липкие сессии",
|
||||
"mihomo.smartCoreStrategyRoundRobin": "Круговой опрос",
|
||||
"mihomo.smartCoreUseLightGBMTooltip": "Использовать предварительно обученную универсальную модель для быстрого улучшения выбора узлов, но может не подходить для вашей специфической сетевой среды",
|
||||
"mihomo.smartCoreCollectDataTooltip": "Собирать данные о вашем сетевом использовании для обучения пользовательских моделей, более подходящих для вашей сетевой среды (отключите, если не знаете, как обучать модели)",
|
||||
"mihomo.mixedPort": "Смешанный порт",
|
||||
"mihomo.confirm": "Подтвердить",
|
||||
"mihomo.socksPort": "Порт Socks",
|
||||
|
||||
@ -127,6 +127,8 @@
|
||||
"mihomo.smartCoreStrategy": "策略模式",
|
||||
"mihomo.smartCoreStrategyStickySession": "粘性会话",
|
||||
"mihomo.smartCoreStrategyRoundRobin": "轮询",
|
||||
"mihomo.smartCoreUseLightGBMTooltip": "使用预训练的通用模型,可快速提升节点选择效果,但可能不适合您的特定网络环境",
|
||||
"mihomo.smartCoreCollectDataTooltip": "收集您的网络使用数据,可用于训练更适合您的网络环境的自定义模型(如果您不懂如何训练模型,请关闭)",
|
||||
"mihomo.mixedPort": "混合端口",
|
||||
"mihomo.confirm": "确认",
|
||||
"mihomo.socksPort": "Socks 端口",
|
||||
|
||||
@ -232,7 +232,18 @@ const Mihomo: React.FC = () => {
|
||||
{enableSmartCore && core === 'mihomo-smart' && (
|
||||
<>
|
||||
<SettingItem
|
||||
title={t('mihomo.smartCoreUseLightGBM')}
|
||||
title={
|
||||
<div className="flex items-center gap-2">
|
||||
<span>{t('mihomo.smartCoreUseLightGBM')}</span>
|
||||
<Tooltip
|
||||
content={t('mihomo.smartCoreUseLightGBMTooltip')}
|
||||
placement="top"
|
||||
className="max-w-xs"
|
||||
>
|
||||
<IoMdInformationCircleOutline className="text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 cursor-help" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
}
|
||||
divider
|
||||
>
|
||||
<Switch
|
||||
@ -247,7 +258,18 @@ const Mihomo: React.FC = () => {
|
||||
</SettingItem>
|
||||
|
||||
<SettingItem
|
||||
title={t('mihomo.smartCoreCollectData')}
|
||||
title={
|
||||
<div className="flex items-center gap-2">
|
||||
<span>{t('mihomo.smartCoreCollectData')}</span>
|
||||
<Tooltip
|
||||
content={t('mihomo.smartCoreCollectDataTooltip')}
|
||||
placement="top"
|
||||
className="max-w-xs"
|
||||
>
|
||||
<IoMdInformationCircleOutline className="text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300 cursor-help" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
}
|
||||
divider
|
||||
>
|
||||
<Switch
|
||||
|
||||
@ -406,6 +406,10 @@ export async function updateTrayIcon(): Promise<void> {
|
||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('updateTrayIcon'))
|
||||
}
|
||||
|
||||
export function updateTrayIconImmediate(sysProxyEnabled: boolean, tunEnabled: boolean): void {
|
||||
window.electron.ipcRenderer.invoke('updateTrayIconImmediate', sysProxyEnabled, tunEnabled)
|
||||
}
|
||||
|
||||
export async function showMainWindow(): Promise<void> {
|
||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('showMainWindow'))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user