[MM-48080] Update tray icon instantly when the settings change (#2376)
* Update wording and update tray icon instantly when the settings change * Add tests * Include new file
This commit is contained in:
parent
4171774aee
commit
e1f5250c0c
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -22,6 +22,7 @@
|
|||
"FOCALBOARD",
|
||||
"gsettings",
|
||||
"ICONNAME",
|
||||
"inputflash",
|
||||
"loadscreen",
|
||||
"mmjstool",
|
||||
"NOSERVERS",
|
||||
|
@ -29,6 +30,7 @@
|
|||
"officedocument",
|
||||
"openxmlformats",
|
||||
"presentationml",
|
||||
"showunreadbadge",
|
||||
"spreadsheetml",
|
||||
"textbox",
|
||||
"UNCLOSEABLE",
|
||||
|
|
|
@ -196,9 +196,9 @@
|
|||
"renderer.components.settingsPage.showUnreadBadge.description": "Regardless of this setting, mentions are always indicated with a red badge and item count on the {taskbar} icon.",
|
||||
"renderer.components.settingsPage.startAppOnLogin": "Start app on login",
|
||||
"renderer.components.settingsPage.startAppOnLogin.description": "If enabled, the app starts automatically when you log in to your machine.",
|
||||
"renderer.components.settingsPage.trayIcon.color": "Icon color: ",
|
||||
"renderer.components.settingsPage.trayIcon.show": "Show icon in the notification area",
|
||||
"renderer.components.settingsPage.trayIcon.show.darwin": "Show {appName} icon in the menu bar",
|
||||
"renderer.components.settingsPage.trayIcon.theme": "Icon theme: ",
|
||||
"renderer.components.settingsPage.trayIcon.theme.dark": "Dark",
|
||||
"renderer.components.settingsPage.trayIcon.theme.light": "Light",
|
||||
"renderer.components.settingsPage.trayIcon.theme.systemDefault": "Use system default",
|
||||
|
|
|
@ -41,7 +41,9 @@ jest.mock('main/AutoLauncher', () => ({
|
|||
jest.mock('main/badge', () => ({
|
||||
setUnreadBadgeSetting: jest.fn(),
|
||||
}));
|
||||
jest.mock('main/tray/tray', () => ({}));
|
||||
jest.mock('main/tray/tray', () => ({
|
||||
refreshTrayImages: jest.fn(),
|
||||
}));
|
||||
jest.mock('main/windows/windowManager', () => ({
|
||||
handleUpdateConfig: jest.fn(),
|
||||
sendToRenderer: jest.fn(),
|
||||
|
|
|
@ -67,6 +67,10 @@ export function handleConfigUpdate(newConfig: CombinedConfig) {
|
|||
setLoggingLevel(newConfig.logLevel as LogLevel);
|
||||
|
||||
handleUpdateMenuEvent();
|
||||
if (newConfig.trayIconTheme) {
|
||||
refreshTrayImages(newConfig.trayIconTheme);
|
||||
}
|
||||
|
||||
ipcMain.emit(EMIT_CONFIGURATION, true, newConfig);
|
||||
}
|
||||
|
||||
|
|
193
src/main/tray/tray.test.js
Normal file
193
src/main/tray/tray.test.js
Normal file
|
@ -0,0 +1,193 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {handleConfigUpdate} from 'main/app/config';
|
||||
|
||||
import AutoLauncher from 'main/AutoLauncher';
|
||||
|
||||
import * as tray from './tray';
|
||||
|
||||
jest.mock('path', () => ({
|
||||
join: (a, b) => b,
|
||||
resolve: (a, b, c) => (c || b),
|
||||
}));
|
||||
jest.mock('electron', () => {
|
||||
class NativeImageMock {
|
||||
image;
|
||||
|
||||
constructor(path) {
|
||||
this.image = path;
|
||||
return this;
|
||||
}
|
||||
|
||||
static createFromPath(path) {
|
||||
return new NativeImageMock(path);
|
||||
}
|
||||
|
||||
setTemplateImage = () => jest.fn();
|
||||
}
|
||||
return {
|
||||
app: {
|
||||
getAppPath: () => '/path/to/app',
|
||||
isReady: jest.fn(),
|
||||
setPath: jest.fn(),
|
||||
},
|
||||
ipcMain: {
|
||||
emit: jest.fn(),
|
||||
handle: jest.fn(),
|
||||
on: jest.fn(),
|
||||
},
|
||||
nativeImage: NativeImageMock,
|
||||
nativeTheme: {
|
||||
shouldUseDarkColors: true, // the value doesn't matter
|
||||
},
|
||||
};
|
||||
});
|
||||
jest.mock('main/app/utils', () => ({
|
||||
handleUpdateMenuEvent: jest.fn(),
|
||||
updateSpellCheckerLocales: jest.fn(),
|
||||
updateServerInfos: jest.fn(),
|
||||
setLoggingLevel: jest.fn(),
|
||||
}));
|
||||
jest.mock('main/app/intercom', () => ({
|
||||
handleMainWindowIsShown: jest.fn(),
|
||||
}));
|
||||
jest.mock('main/AutoLauncher', () => ({
|
||||
enable: jest.fn(),
|
||||
disable: jest.fn(),
|
||||
}));
|
||||
jest.mock('main/badge', () => ({
|
||||
setUnreadBadgeSetting: jest.fn(),
|
||||
}));
|
||||
jest.mock('main/windows/windowManager', () => ({
|
||||
handleUpdateConfig: jest.fn(),
|
||||
sendToRenderer: jest.fn(),
|
||||
initializeCurrentServerName: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('main/tray', () => {
|
||||
beforeEach(() => {
|
||||
AutoLauncher.enable.mockResolvedValue({});
|
||||
AutoLauncher.disable.mockResolvedValue({});
|
||||
});
|
||||
describe('config changes', () => {
|
||||
let spy;
|
||||
beforeAll(() => {
|
||||
spy = jest.spyOn(tray, 'refreshTrayImages').mockImplementation();
|
||||
});
|
||||
afterAll(() => {
|
||||
spy.mockRestore();
|
||||
});
|
||||
it('should update the tray icon color immediately when the config is updated', () => {
|
||||
handleConfigUpdate({
|
||||
trayIconTheme: 'light',
|
||||
});
|
||||
expect(tray.refreshTrayImages).toHaveBeenCalledWith('light');
|
||||
});
|
||||
it('should update the tray icon color immediately when the config is updated', () => {
|
||||
handleConfigUpdate({
|
||||
trayIconTheme: 'dark',
|
||||
});
|
||||
expect(tray.refreshTrayImages).toHaveBeenCalledWith('dark');
|
||||
});
|
||||
});
|
||||
|
||||
describe('darwin', () => {
|
||||
const darwinResultAllThemes = {
|
||||
normal: 'osx/menuIcons/MenuIcon16Template.png',
|
||||
unread: 'osx/menuIcons/MenuIconUnread16Template.png',
|
||||
mention: 'osx/menuIcons/MenuIconUnread16Template.png',
|
||||
};
|
||||
const originalPlatform = process.platform;
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'darwin',
|
||||
});
|
||||
const result = tray.refreshTrayImages('light');
|
||||
it.each(Object.keys(result))('match "%s"', (a) => {
|
||||
expect(result[a].image).toBe(darwinResultAllThemes[a]);
|
||||
});
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
});
|
||||
});
|
||||
|
||||
describe('win32 - light', () => {
|
||||
const theme = 'light';
|
||||
const winResultLight = {
|
||||
normal: `windows/tray_${theme}.ico`,
|
||||
unread: `windows/tray_${theme}_unread.ico`,
|
||||
mention: `windows/tray_${theme}_mention.ico`,
|
||||
};
|
||||
const originalPlatform = process.platform;
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'win32',
|
||||
});
|
||||
const result = tray.refreshTrayImages('light');
|
||||
it.each(Object.keys(result))('match "%s"', (a) => {
|
||||
expect(result[a].image).toBe(winResultLight[a]);
|
||||
});
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
});
|
||||
});
|
||||
|
||||
describe('win32 - dark', () => {
|
||||
const theme = 'dark';
|
||||
const winResultDark = {
|
||||
normal: `windows/tray_${theme}.ico`,
|
||||
unread: `windows/tray_${theme}_unread.ico`,
|
||||
mention: `windows/tray_${theme}_mention.ico`,
|
||||
};
|
||||
const originalPlatform = process.platform;
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'win32',
|
||||
});
|
||||
const result = tray.refreshTrayImages('dark');
|
||||
it.each(Object.keys(result))('match "%s"', (a) => {
|
||||
expect(result[a].image).toBe(winResultDark[a]);
|
||||
});
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
});
|
||||
});
|
||||
|
||||
describe('linux - light', () => {
|
||||
const theme = 'light';
|
||||
const linuxResultLight = {
|
||||
normal: `top_bar_${theme}_16.png`,
|
||||
unread: `top_bar_${theme}_unread_16.png`,
|
||||
mention: `top_bar_${theme}_mention_16.png`,
|
||||
};
|
||||
const originalPlatform = process.platform;
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'linux',
|
||||
});
|
||||
const result = tray.refreshTrayImages('light');
|
||||
it.each(Object.keys(result))('match "%s"', (a) => {
|
||||
expect(result[a].image).toBe(linuxResultLight[a]);
|
||||
});
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
});
|
||||
});
|
||||
|
||||
describe('linux - dark', () => {
|
||||
const theme = 'dark';
|
||||
const linuxResultDark = {
|
||||
normal: `top_bar_${theme}_16.png`,
|
||||
unread: `top_bar_${theme}_unread_16.png`,
|
||||
mention: `top_bar_${theme}_mention_16.png`,
|
||||
};
|
||||
const originalPlatform = process.platform;
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: 'linux',
|
||||
});
|
||||
const result = tray.refreshTrayImages('dark');
|
||||
it.each(Object.keys(result))('match "%s"', (a) => {
|
||||
expect(result[a].image).toBe(linuxResultDark[a]);
|
||||
});
|
||||
Object.defineProperty(process, 'platform', {
|
||||
value: originalPlatform,
|
||||
});
|
||||
});
|
||||
});
|
|
@ -74,8 +74,8 @@ export function refreshTrayImages(trayIconTheme: string) {
|
|||
return trayImages;
|
||||
}
|
||||
|
||||
export function setupTray(icontheme: string) {
|
||||
refreshTrayImages(icontheme);
|
||||
export function setupTray(iconTheme: string) {
|
||||
refreshTrayImages(iconTheme);
|
||||
trayIcon = new Tray(trayImages.normal);
|
||||
if (process.platform === 'darwin') {
|
||||
systemPreferences.subscribeNotification('AppleInterfaceThemeChangedNotification', () => {
|
||||
|
|
|
@ -633,7 +633,7 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
options.push(
|
||||
<div
|
||||
style={settingsPage.container}
|
||||
key='containerInputSpellchekerURL'
|
||||
key='containerInputSpellcheckerURL'
|
||||
>
|
||||
<input
|
||||
disabled={!this.state.useSpellChecker}
|
||||
|
@ -855,8 +855,8 @@ class SettingsPage extends React.PureComponent<Props, State> {
|
|||
style={{marginLeft: '20px'}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='renderer.components.settingsPage.trayIcon.theme'
|
||||
defaultMessage='Icon theme: '
|
||||
id='renderer.components.settingsPage.trayIcon.color'
|
||||
defaultMessage='Icon color: '
|
||||
/>
|
||||
{window.process.platform === 'win32' &&
|
||||
<>
|
||||
|
|
Loading…
Reference in a new issue