mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2026-02-10 19:50:28 +08:00
fix: use sync state to prevent tray icon flickering on macOS with traffic display
This commit is contained in:
parent
228e2cbffc
commit
e21558ac37
@ -39,6 +39,8 @@ import { trayLogger } from '../utils/logger'
|
|||||||
import { floatingWindow, triggerFloatingWindow } from './floatingWindow'
|
import { floatingWindow, triggerFloatingWindow } from './floatingWindow'
|
||||||
|
|
||||||
export let tray: Tray | null = null
|
export let tray: Tray | null = null
|
||||||
|
// macOS 流量显示状态,避免异步读取配置导致的时序问题
|
||||||
|
let macTrafficIconEnabled = false
|
||||||
|
|
||||||
export const buildContextMenu = async (): Promise<Menu> => {
|
export const buildContextMenu = async (): Promise<Menu> => {
|
||||||
// 添加调试日志
|
// 添加调试日志
|
||||||
@ -231,6 +233,7 @@ export const buildContextMenu = async (): Promise<Menu> => {
|
|||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
try {
|
try {
|
||||||
await restartAsAdmin()
|
await restartAsAdmin()
|
||||||
|
return
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await trayLogger.error('Failed to restart as admin from tray', error)
|
await trayLogger.error('Failed to restart as admin from tray', error)
|
||||||
item.checked = false
|
item.checked = false
|
||||||
@ -392,7 +395,8 @@ export async function createTray(): Promise<void> {
|
|||||||
}
|
}
|
||||||
// 移除旧监听器防止累积
|
// 移除旧监听器防止累积
|
||||||
ipcMain.removeAllListeners('trayIconUpdate')
|
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 })
|
const image = nativeImage.createFromDataURL(png).resize({ height: 16 })
|
||||||
image.setTemplateImage(true)
|
image.setTemplateImage(true)
|
||||||
tray?.setImage(image)
|
tray?.setImage(image)
|
||||||
@ -524,14 +528,15 @@ const getIconPaths = () => {
|
|||||||
|
|
||||||
export function updateTrayIconImmediate(sysProxyEnabled: boolean, tunEnabled: boolean): void {
|
export function updateTrayIconImmediate(sysProxyEnabled: boolean, tunEnabled: boolean): void {
|
||||||
if (!tray) return
|
if (!tray) return
|
||||||
|
// macOS 流量显示开启时,由 trayIconUpdate 负责图标更新
|
||||||
|
if (process.platform === 'darwin' && macTrafficIconEnabled) return
|
||||||
|
|
||||||
const status = calculateTrayIconStatus(sysProxyEnabled, tunEnabled)
|
const status = calculateTrayIconStatus(sysProxyEnabled, tunEnabled)
|
||||||
const iconPaths = getIconPaths()
|
const iconPaths = getIconPaths()
|
||||||
|
|
||||||
getAppConfig().then(({ disableTrayIconColor = false, showTraffic = false }) => {
|
getAppConfig().then(({ disableTrayIconColor = false }) => {
|
||||||
if (!tray) return
|
if (!tray) return
|
||||||
// macOS 开启流量显示时,由 trayIconUpdate 负责图标更新
|
if (process.platform === 'darwin' && macTrafficIconEnabled) return
|
||||||
if (process.platform === 'darwin' && showTraffic) return
|
|
||||||
const iconPath = disableTrayIconColor ? iconPaths.white : iconPaths[status]
|
const iconPath = disableTrayIconColor ? iconPaths.white : iconPaths[status]
|
||||||
try {
|
try {
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
@ -550,10 +555,10 @@ export function updateTrayIconImmediate(sysProxyEnabled: boolean, tunEnabled: bo
|
|||||||
|
|
||||||
export async function updateTrayIcon(): Promise<void> {
|
export async function updateTrayIcon(): Promise<void> {
|
||||||
if (!tray) return
|
if (!tray) return
|
||||||
|
// macOS 流量显示开启时,由 trayIconUpdate 负责图标更新
|
||||||
|
if (process.platform === 'darwin' && macTrafficIconEnabled) return
|
||||||
|
|
||||||
const { disableTrayIconColor = false, showTraffic = false } = await getAppConfig()
|
const { disableTrayIconColor = false } = await getAppConfig()
|
||||||
// macOS 开启流量显示时,由 trayIconUpdate 负责图标更新
|
|
||||||
if (process.platform === 'darwin' && showTraffic) return
|
|
||||||
const status = await getTrayIconStatus()
|
const status = await getTrayIconStatus()
|
||||||
const iconPaths = getIconPaths()
|
const iconPaths = getIconPaths()
|
||||||
const iconPath = disableTrayIconColor ? iconPaths.white : iconPaths[status]
|
const iconPath = disableTrayIconColor ? iconPaths.white : iconPaths[status]
|
||||||
|
|||||||
@ -161,7 +161,7 @@ const ConnCard: React.FC<Props> = (props) => {
|
|||||||
}
|
}
|
||||||
} else if (hasShowTrafficRef.current) {
|
} else if (hasShowTrafficRef.current) {
|
||||||
// 只在从 showTraffic=true 切换到 false 时恢复一次原始图标
|
// 只在从 showTraffic=true 切换到 false 时恢复一次原始图标
|
||||||
window.electron.ipcRenderer.send('trayIconUpdate', trayIconBase64)
|
window.electron.ipcRenderer.send('trayIconUpdate', trayIconBase64, false)
|
||||||
hasShowTrafficRef.current = false
|
hasShowTrafficRef.current = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -305,7 +305,7 @@ const drawSvg = async (
|
|||||||
currentDownloadRef.current = download
|
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 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)
|
const image = await loadImage(svg)
|
||||||
window.electron.ipcRenderer.send('trayIconUpdate', image)
|
window.electron.ipcRenderer.send('trayIconUpdate', image, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadImage = (url: string): Promise<string> => {
|
const loadImage = (url: string): Promise<string> => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user