feat: Add proper tray icons for Windows dark mode (#2476)

This commit is contained in:
Janosch Braukmann 2023-12-10 18:39:35 +01:00 committed by GitHub
parent 59cb1b1dbb
commit d219a65e75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 59 additions and 41 deletions

View file

@ -170,8 +170,6 @@ class AppearanceModeSwitch extends React.Component<
}
}
const { INBOX_ZERO_ICON, INBOX_FULL_ICON, INBOX_FULL_NEW_ICON, INBOX_FULL_UNREAD_ICON } = SystemTrayIconStore;
class TrayIconStylePicker extends React.Component<{ config: ConfigLike }> {
kp = 'core.workspace.trayIconStyle';
@ -180,11 +178,12 @@ class TrayIconStylePicker extends React.Component<{ config: ConfigLike }> {
};
render() {
let systemTrayIconScore = new SystemTrayIconStore();
const val = this.props.config.get(this.kp) || 'blue';
const options = [
['blue', localized('Blue icon for new and unread messages'), localized('(The same blue tray icon is used whether you have new or old unread messages.)'), INBOX_FULL_UNREAD_ICON],
['red', localized('Red icon for new and blue icon for unread messages'), localized('(A red tray icon is displayed for new messages and a blue icon for older unread messages.)'), INBOX_FULL_NEW_ICON],
['blue', localized('Blue icon for new and unread messages'), localized('(The same blue tray icon is used whether you have new or old unread messages.)'), systemTrayIconScore.inboxFullUnreadIcon()],
['red', localized('Red icon for new and blue icon for unread messages'), localized('(A red tray icon is displayed for new messages and a blue icon for older unread messages.)'), systemTrayIconScore.inboxFullNewIcon()],
];
return (

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -5,22 +5,7 @@ import { BadgeStore } from 'mailspring-exports';
// Must be absolute real system path
// https://github.com/atom/electron/issues/1299
const { platform } = process;
const INBOX_ZERO_ICON = path.join(__dirname, '..', 'assets', platform, 'MenuItem-Inbox-Zero.png');
const INBOX_FULL_ICON = path.join(__dirname, '..', 'assets', platform, 'MenuItem-Inbox-Full.png');
const INBOX_FULL_NEW_ICON = path.join(
__dirname,
'..',
'assets',
platform,
'MenuItem-Inbox-Full-NewItems.png'
);
const INBOX_FULL_UNREAD_ICON = path.join(
__dirname,
'..',
'assets',
platform,
'MenuItem-Inbox-Full-UnreadItems.png'
);
const { nativeTheme } = require("@electron/remote");
/*
Current / Intended Behavior:
@ -38,13 +23,6 @@ Current / Intended Behavior:
it will switch to blue.)
*/
class SystemTrayIconStore {
static INBOX_ZERO_ICON = INBOX_ZERO_ICON;
static INBOX_FULL_ICON = INBOX_FULL_ICON;
static INBOX_FULL_NEW_ICON = INBOX_FULL_NEW_ICON;
static INBOX_FULL_UNREAD_ICON = INBOX_FULL_UNREAD_ICON;
_windowBackgrounded = false;
_unsubscribers: (() => void)[];
@ -66,6 +44,11 @@ class SystemTrayIconStore {
window.removeEventListener('browser-window-hide', this._onWindowBackgrounded);
window.removeEventListener('browser-window-blur', this._onWindowBackgrounded);
});
// If the theme changes from bright to dark mode or vice versa, we need to update the tray icon
nativeTheme.on('updated', () => {
this._updateIcon();
})
}
deactivate() {
@ -84,6 +67,44 @@ class SystemTrayIconStore {
this._updateIcon();
};
// This implementation is windows only.
// On Mac the icon color is automatically inverted
// Linux ships with the icons used for a dark tray only
_dark = () => {
if (nativeTheme.shouldUseDarkColors && process.platform === 'win32') {
return "-dark";
}
return "";
}
inboxZeroIcon = () => {
return path.join(__dirname, '..', 'assets', platform, `MenuItem-Inbox-Zero${this._dark()}.png`);
}
inboxFullIcon = () => {
return path.join(__dirname, '..', 'assets', platform, `MenuItem-Inbox-Full${this._dark()}.png`);
}
inboxFullNewIcon = () => {
return path.join(
__dirname,
'..',
'assets',
platform,
`MenuItem-Inbox-Full-NewItems${this._dark()}.png`
);
}
inboxFullUnreadIcon = () => {
return path.join(
__dirname,
'..',
'assets',
platform,
`MenuItem-Inbox-Full-UnreadItems${this._dark()}.png`
);
}
_updateIcon = () => {
const unread = BadgeStore.unread();
const unreadString = (+unread).toLocaleString();
@ -91,17 +112,17 @@ class SystemTrayIconStore {
const newMessagesIconStyle = AppEnv.config.get('core.workspace.trayIconStyle') || 'blue';
let icon = { path: INBOX_FULL_ICON, isTemplateImg: true };
let icon = { path: this.inboxFullIcon(), isTemplateImg: true };
if (isInboxZero) {
icon = { path: INBOX_ZERO_ICON, isTemplateImg: true };
icon = { path: this.inboxZeroIcon(), isTemplateImg: true };
} else if (unread !== 0) {
if (newMessagesIconStyle === 'blue') {
icon = { path: INBOX_FULL_UNREAD_ICON, isTemplateImg: false };
icon = { path: this.inboxFullUnreadIcon(), isTemplateImg: false };
} else {
if (this._windowBackgrounded) {
icon = { path: INBOX_FULL_NEW_ICON, isTemplateImg: false };
icon = { path: this.inboxFullNewIcon(), isTemplateImg: false };
} else {
icon = { path: INBOX_FULL_UNREAD_ICON, isTemplateImg: false };
icon = { path: this.inboxFullUnreadIcon(), isTemplateImg: false };
}
}
}

View file

@ -2,8 +2,6 @@ import { ipcRenderer } from 'electron';
import { BadgeStore } from 'mailspring-exports';
import SystemTrayIconStore from '../lib/system-tray-icon-store';
const { INBOX_ZERO_ICON, INBOX_FULL_ICON, INBOX_FULL_NEW_ICON, INBOX_FULL_UNREAD_ICON } = SystemTrayIconStore;
describe('SystemTrayIconStore', function systemTrayIconStore() {
beforeEach(() => {
spyOn(ipcRenderer, 'send');
@ -20,7 +18,7 @@ describe('SystemTrayIconStore', function systemTrayIconStore() {
spyOn(BadgeStore, 'unread').andReturn(0);
spyOn(BadgeStore, 'total').andReturn(0);
this.iconStore._updateIcon();
expect(getCallData()).toEqual({ path: INBOX_ZERO_ICON, isTemplateImg: true });
expect(getCallData()).toEqual({ path: this.iconStore.inboxZeroIcon(), isTemplateImg: true });
});
it('shows inbox zero icon when isInboxZero and window is blurred', () => {
@ -28,7 +26,7 @@ describe('SystemTrayIconStore', function systemTrayIconStore() {
spyOn(BadgeStore, 'unread').andReturn(0);
spyOn(BadgeStore, 'total').andReturn(0);
this.iconStore._updateIcon();
expect(getCallData()).toEqual({ path: INBOX_ZERO_ICON, isTemplateImg: true });
expect(getCallData()).toEqual({ path: this.iconStore.inboxZeroIcon(), isTemplateImg: true });
});
it('shows inbox full icon when not isInboxZero and window is focused', () => {
@ -36,7 +34,7 @@ describe('SystemTrayIconStore', function systemTrayIconStore() {
spyOn(BadgeStore, 'unread').andReturn(102);
spyOn(BadgeStore, 'total').andReturn(123123);
this.iconStore._updateIcon();
expect(getCallData()).toEqual({ path: INBOX_FULL_ICON, isTemplateImg: true });
expect(getCallData()).toEqual({ path: this.iconStore.inboxFullIcon(), isTemplateImg: true });
});
it('shows inbox full /alt/ icon when not isInboxZero and window is blurred', () => {
@ -44,7 +42,7 @@ describe('SystemTrayIconStore', function systemTrayIconStore() {
spyOn(BadgeStore, 'unread').andReturn(102);
spyOn(BadgeStore, 'total').andReturn(123123);
this.iconStore._updateIcon();
expect(getCallData()).toEqual({ path: INBOX_FULL_UNREAD_ICON, isTemplateImg: false });
expect(getCallData()).toEqual({ path: this.iconStore.inboxFullUnreadIcon(), isTemplateImg: false });
});
});
@ -53,7 +51,7 @@ describe('SystemTrayIconStore', function systemTrayIconStore() {
spyOn(BadgeStore, 'total').andReturn(1);
this.iconStore._onWindowFocus();
const { path } = getCallData();
expect(path).toBe(INBOX_FULL_ICON);
expect(path).toBe(this.iconStore.inboxFullIcon());
});
it('shows inbox full /alt/ icon ONLY when window is currently blurred and total count changes', () => {
@ -66,7 +64,7 @@ describe('SystemTrayIconStore', function systemTrayIconStore() {
this.iconStore._updateIcon();
const { path } = getCallData();
expect(path).toBe(INBOX_FULL_UNREAD_ICON);
expect(path).toBe(this.iconStore.inboxFullUnreadIcon());
});
it('does not show inbox full /alt/ icon when window is currently focused and total count changes', () => {
@ -77,7 +75,7 @@ describe('SystemTrayIconStore', function systemTrayIconStore() {
this.iconStore._updateIcon();
const { path } = getCallData();
expect(path).toBe(INBOX_FULL_ICON);
expect(path).toBe(this.iconStore.inboxFullIcon());
});
});
});