From e21558ac37425ab0e81ecc78472eb27c7e1a9f5e Mon Sep 17 00:00:00 2001 From: xmk23333 Date: Thu, 15 Jan 2026 23:14:17 +0800 Subject: [PATCH] fix: use sync state to prevent tray icon flickering on macOS with traffic display --- src/main/resolve/tray.ts | 19 ++++++++++++------- .../src/components/sider/conn-card.tsx | 4 ++-- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/main/resolve/tray.ts b/src/main/resolve/tray.ts index d8caeca..ed16714 100644 --- a/src/main/resolve/tray.ts +++ b/src/main/resolve/tray.ts @@ -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 => { // 添加调试日志 @@ -231,6 +233,7 @@ export const buildContextMenu = async (): Promise => { 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 { } // 移除旧监听器防止累积 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 { 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] diff --git a/src/renderer/src/components/sider/conn-card.tsx b/src/renderer/src/components/sider/conn-card.tsx index 22eae85..4bdd8b4 100644 --- a/src/renderer/src/components/sider/conn-card.tsx +++ b/src/renderer/src/components/sider/conn-card.tsx @@ -161,7 +161,7 @@ const ConnCard: React.FC = (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,${calcTraffic(upload)}/s${calcTraffic(download)}/s` const image = await loadImage(svg) - window.electron.ipcRenderer.send('trayIconUpdate', image) + window.electron.ipcRenderer.send('trayIconUpdate', image, true) } const loadImage = (url: string): Promise => {