feat: Add proper tray icons for Windows dark mode (#2476)
|
@ -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 (
|
||||
|
|
After Width: | Height: | Size: 937 B |
After Width: | Height: | Size: 740 B |
After Width: | Height: | Size: 879 B |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 6 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 6 KiB |
After Width: | Height: | Size: 6.3 KiB |
|
@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|