diff --git a/assets/images/tray-idle-white-update.png b/assets/images/tray-idle-white-update.png new file mode 100644 index 000000000..5b040ca96 Binary files /dev/null and b/assets/images/tray-idle-white-update.png differ diff --git a/assets/images/tray-idle-white-update@2x.png b/assets/images/tray-idle-white-update@2x.png new file mode 100644 index 000000000..2581b33a1 Binary files /dev/null and b/assets/images/tray-idle-white-update@2x.png differ diff --git a/assets/images/tray-idle-white.png b/assets/images/tray-idle-white.png new file mode 100644 index 000000000..e37a3edd3 Binary files /dev/null and b/assets/images/tray-idle-white.png differ diff --git a/assets/images/tray-idle-white@2x.png b/assets/images/tray-idle-white@2x.png new file mode 100644 index 000000000..d8f5bf107 Binary files /dev/null and b/assets/images/tray-idle-white@2x.png differ diff --git a/assets/images/tray-idleTemplate.png b/assets/images/tray-idleTemplate.png index e099ec6a4..7ccebca06 100644 Binary files a/assets/images/tray-idleTemplate.png and b/assets/images/tray-idleTemplate.png differ diff --git a/src/__mocks__/state-mocks.ts b/src/__mocks__/state-mocks.ts index 07237b592..6434f25ff 100644 --- a/src/__mocks__/state-mocks.ts +++ b/src/__mocks__/state-mocks.ts @@ -97,6 +97,7 @@ const mockSystemSettings = { showNotificationsCountInTray: false, showNotifications: true, playSound: true, + useAlternateIdleIcon: false, openAtStartup: false, }; diff --git a/src/components/settings/SystemSettings.test.tsx b/src/components/settings/SystemSettings.test.tsx index f424b79c2..f11f019f9 100644 --- a/src/components/settings/SystemSettings.test.tsx +++ b/src/components/settings/SystemSettings.test.tsx @@ -137,6 +137,31 @@ describe('routes/components/settings/SystemSettings.tsx', () => { expect(updateSetting).toHaveBeenCalledWith('playSound', false); }); + it('should toggle the useAlternateIdleIcon checkbox', async () => { + await act(async () => { + render( + + + + + , + ); + }); + + fireEvent.click(screen.getByLabelText('Use alternate idle icon'), { + target: { checked: true }, + }); + + expect(updateSetting).toHaveBeenCalledTimes(1); + expect(updateSetting).toHaveBeenCalledWith('useAlternateIdleIcon', false); + }); + it('should toggle the openAtStartup checkbox', async () => { await act(async () => { render( diff --git a/src/components/settings/SystemSettings.tsx b/src/components/settings/SystemSettings.tsx index 11eff6410..4bdd57f56 100644 --- a/src/components/settings/SystemSettings.tsx +++ b/src/components/settings/SystemSettings.tsx @@ -67,6 +67,21 @@ export const SystemSettings: FC = () => { checked={settings.playSound} onChange={(evt) => updateSetting('playSound', evt.target.checked)} /> + + updateSetting('useAlternateIdleIcon', evt.target.checked) + } + tooltip={ +
+ Use a white Gitify logo (instead of the default black logo) when all + notifications are read. Particularly useful for devices which have a + dark-themed menubar or taskbar. +
+ } + /> {!isLinux() && ( { user: null, } as AuthState, settings: { + ...defaultSettings, participating: true, - playSound: true, - showNotifications: true, - hideBots: false, - showNotificationsCountInTray: false, - openAtStartup: false, - theme: 'SYSTEM', - detailedNotifications: true, - markAsDoneOnOpen: false, - markAsDoneOnUnsubscribe: false, - showAccountHeader: false, - delayNotificationState: false, - showPills: true, - showNumber: true, - keyboardShortcut: true, - groupBy: 'REPOSITORY', - filterReasons: [], - zoomPercentage: 100, - openLinks: 'FOREGROUND', } as SettingsState, }); }); @@ -403,25 +386,8 @@ describe('context/App.tsx', () => { user: null, } as AuthState, settings: { - participating: false, - playSound: true, - showNotifications: true, - hideBots: false, - showNotificationsCountInTray: false, + ...defaultSettings, openAtStartup: true, - theme: 'SYSTEM', - detailedNotifications: true, - markAsDoneOnOpen: false, - markAsDoneOnUnsubscribe: false, - showAccountHeader: false, - delayNotificationState: false, - showPills: true, - showNumber: true, - keyboardShortcut: true, - groupBy: 'REPOSITORY', - filterReasons: [], - zoomPercentage: 100, - openLinks: 'FOREGROUND', } as SettingsState, }); }); diff --git a/src/context/App.tsx b/src/context/App.tsx index c006a129b..361155612 100644 --- a/src/context/App.tsx +++ b/src/context/App.tsx @@ -37,6 +37,7 @@ import { removeAccount, } from '../utils/auth/utils'; import { + setAlternateIdleIcon, setAutoLaunch, setKeyboardShortcut, updateTrayTitle, @@ -77,6 +78,7 @@ const defaultSystemSettings = { showNotificationsCountInTray: false, showNotifications: true, playSound: true, + useAlternateIdleIcon: false, openAtStartup: false, }; @@ -196,6 +198,9 @@ export const AppProvider = ({ children }: { children: ReactNode }) => { if (name === 'openAtStartup') { setAutoLaunch(value as boolean); } + if (name === 'useAlternateIdleIcon') { + setAlternateIdleIcon(value as boolean); + } const newSettings = { ...settings, [name]: value }; setSettings(newSettings); @@ -271,6 +276,7 @@ export const AppProvider = ({ children }: { children: ReactNode }) => { if (existing.settings) { setKeyboardShortcut(existing.settings.keyboardShortcut); + setAlternateIdleIcon(existing.settings.useAlternateIdleIcon); setSettings({ ...defaultSettings, ...existing.settings }); webFrame.setZoomLevel( zoomPercentageToLevel(existing.settings.zoomPercentage), diff --git a/src/electron/main.js b/src/electron/main.js index 9bbb7bd99..bc7637dbe 100644 --- a/src/electron/main.js +++ b/src/electron/main.js @@ -21,9 +21,15 @@ log.initialize(); const idleIcon = path.resolve( `${__dirname}/../../assets/images/tray-idleTemplate.png`, ); +const idleAlternateIcon = path.resolve( + `${__dirname}/../../assets/images/tray-idle-white.png`, +); const idleUpdateAvailableIcon = path.resolve( `${__dirname}/../../assets/images/tray-idle-update.png`, ); +const idleAlternateUpdateAvailableIcon = path.resolve( + `${__dirname}/../../assets/images/tray-idle-white-update.png`, +); const activeIcon = path.resolve( `${__dirname}/../../assets/images/tray-active.png`, ); @@ -114,6 +120,8 @@ const mb = menubar({ showDockIcon: false, }); +let shouldUseAlternateIdleIcon = false; + app.whenReady().then(async () => { await onFirstRunMaybe(); @@ -177,6 +185,10 @@ app.whenReady().then(async () => { ipc.on('gitify:quit', () => mb.app.quit()); + ipc.on('gitify:use-alternate-idle-icon', (_, useAlternateIdleIcon) => { + shouldUseAlternateIdleIcon = useAlternateIdleIcon; + }); + ipc.on('gitify:icon-active', () => { if (!mb.tray.isDestroyed()) { mb.tray.setImage( @@ -189,9 +201,17 @@ app.whenReady().then(async () => { ipc.on('gitify:icon-idle', () => { if (!mb.tray.isDestroyed()) { - mb.tray.setImage( - updateAvailableMenuItem.visible ? idleUpdateAvailableIcon : idleIcon, - ); + if (shouldUseAlternateIdleIcon) { + mb.tray.setImage( + updateAvailableMenuItem.visible + ? idleAlternateUpdateAvailableIcon + : idleAlternateIcon, + ); + } else { + mb.tray.setImage( + updateAvailableMenuItem.visible ? idleUpdateAvailableIcon : idleIcon, + ); + } } }); diff --git a/src/routes/__snapshots__/Settings.test.tsx.snap b/src/routes/__snapshots__/Settings.test.tsx.snap index 90effae09..263fa1f5b 100644 --- a/src/routes/__snapshots__/Settings.test.tsx.snap +++ b/src/routes/__snapshots__/Settings.test.tsx.snap @@ -795,6 +795,49 @@ exports[`routes/Settings.tsx should render itself & its children 1`] = ` +
+
+ +
+ +
+
+
diff --git a/src/types.ts b/src/types.ts index f7c1bea00..58dbe4cd9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -75,20 +75,21 @@ interface AppearanceSettingsState { } interface NotificationSettingsState { + groupBy: GroupBy; participating: boolean; - showNotifications: boolean; markAsDoneOnOpen: boolean; markAsDoneOnUnsubscribe: boolean; delayNotificationState: boolean; - groupBy: GroupBy; } interface SystemSettingsState { openLinks: OpenPreference; + keyboardShortcut: boolean; + showNotificationsCountInTray: boolean; + showNotifications: boolean; + useAlternateIdleIcon: boolean; playSound: boolean; openAtStartup: boolean; - showNotificationsCountInTray: boolean; - keyboardShortcut: boolean; } interface FilterSettingsState { diff --git a/src/utils/comms.test.ts b/src/utils/comms.test.ts index e78779d14..a71bc5a9c 100644 --- a/src/utils/comms.test.ts +++ b/src/utils/comms.test.ts @@ -6,6 +6,7 @@ import { hideWindow, openExternalLink, quitApp, + setAlternateIdleIcon, setAutoLaunch, showWindow, updateTrayIcon, @@ -104,4 +105,13 @@ describe('utils/comms.ts', () => { openAtLogin: false, }); }); + + it('should setAlternateIdleIcon', () => { + setAlternateIdleIcon(true); + + expect(ipcRenderer.send).toHaveBeenCalledWith( + 'gitify:use-alternate-idle-icon', + true, + ); + }); }); diff --git a/src/utils/comms.ts b/src/utils/comms.ts index 03266e606..54f870d98 100644 --- a/src/utils/comms.ts +++ b/src/utils/comms.ts @@ -42,6 +42,10 @@ export function setAutoLaunch(value: boolean): void { }); } +export function setAlternateIdleIcon(value: boolean): void { + ipcRenderer.send('gitify:use-alternate-idle-icon', value); +} + export function setKeyboardShortcut(keyboardShortcut: boolean): void { ipcRenderer.send('gitify:update-keyboard-shortcut', { enabled: keyboardShortcut,