mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-26 20:50:30 +08:00
feat: real-time tray icon color updates based on proxy status (#984)
* feat: real-time tray icon color updates based on proxy status * Update changelog.md
This commit is contained in:
parent
e357700d60
commit
a57ea34f1b
@ -3,6 +3,7 @@
|
||||
### 新功能 (Feat)
|
||||
- 支持 cron 表达式以自定义订阅更新频率(#766)
|
||||
- 修复权限检查并优化TUN与自启联动(#977)
|
||||
- 托盘图标能根据代理状态实时变化颜色
|
||||
### 修复 (Fix)
|
||||
- Windows 下当前运行内核权限检测(之前没有正确检测管理员权限运行的内核)
|
||||
- Windows 下 开机自启 按钮卡顿问题 隐藏运行黑框 现在申请权限会弹通知
|
||||
@ -48,4 +49,4 @@
|
||||
### 新功能 (Feat)
|
||||
- 重构 域名嗅探 卡片模块,改为“覆写”逻辑,当开关打开后,使用 嗅探覆写 设置中的配置覆盖订阅原始配置,关闭开关恢复订阅原始配置
|
||||
- 订阅/覆写卡片可右键呼出菜单
|
||||
- MacOS 下“轻触(tap)”触控板可进行开关操作(之前必须“按下(click)”)
|
||||
- MacOS 下“轻触(tap)”触控板可进行开关操作(之前必须“按下(click)”)
|
||||
|
||||
BIN
resources/icon_blue.ico
Normal file
BIN
resources/icon_blue.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
BIN
resources/icon_blue.png
Normal file
BIN
resources/icon_blue.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
BIN
resources/icon_green.ico
Normal file
BIN
resources/icon_green.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
BIN
resources/icon_green.png
Normal file
BIN
resources/icon_green.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
BIN
resources/icon_red.ico
Normal file
BIN
resources/icon_red.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
BIN
resources/icon_red.png
Normal file
BIN
resources/icon_red.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
@ -169,7 +169,9 @@ export const mihomoUpgrade = async (): Promise<void> => {
|
||||
}
|
||||
|
||||
// Smart 内核 API
|
||||
export const mihomoSmartGroupWeights = async (groupName: string): Promise<Record<string, number>> => {
|
||||
export const mihomoSmartGroupWeights = async (
|
||||
groupName: string
|
||||
): Promise<Record<string, number>> => {
|
||||
const instance = await getAxios()
|
||||
return await instance.get(`/group/${encodeURIComponent(groupName)}/weights`)
|
||||
}
|
||||
@ -362,3 +364,27 @@ const mihomoConnections = async (): Promise<void> => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function SysProxyStatus(): Promise<boolean> {
|
||||
const appConfig = await getAppConfig()
|
||||
return appConfig.sysProxy.enable
|
||||
}
|
||||
|
||||
export const TunStatus = async (): Promise<boolean> => {
|
||||
const config = await getControledMihomoConfig()
|
||||
return config?.tun?.enable === true
|
||||
}
|
||||
|
||||
export async function getTrayIconStatus(): Promise<'white' | 'blue' | 'green' | 'red'> {
|
||||
const [sysProxyEnabled, tunEnabled] = await Promise.all([SysProxyStatus(), TunStatus()])
|
||||
|
||||
if (sysProxyEnabled && tunEnabled) {
|
||||
return 'red' // 系统代理 + TUN 同时启用(警告状态)
|
||||
} else if (sysProxyEnabled) {
|
||||
return 'blue' // 仅系统代理启用
|
||||
} else if (tunEnabled) {
|
||||
return 'green' // 仅 TUN 启用
|
||||
} else {
|
||||
return 'white' // 全关
|
||||
}
|
||||
}
|
||||
@ -7,14 +7,14 @@ import {
|
||||
patchControledMihomoConfig
|
||||
} from '../config'
|
||||
import icoIcon from '../../../resources/icon.ico?asset'
|
||||
import icoIconBlue from '../../../resources/icon_blue.ico?asset'
|
||||
import icoIconRed from '../../../resources/icon_red.ico?asset'
|
||||
import icoIconGreen from '../../../resources/icon_green.ico?asset'
|
||||
import pngIcon from '../../../resources/icon.png?asset'
|
||||
import templateIcon from '../../../resources/iconTemplate.png?asset'
|
||||
import {
|
||||
mihomoChangeProxy,
|
||||
mihomoCloseAllConnections,
|
||||
mihomoGroups,
|
||||
patchMihomoConfig
|
||||
} from '../core/mihomoApi'
|
||||
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 { mihomoChangeProxy, mihomoCloseAllConnections, mihomoGroups, patchMihomoConfig, getTrayIconStatus } 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'
|
||||
@ -328,7 +328,8 @@ export async function createTray(): Promise<void> {
|
||||
tray.setContextMenu(menu)
|
||||
}
|
||||
if (process.platform === 'darwin') {
|
||||
const icon = nativeImage.createFromPath(templateIcon).resize({ height: 16 })
|
||||
const iconPaths = getIconPaths()
|
||||
const icon = nativeImage.createFromPath(iconPaths.white).resize({ height: 16 })
|
||||
icon.setTemplateImage(true)
|
||||
tray = new Tray(icon)
|
||||
}
|
||||
@ -337,6 +338,9 @@ export async function createTray(): Promise<void> {
|
||||
}
|
||||
tray?.setToolTip('Mihomo Party')
|
||||
tray?.setIgnoreDoubleClickEvents(true)
|
||||
|
||||
await updateTrayIcon()
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
if (!useDockIcon) {
|
||||
hideDockIcon()
|
||||
@ -377,6 +381,7 @@ async function updateTrayMenu(): Promise<void> {
|
||||
if (process.platform === 'linux') {
|
||||
tray?.setContextMenu(menu)
|
||||
}
|
||||
await updateTrayIcon()
|
||||
}
|
||||
|
||||
export async function copyEnv(type: 'bash' | 'cmd' | 'powershell'): Promise<void> {
|
||||
@ -429,3 +434,43 @@ export async function hideDockIcon(): Promise<void> {
|
||||
app.dock.hide()
|
||||
}
|
||||
}
|
||||
|
||||
const getIconPaths = () => {
|
||||
if (process.platform === 'win32') {
|
||||
return {
|
||||
white: icoIcon,
|
||||
blue: icoIconBlue,
|
||||
green: icoIconGreen,
|
||||
red: icoIconRed
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
white: pngIcon,
|
||||
blue: pngIconBlue,
|
||||
green: pngIconGreen,
|
||||
red: pngIconRed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateTrayIcon(): Promise<void> {
|
||||
if (!tray) return
|
||||
|
||||
const status = await getTrayIconStatus()
|
||||
const iconPaths = getIconPaths()
|
||||
const iconPath = iconPaths[status]
|
||||
|
||||
try {
|
||||
if (process.platform === 'darwin') {
|
||||
const icon = nativeImage.createFromPath(iconPath).resize({ height: 16 })
|
||||
icon.setTemplateImage(true)
|
||||
tray.setImage(icon)
|
||||
} else if (process.platform === 'win32') {
|
||||
tray.setImage(iconPath)
|
||||
} else if (process.platform === 'linux') {
|
||||
tray.setImage(iconPath)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新托盘图标失败:', error)
|
||||
}
|
||||
}
|
||||
@ -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 } from '../resolve/tray'
|
||||
import { closeTrayIcon, copyEnv, showTrayIcon, updateTrayIcon } from '../resolve/tray'
|
||||
import { registerShortcut } from '../resolve/shortcut'
|
||||
import { closeMainWindow, mainWindow, showMainWindow, triggerMainWindow } from '..'
|
||||
import {
|
||||
@ -259,6 +259,7 @@ export function registerIpcMainHandlers(): void {
|
||||
})
|
||||
ipcMain.handle('showTrayIcon', () => ipcErrorWrapper(showTrayIcon)())
|
||||
ipcMain.handle('closeTrayIcon', () => ipcErrorWrapper(closeTrayIcon)())
|
||||
ipcMain.handle('updateTrayIcon', () => ipcErrorWrapper(updateTrayIcon)())
|
||||
ipcMain.handle('showMainWindow', showMainWindow)
|
||||
ipcMain.handle('closeMainWindow', closeMainWindow)
|
||||
ipcMain.handle('triggerMainWindow', triggerMainWindow)
|
||||
|
||||
@ -2,7 +2,7 @@ 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 } from '@renderer/utils/ipc'
|
||||
import { triggerSysProxy, updateTrayIcon } from '@renderer/utils/ipc'
|
||||
import { AiOutlineGlobal } from 'react-icons/ai'
|
||||
import React from 'react'
|
||||
import { useSortable } from '@dnd-kit/sortable'
|
||||
@ -43,6 +43,7 @@ const SysproxySwitcher: React.FC<Props> = (props) => {
|
||||
|
||||
window.electron.ipcRenderer.send('updateFloatingWindow')
|
||||
window.electron.ipcRenderer.send('updateTrayMenu')
|
||||
await updateTrayIcon()
|
||||
} catch (e) {
|
||||
await patchAppConfig({ sysProxy: { enable: previousState } })
|
||||
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 } from '@renderer/utils/ipc'
|
||||
import { restartCore, updateTrayIcon } from '@renderer/utils/ipc'
|
||||
import { useSortable } from '@dnd-kit/sortable'
|
||||
import { CSS } from '@dnd-kit/utilities'
|
||||
import React from 'react'
|
||||
@ -84,6 +84,7 @@ const TunSwitcher: React.FC<Props> = (props) => {
|
||||
await restartCore()
|
||||
window.electron.ipcRenderer.send('updateFloatingWindow')
|
||||
window.electron.ipcRenderer.send('updateTrayMenu')
|
||||
await updateTrayIcon()
|
||||
}
|
||||
|
||||
if (iconOnly) {
|
||||
|
||||
@ -402,6 +402,10 @@ export async function closeTrayIcon(): Promise<void> {
|
||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('closeTrayIcon'))
|
||||
}
|
||||
|
||||
export async function updateTrayIcon(): Promise<void> {
|
||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('updateTrayIcon'))
|
||||
}
|
||||
|
||||
export async function showMainWindow(): Promise<void> {
|
||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('showMainWindow'))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user