fix: use sync state to prevent tray icon flickering on macOS with traffic display

This commit is contained in:
xmk23333 2026-01-15 23:14:17 +08:00
parent 228e2cbffc
commit e21558ac37
2 changed files with 14 additions and 9 deletions

View File

@ -39,6 +39,8 @@ import { trayLogger } from '../utils/logger'
import { floatingWindow, triggerFloatingWindow } from './floatingWindow'
export let tray: Tray | null = null
// macOS 流量显示状态,避免异步读取配置导致的时序问题
let macTrafficIconEnabled = false
export const buildContextMenu = async (): Promise<Menu> => {
// 添加调试日志
@ -231,6 +233,7 @@ export const buildContextMenu = async (): Promise<Menu> => {
if (process.platform === 'win32') {
try {
await restartAsAdmin()
return
} catch (error) {
await trayLogger.error('Failed to restart as admin from tray', error)
item.checked = false
@ -392,7 +395,8 @@ export async function createTray(): Promise<void> {
}
// 移除旧监听器防止累积
ipcMain.removeAllListeners('trayIconUpdate')
ipcMain.on('trayIconUpdate', async (_, png: string) => {
ipcMain.on('trayIconUpdate', async (_, png: string, enabled: boolean) => {
macTrafficIconEnabled = enabled
const image = nativeImage.createFromDataURL(png).resize({ height: 16 })
image.setTemplateImage(true)
tray?.setImage(image)
@ -524,14 +528,15 @@ const getIconPaths = () => {
export function updateTrayIconImmediate(sysProxyEnabled: boolean, tunEnabled: boolean): void {
if (!tray) return
// macOS 流量显示开启时,由 trayIconUpdate 负责图标更新
if (process.platform === 'darwin' && macTrafficIconEnabled) return
const status = calculateTrayIconStatus(sysProxyEnabled, tunEnabled)
const iconPaths = getIconPaths()
getAppConfig().then(({ disableTrayIconColor = false, showTraffic = false }) => {
getAppConfig().then(({ disableTrayIconColor = false }) => {
if (!tray) return
// macOS 开启流量显示时,由 trayIconUpdate 负责图标更新
if (process.platform === 'darwin' && showTraffic) return
if (process.platform === 'darwin' && macTrafficIconEnabled) return
const iconPath = disableTrayIconColor ? iconPaths.white : iconPaths[status]
try {
if (process.platform === 'darwin') {
@ -550,10 +555,10 @@ export function updateTrayIconImmediate(sysProxyEnabled: boolean, tunEnabled: bo
export async function updateTrayIcon(): Promise<void> {
if (!tray) return
// macOS 流量显示开启时,由 trayIconUpdate 负责图标更新
if (process.platform === 'darwin' && macTrafficIconEnabled) return
const { disableTrayIconColor = false, showTraffic = false } = await getAppConfig()
// macOS 开启流量显示时,由 trayIconUpdate 负责图标更新
if (process.platform === 'darwin' && showTraffic) return
const { disableTrayIconColor = false } = await getAppConfig()
const status = await getTrayIconStatus()
const iconPaths = getIconPaths()
const iconPath = disableTrayIconColor ? iconPaths.white : iconPaths[status]

View File

@ -161,7 +161,7 @@ const ConnCard: React.FC<Props> = (props) => {
}
} else if (hasShowTrafficRef.current) {
// 只在从 showTraffic=true 切换到 false 时恢复一次原始图标
window.electron.ipcRenderer.send('trayIconUpdate', trayIconBase64)
window.electron.ipcRenderer.send('trayIconUpdate', trayIconBase64, false)
hasShowTrafficRef.current = false
}
}
@ -305,7 +305,7 @@ const drawSvg = async (
currentDownloadRef.current = download
const svg = `data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 140 36"><image height="36" width="36" href="${trayIconBase64}"/><text x="140" y="15" font-size="18" font-family="PingFang SC" font-weight="bold" text-anchor="end">${calcTraffic(upload)}/s</text><text x="140" y="34" font-size="18" font-family="PingFang SC" font-weight="bold" text-anchor="end">${calcTraffic(download)}/s</text></svg>`
const image = await loadImage(svg)
window.electron.ipcRenderer.send('trayIconUpdate', image)
window.electron.ipcRenderer.send('trayIconUpdate', image, true)
}
const loadImage = (url: string): Promise<string> => {