From f373aaebcb742c31ab2323a50d39a2202763877c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?RD1=20Tyrone=20=E8=91=89=E6=BE=A4=E7=A5=A5=20295?= Date: Mon, 25 May 2026 10:51:16 +0800 Subject: [PATCH 1/8] Add support for offline tray icons and handle user login state changes --- src/public/images/tray/darwin/offline.png | Bin 0 -> 529 bytes src/public/images/tray/darwin/offline@2x.png | Bin 0 -> 1008 bytes src/public/images/tray/linux/offline.png | Bin 0 -> 3535 bytes src/public/images/tray/linux/offline@2x.png | Bin 0 -> 5182 bytes src/public/images/tray/win32/offline.ico | Bin 0 -> 113327 bytes src/ui/main/icons.ts | 38 +++++++++++++++---- src/ui/main/rootWindow.ts | 1 + src/ui/main/trayIcon.ts | 32 +++++++++++++++- 8 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 src/public/images/tray/darwin/offline.png create mode 100644 src/public/images/tray/darwin/offline@2x.png create mode 100644 src/public/images/tray/linux/offline.png create mode 100644 src/public/images/tray/linux/offline@2x.png create mode 100644 src/public/images/tray/win32/offline.ico diff --git a/src/public/images/tray/darwin/offline.png b/src/public/images/tray/darwin/offline.png new file mode 100644 index 0000000000000000000000000000000000000000..fc5d17596fb3e12dc6a126ed4e02d8939fcd8d3e GIT binary patch literal 529 zcmV+s0`C2ZP)z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUzk4Z#9R7l6QmA@|pK@@<$)p1<7ghWD6&|gP!5}^<(QBYi?Adx6U z;lEI*X#53AE);@9At6F7QC!F+E|J5bl8okUyc@G-kG+>{W_RYz`{vF2u^2E03=NW| z@TF0Zz&0MpT%sOmqXJt3vPpZB3*#XW0~CSfe_xT3eFM{u#a*BoX!~}QE1&?J)B_wq zd7(V{?Wq78KqfBa(E*vXbW%Vb*a7YZ^aSL5#wXOtRxC)Aq=0R;Z#+t|6(|E$U_@tC z%wk*>KsicbOcd7ag*qUIVk7&bl7TK657gWd@D@OyqvGep*t*i+ld;zY_>}QO&9%#z z4q(uNw1jI)zY>xDAZ{68)|&5D@153l^;o)F_7&Mu1nzt}9TAgZUyya0-um*{g5-gB z**ovsTLNCxcN!Rq0eJ=%ea8Fc6sOAgnJS`dSvv<_9To3wb_HNcnp+i^0Xifu54DHq zQu6*d?*C-e(a4IxrnCe85cnEe23U}mTmmkDn|fNY%acTZk1j~!00*Qo5<z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBU#Zb?KzRA}DSnoUR*Q51l`QAthdKk_F+7lF_#f+Dl9T@X~zrj50T zil``sRxNDN4@E&zAhigCpiNNZqE)#lk$#P$KSLv_46bRXP~_s*M{HzRKj zTprB3=bZc9-*fH^04}&LxFk><*>DG(Bmor22T2V1|1B2N+T12k=}?!;!e*R%CiOz(@osgTNJFbDR)oVur|+UqCxBD{6ph-BHXC zE-(!2iE0gGqz|amwp5#uLEw!l!$4a7mH`WZg+MKk0+s=@J$!ZoJAjEOM&W_%Da%L% zl?}jEHGNE@@d~KPwec0I7p3vOh#&yw0_Q9cpVi2Pl2V}8V6;U)p(BC-SOPpT_+0Q38Aux~nZd?umNESrZzAj2oWK0~*D%E!xR^%_GxW3oNqf3K)@-V)ZtNY9ncIcwrs_RJRr6L`_+zPlKG96JT19O!ocWo0^4=A^oo1@K*SG_FoZRGxY(f{U$7nM>lZ5Jg$CB0Zt*2DSt1ft`l> zJt_^Y)=HI%Uq-d7#a`f%yjpY&@9SJ}!(Q#*2-utFW8R&DU$6TtUx1BKUk643(E>d4 zXm}T}JI+g4zYy8x*Gyogx+?#q7T&appVwV^{}wVEL?Ye=dqE`TvjQ7LqP~l;KqN~H eAEzWwbcnxv6vjO}I@X~80000> literal 0 HcmV?d00001 diff --git a/src/public/images/tray/linux/offline.png b/src/public/images/tray/linux/offline.png new file mode 100644 index 0000000000000000000000000000000000000000..c12af62be2aa7ce26de4e4ae4a1699080e8f84d8 GIT binary patch literal 3535 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 sJ<%??pF literal 0 HcmV?d00001 diff --git a/src/public/images/tray/win32/offline.ico b/src/public/images/tray/win32/offline.ico new file mode 100644 index 0000000000000000000000000000000000000000..c94256880c2b7fe521e3fe0660ba48f2d03eec32 GIT binary patch literal 113327 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 literal 0 HcmV?d00001 diff --git a/src/ui/main/icons.ts b/src/ui/main/icons.ts index 19b809d78c..0b0332cb82 100644 --- a/src/ui/main/icons.ts +++ b/src/ui/main/icons.ts @@ -16,13 +16,28 @@ export const getAppIconPath = ({ return `${app.getAppPath()}/app/images/icon.ico`; }; -const getMacOSTrayIconPath = (badge: Server['badge']): string => - path.join( +const getMacOSTrayIconPath = ( + badge: Server['badge'], + isLoggedIn: boolean +): string => { + if (!isLoggedIn) { + return path.join(app.getAppPath(), 'app/images/tray/darwin/offline.png'); + } + + return path.join( app.getAppPath(), `app/images/tray/darwin/${badge ? 'notification' : 'default'}Template.png` ); +} + +const getWindowsTrayIconPath = ( + badge: Server['badge'], + isLoggedIn: boolean +): string => { + if (!isLoggedIn) { + return path.join(app.getAppPath(), 'app/images/tray/win32/offline.ico'); + } -const getWindowsTrayIconPath = (badge: Server['badge']): string => { const name = (!badge && 'default') || (badge === '•' && 'notification-dot') || @@ -31,7 +46,14 @@ const getWindowsTrayIconPath = (badge: Server['badge']): string => { return path.join(app.getAppPath(), `app/images/tray/win32/${name}.ico`); }; -const getLinuxTrayIconPath = (badge: Server['badge']): string => { +const getLinuxTrayIconPath = ( + badge: Server['badge'], + isLoggedIn: boolean +): string => { + if (!isLoggedIn) { + return path.join(app.getAppPath(), 'app/images/tray/linux/offline.png'); + } + const name = (!badge && 'default') || (badge === '•' && 'notification-dot') || @@ -43,19 +65,21 @@ const getLinuxTrayIconPath = (badge: Server['badge']): string => { export const getTrayIconPath = ({ badge, platform, + isLoggedIn = false, }: { badge?: Server['badge']; platform: NodeJS.Platform; + isLoggedIn?: boolean; }): string => { switch (platform ?? process.platform) { case 'darwin': - return getMacOSTrayIconPath(badge); + return getMacOSTrayIconPath(badge, isLoggedIn); case 'win32': - return getWindowsTrayIconPath(badge); + return getWindowsTrayIconPath(badge, isLoggedIn); case 'linux': - return getLinuxTrayIconPath(badge); + return getLinuxTrayIconPath(badge, isLoggedIn); default: throw Error(`unsupported platform (${platform})`); diff --git a/src/ui/main/rootWindow.ts b/src/ui/main/rootWindow.ts index bdc40ca3f3..e2689d6599 100644 --- a/src/ui/main/rootWindow.ts +++ b/src/ui/main/rootWindow.ts @@ -438,6 +438,7 @@ export const setupRootWindow = (): void => { getTrayIconPath({ platform: process.platform, badge: globalBadge, + isLoggedIn: true, }) ) ); diff --git a/src/ui/main/trayIcon.ts b/src/ui/main/trayIcon.ts index 2baca3d90e..92baed5e52 100644 --- a/src/ui/main/trayIcon.ts +++ b/src/ui/main/trayIcon.ts @@ -1,4 +1,4 @@ -import { app, Menu, nativeImage, Tray } from 'electron'; +import { app, Menu, nativeImage, Tray, Notification } from 'electron'; import i18next from 'i18next'; import type { Server } from '../../servers/common'; @@ -63,9 +63,12 @@ const createTrayIcon = (): Tray => { }; const updateTrayIconImage = (trayIcon: Tray, badge: Server['badge']): void => { + const servers = select(({ servers }) => servers || []); + const isLoggedIn = servers.every((server) => server.userLoggedIn); const image = getTrayIconPath({ platform: process.platform, badge, + isLoggedIn, }); trayIcon.setImage(nativeImage.createFromPath(image)); }; @@ -128,6 +131,32 @@ const manageTrayIcon = async (): Promise<() => void> => { updateTrayIconToolTip(trayIcon, globalBadge); }); + const unwatchUserLoggedIn = watch( + (state: RootState) => { + const servers = state.servers || []; + return ( + servers.length > 0 && servers.every((server) => !server.userLoggedIn) + ); + }, + async (isLoggedOut) => { + if (isLoggedOut) { + const rootWindow = await getRootWindow(); + if (rootWindow) { + if (rootWindow.isMinimized()) rootWindow.restore(); + rootWindow.show(); + rootWindow.focus(); + } + new Notification({ + title: t('tray.balloon.stillRunning.title', { appName: app.name }), + body: t('error.authNeeded', { auth: '' }).replace(/<\/?strong>/g, ''), + timeoutType: 'never', + urgency: 'critical', + }).show(); + } + updateTrayIconImage(trayIcon, undefined); + } + ); + let firstTrayIconBalloonShown = false; const unwatchIsRootWindowVisible = watch( @@ -175,6 +204,7 @@ const manageTrayIcon = async (): Promise<() => void> => { return () => { unwatchGlobalBadge(); + unwatchUserLoggedIn(); unwatchIsRootWindowVisible(); trayIcon.destroy(); }; From a983e3d732dedfff2edc90e30bae5f86e6278874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?RD1=20Tyrone=20=E8=91=89=E6=BE=A4=E7=A5=A5=20295?= Date: Mon, 25 May 2026 11:53:23 +0800 Subject: [PATCH 2/8] Fix tray icon notification body formatting by properly escaping HTML tags --- src/ui/main/trayIcon.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ui/main/trayIcon.ts b/src/ui/main/trayIcon.ts index 92baed5e52..62d8ac8bb0 100644 --- a/src/ui/main/trayIcon.ts +++ b/src/ui/main/trayIcon.ts @@ -148,7 +148,10 @@ const manageTrayIcon = async (): Promise<() => void> => { } new Notification({ title: t('tray.balloon.stillRunning.title', { appName: app.name }), - body: t('error.authNeeded', { auth: '' }).replace(/<\/?strong>/g, ''), + body: t('error.authNeeded', { auth: '' }).replace( + /<[\/]?strong>/g, + '' + ), timeoutType: 'never', urgency: 'critical', }).show(); From 49f4ab5276c4467bd6ddd940d13d4b5364e093e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?RD1=20Tyrone=20=E8=91=89=E6=BE=A4=E7=A5=A5=20295?= Date: Mon, 25 May 2026 14:05:25 +0800 Subject: [PATCH 3/8] Fix trailing semicolon and reposition updateTrayIconImage call --- src/ui/main/icons.ts | 2 +- src/ui/main/trayIcon.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/main/icons.ts b/src/ui/main/icons.ts index 0b0332cb82..d213141e60 100644 --- a/src/ui/main/icons.ts +++ b/src/ui/main/icons.ts @@ -28,7 +28,7 @@ const getMacOSTrayIconPath = ( app.getAppPath(), `app/images/tray/darwin/${badge ? 'notification' : 'default'}Template.png` ); -} +}; const getWindowsTrayIconPath = ( badge: Server['badge'], diff --git a/src/ui/main/trayIcon.ts b/src/ui/main/trayIcon.ts index 62d8ac8bb0..56c0e087d4 100644 --- a/src/ui/main/trayIcon.ts +++ b/src/ui/main/trayIcon.ts @@ -155,8 +155,8 @@ const manageTrayIcon = async (): Promise<() => void> => { timeoutType: 'never', urgency: 'critical', }).show(); + updateTrayIconImage(trayIcon, undefined); } - updateTrayIconImage(trayIcon, undefined); } ); From 889dd266c7d26dfa71ff8918a9f75424285977dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?RD1=20Tyrone=20=E8=91=89=E6=BE=A4=E7=A5=A5=20295?= Date: Mon, 25 May 2026 14:16:41 +0800 Subject: [PATCH 4/8] Fix tray icon update timing in notification handler --- src/ui/main/trayIcon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/main/trayIcon.ts b/src/ui/main/trayIcon.ts index 56c0e087d4..62d8ac8bb0 100644 --- a/src/ui/main/trayIcon.ts +++ b/src/ui/main/trayIcon.ts @@ -155,8 +155,8 @@ const manageTrayIcon = async (): Promise<() => void> => { timeoutType: 'never', urgency: 'critical', }).show(); - updateTrayIconImage(trayIcon, undefined); } + updateTrayIconImage(trayIcon, undefined); } ); From 0e77c046ca6d32f3bf8c3728ef54593b7961d046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?RD1=20Tyrone=20=E8=91=89=E6=BE=A4=E7=A5=A5=20295?= Date: Mon, 25 May 2026 14:26:27 +0800 Subject: [PATCH 5/8] Fix tray icon badge update to use global badge state --- src/ui/main/trayIcon.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ui/main/trayIcon.ts b/src/ui/main/trayIcon.ts index 62d8ac8bb0..124c768a0d 100644 --- a/src/ui/main/trayIcon.ts +++ b/src/ui/main/trayIcon.ts @@ -156,7 +156,8 @@ const manageTrayIcon = async (): Promise<() => void> => { urgency: 'critical', }).show(); } - updateTrayIconImage(trayIcon, undefined); + const globalBadge = select(selectGlobalBadge); + updateTrayIconImage(trayIcon, globalBadge); } ); From 3e6dda280b18c51f73b322c2eb486821cfb73c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?RD1=20Tyrone=20=E8=91=89=E6=BE=A4=E7=A5=A5=20295?= Date: Mon, 25 May 2026 14:34:36 +0800 Subject: [PATCH 6/8] Fix regex pattern for removing strong tags in tray icon notification --- src/ui/main/trayIcon.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ui/main/trayIcon.ts b/src/ui/main/trayIcon.ts index 124c768a0d..91f5e788d7 100644 --- a/src/ui/main/trayIcon.ts +++ b/src/ui/main/trayIcon.ts @@ -148,10 +148,7 @@ const manageTrayIcon = async (): Promise<() => void> => { } new Notification({ title: t('tray.balloon.stillRunning.title', { appName: app.name }), - body: t('error.authNeeded', { auth: '' }).replace( - /<[\/]?strong>/g, - '' - ), + body: t('error.authNeeded', { auth: '' }).replace(/<\/?strong>/g, ''), timeoutType: 'never', urgency: 'critical', }).show(); From 0fdb86ef909e7c34ee2943e9c63606a1ff9166a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?RD1=20Tyrone=20=E8=91=89=E6=BE=A4=E7=A5=A5=20295?= Date: Mon, 25 May 2026 14:45:13 +0800 Subject: [PATCH 7/8] Fix tray icon behavior when user logs out by handling potential root window errors --- src/ui/main/trayIcon.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ui/main/trayIcon.ts b/src/ui/main/trayIcon.ts index 91f5e788d7..833fdcacac 100644 --- a/src/ui/main/trayIcon.ts +++ b/src/ui/main/trayIcon.ts @@ -140,11 +140,13 @@ const manageTrayIcon = async (): Promise<() => void> => { }, async (isLoggedOut) => { if (isLoggedOut) { - const rootWindow = await getRootWindow(); - if (rootWindow) { + try { + const rootWindow = await getRootWindow(); if (rootWindow.isMinimized()) rootWindow.restore(); rootWindow.show(); rootWindow.focus(); + } catch { + // Root window may not be ready/destroyed; continue with notification/icon update. } new Notification({ title: t('tray.balloon.stillRunning.title', { appName: app.name }), From f8fe5b89c66e75936c22617f26b1499bca79485b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?RD1=20Tyrone=20=E8=91=89=E6=BE=A4=E7=A5=A5=20295?= Date: Mon, 25 May 2026 15:04:36 +0800 Subject: [PATCH 8/8] Fix tray icon visibility logic to show icon when servers are logged out --- src/ui/main/trayIcon.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/main/trayIcon.ts b/src/ui/main/trayIcon.ts index 833fdcacac..e840cc8b61 100644 --- a/src/ui/main/trayIcon.ts +++ b/src/ui/main/trayIcon.ts @@ -135,7 +135,7 @@ const manageTrayIcon = async (): Promise<() => void> => { (state: RootState) => { const servers = state.servers || []; return ( - servers.length > 0 && servers.every((server) => !server.userLoggedIn) + servers.length === 0 || servers.some((server) => !server.userLoggedIn) ); }, async (isLoggedOut) => {