[MM-51871] Migrate mainWindow and settingsWindow to singletons (#2650)

* Migrate mainWindow to singleton

* Migrate settingsWindow to singleton

* PR feedback

* Missed a couple unwrapping cases
This commit is contained in:
Devin Binnie
2023-04-04 10:01:40 -04:00
committed by GitHub
parent c682cf5dd2
commit 22ec280945
46 changed files with 1131 additions and 990 deletions

View File

@@ -4,6 +4,7 @@
import {app, dialog} from 'electron';
import CertificateStore from 'main/certificateStore';
import MainWindow from 'main/windows/mainWindow';
import WindowManager from 'main/windows/windowManager';
import {handleAppWillFinishLaunching, handleAppCertificateError, certificateErrorCallbacks} from 'main/app/app';
@@ -45,13 +46,15 @@ jest.mock('main/i18nManager', () => ({
}));
jest.mock('main/tray/tray', () => ({}));
jest.mock('main/windows/windowManager', () => ({
getMainWindow: jest.fn(),
getViewNameByWebContentsId: jest.fn(),
getServerNameByWebContentsId: jest.fn(),
viewManager: {
views: new Map(),
},
}));
jest.mock('main/windows/mainWindow', () => ({
get: jest.fn(),
}));
describe('main/app/app', () => {
describe('handleAppWillFinishLaunching', () => {
@@ -103,7 +106,7 @@ describe('main/app/app', () => {
const certificate = {};
beforeEach(() => {
WindowManager.getMainWindow.mockReturnValue(mainWindow);
MainWindow.get.mockReturnValue(mainWindow);
WindowManager.getServerNameByWebContentsId.mockReturnValue('test-team');
});

View File

@@ -12,6 +12,7 @@ import CertificateStore from 'main/certificateStore';
import {localizeMessage} from 'main/i18nManager';
import {destroyTray} from 'main/tray/tray';
import WindowManager from 'main/windows/windowManager';
import MainWindow from 'main/windows/mainWindow';
import {getDeeplinkingURL, openDeepLink, resizeScreen} from './utils';
@@ -115,7 +116,7 @@ export async function handleAppCertificateError(event: Event, webContents: WebCo
certificateErrorCallbacks.set(errorID, callback);
// TODO: should we move this to window manager or provide a handler for dialogs?
const mainWindow = WindowManager.getMainWindow();
const mainWindow = MainWindow.get();
if (!mainWindow) {
return;
}

View File

@@ -61,9 +61,11 @@ export function handleConfigUpdate(newConfig: CombinedConfig) {
});
}
updateServerInfos(newConfig.teams);
WindowManager.initializeCurrentServerName();
handleMainWindowIsShown();
if (app.isReady()) {
updateServerInfos(newConfig.teams);
WindowManager.initializeCurrentServerName();
handleMainWindowIsShown();
}
handleUpdateMenuEvent();
if (newConfig.trayIconTheme) {

View File

@@ -9,6 +9,7 @@ import Config from 'common/config';
import urlUtils from 'common/utils/url';
import parseArgs from 'main/ParseArgs';
import MainWindow from 'main/windows/mainWindow';
import WindowManager from 'main/windows/windowManager';
import {initialize} from './initialize';
@@ -138,8 +139,7 @@ jest.mock('main/badge', () => ({
}));
jest.mock('main/certificateManager', () => ({}));
jest.mock('main/CriticalErrorHandler', () => ({
processUncaughtExceptionHandler: jest.fn(),
setMainWindow: jest.fn(),
init: jest.fn(),
}));
jest.mock('main/notifications', () => ({
displayDownloadCompleted: jest.fn(),
@@ -157,13 +157,17 @@ jest.mock('main/UserActivityMonitor', () => ({
startMonitoring: jest.fn(),
}));
jest.mock('main/windows/windowManager', () => ({
getMainWindow: jest.fn(),
showMainWindow: jest.fn(),
sendToMattermostViews: jest.fn(),
sendToRenderer: jest.fn(),
getServerNameByWebContentsId: jest.fn(),
getServerURLFromWebContentsId: jest.fn(),
}));
jest.mock('main/windows/settingsWindow', () => ({
show: jest.fn(),
}));
jest.mock('main/windows/mainWindow', () => ({
get: jest.fn(),
}));
const originalProcess = process;
describe('main/app/initialize', () => {
beforeAll(() => {
@@ -269,7 +273,7 @@ describe('main/app/initialize', () => {
expect(callback).toHaveBeenCalledWith(false);
callback = jest.fn();
WindowManager.getMainWindow.mockReturnValue({webContents: {id: 1}});
MainWindow.get.mockReturnValue({webContents: {id: 1}});
session.defaultSession.setPermissionRequestHandler.mockImplementation((cb) => {
cb({id: 1, getURL: () => 'http://server-1.com'}, 'openExternal', callback);
});

View File

@@ -52,10 +52,12 @@ import CriticalErrorHandler from 'main/CriticalErrorHandler';
import downloadsManager from 'main/downloadsManager';
import i18nManager from 'main/i18nManager';
import parseArgs from 'main/ParseArgs';
import SettingsWindow from 'main/windows/settingsWindow';
import TrustedOriginsStore from 'main/trustedOrigins';
import {refreshTrayImages, setupTray} from 'main/tray/tray';
import UserActivityMonitor from 'main/UserActivityMonitor';
import WindowManager from 'main/windows/windowManager';
import MainWindow from 'main/windows/mainWindow';
import {protocols} from '../../../electron-builder.json';
@@ -105,7 +107,7 @@ export const mainProtocol = protocols?.[0]?.schemes?.[0];
* Main entry point for the application, ensures that everything initializes in the proper order
*/
export async function initialize() {
process.on('uncaughtException', CriticalErrorHandler.processUncaughtExceptionHandler.bind(CriticalErrorHandler));
CriticalErrorHandler.init();
global.willAppQuit = false;
// initialization that can run before the app is ready
@@ -258,7 +260,7 @@ function initializeInterCommunicationEventListeners() {
ipcMain.on(WINDOW_MAXIMIZE, WindowManager.maximize);
ipcMain.on(WINDOW_MINIMIZE, WindowManager.minimize);
ipcMain.on(WINDOW_RESTORE, WindowManager.restore);
ipcMain.on(SHOW_SETTINGS_WINDOW, WindowManager.showSettingsWindow);
ipcMain.on(SHOW_SETTINGS_WINDOW, SettingsWindow.show);
ipcMain.handle(GET_AVAILABLE_SPELL_CHECKER_LANGUAGES, () => session.defaultSession.availableSpellCheckerLanguages);
ipcMain.handle(GET_DOWNLOAD_LOCATION, handleSelectDownload);
ipcMain.on(START_UPDATE_DOWNLOAD, handleStartDownload);
@@ -344,8 +346,6 @@ function initializeAfterAppReady() {
WindowManager.showMainWindow(deeplinkingURL);
CriticalErrorHandler.setMainWindow(WindowManager.getMainWindow()!);
// listen for status updates and pass on to renderer
UserActivityMonitor.on('status', (status) => {
log.debug('Initialize.UserActivityMonitor.on(status)', status);
@@ -396,7 +396,7 @@ function initializeAfterAppReady() {
}
// is the request coming from the renderer?
const mainWindow = WindowManager.getMainWindow();
const mainWindow = MainWindow.get();
if (mainWindow && webContents.id === mainWindow.webContents.id) {
callback(true);
return;

View File

@@ -5,6 +5,7 @@ import Config from 'common/config';
import {getDefaultTeamWithTabsFromTeam} from 'common/tabs/TabView';
import {getLocalURLString, getLocalPreload} from 'main/utils';
import MainWindow from 'main/windows/mainWindow';
import ModalManager from 'main/views/modalManager';
import WindowManager from 'main/windows/windowManager';
@@ -33,10 +34,12 @@ jest.mock('main/views/modalManager', () => ({
addModal: jest.fn(),
}));
jest.mock('main/windows/windowManager', () => ({
getMainWindow: jest.fn(),
switchServer: jest.fn(),
switchTab: jest.fn(),
}));
jest.mock('main/windows/mainWindow', () => ({
get: jest.fn(),
}));
jest.mock('./app', () => ({}));
jest.mock('./utils', () => ({
@@ -111,7 +114,7 @@ describe('main/app/intercom', () => {
beforeEach(() => {
getLocalURLString.mockReturnValue('/some/index.html');
getLocalPreload.mockReturnValue('/some/preload.js');
WindowManager.getMainWindow.mockReturnValue({});
MainWindow.get.mockReturnValue({});
Config.set.mockImplementation((name, value) => {
Config[name] = value;
@@ -150,7 +153,7 @@ describe('main/app/intercom', () => {
beforeEach(() => {
getLocalURLString.mockReturnValue('/some/index.html');
getLocalPreload.mockReturnValue('/some/preload.js');
WindowManager.getMainWindow.mockReturnValue({});
MainWindow.get.mockReturnValue({});
Config.set.mockImplementation((name, value) => {
Config[name] = value;
@@ -193,7 +196,7 @@ describe('main/app/intercom', () => {
beforeEach(() => {
getLocalURLString.mockReturnValue('/some/index.html');
getLocalPreload.mockReturnValue('/some/preload.js');
WindowManager.getMainWindow.mockReturnValue({});
MainWindow.get.mockReturnValue({});
Config.set.mockImplementation((name, value) => {
Config[name] = value;
@@ -242,7 +245,7 @@ describe('main/app/intercom', () => {
beforeEach(() => {
getLocalURLString.mockReturnValue('/some/index.html');
getLocalPreload.mockReturnValue('/some/preload.js');
WindowManager.getMainWindow.mockReturnValue({});
MainWindow.get.mockReturnValue({});
Config.set.mockImplementation((name, value) => {
Config[name] = value;
@@ -263,7 +266,7 @@ describe('main/app/intercom', () => {
it('MM-48079 should not show onboarding screen or server screen if GPO server is pre-configured', () => {
getLocalURLString.mockReturnValue('/some/index.html');
getLocalPreload.mockReturnValue('/some/preload.js');
WindowManager.getMainWindow.mockReturnValue({
MainWindow.get.mockReturnValue({
isVisible: () => true,
});

View File

@@ -15,6 +15,7 @@ import {displayMention} from 'main/notifications';
import {getLocalPreload, getLocalURLString} from 'main/utils';
import ModalManager from 'main/views/modalManager';
import WindowManager from 'main/windows/windowManager';
import MainWindow from 'main/windows/mainWindow';
import {handleAppBeforeQuit} from './app';
import {updateServerInfos} from './utils';
@@ -121,7 +122,7 @@ export function handleMainWindowIsShown() {
* calls of this function will notification re-evaluate the booleans passed to "handleShowOnboardingScreens".
*/
const mainWindow = WindowManager.getMainWindow();
const mainWindow = MainWindow.get();
log.debug('intercom.handleMainWindowIsShown', {configTeams: Config.teams, showWelcomeScreen, showNewServerModal, mainWindow: Boolean(mainWindow)});
if (mainWindow?.isVisible()) {
@@ -140,7 +141,7 @@ export function handleNewServerModal() {
const preload = getLocalPreload('desktopAPI.js');
const mainWindow = WindowManager.getMainWindow();
const mainWindow = MainWindow.get();
if (!mainWindow) {
return;
}
@@ -172,7 +173,7 @@ export function handleEditServerModal(e: IpcMainEvent, name: string) {
const preload = getLocalPreload('desktopAPI.js');
const mainWindow = WindowManager.getMainWindow();
const mainWindow = MainWindow.get();
if (!mainWindow) {
return;
}
@@ -214,7 +215,7 @@ export function handleRemoveServerModal(e: IpcMainEvent, name: string) {
const preload = getLocalPreload('desktopAPI.js');
const mainWindow = WindowManager.getMainWindow();
const mainWindow = MainWindow.get();
if (!mainWindow) {
return;
}
@@ -254,7 +255,7 @@ export function handleWelcomeScreenModal() {
const preload = getLocalPreload('desktopAPI.js');
const mainWindow = WindowManager.getMainWindow();
const mainWindow = MainWindow.get();
if (!mainWindow) {
return;
}
@@ -293,7 +294,7 @@ export function handleOpenAppMenu() {
return;
}
windowMenu.popup({
window: WindowManager.getMainWindow(),
window: MainWindow.get(),
x: 18,
y: 18,
});

View File

@@ -60,6 +60,7 @@ jest.mock('main/server/serverInfo', () => ({
ServerInfo: jest.fn(),
}));
jest.mock('main/tray/tray', () => ({}));
jest.mock('main/windows/mainWindow', () => ({}));
jest.mock('main/windows/windowManager', () => ({}));
jest.mock('./initialize', () => ({

View File

@@ -28,6 +28,7 @@ import {createMenu as createTrayMenu} from 'main/menus/tray';
import {ServerInfo} from 'main/server/serverInfo';
import {setTrayMenu} from 'main/tray/tray';
import WindowManager from 'main/windows/windowManager';
import MainWindow from 'main/windows/mainWindow';
import {mainProtocol} from './initialize';
@@ -140,7 +141,7 @@ export function wasUpdated(lastAppVersion?: string) {
export function clearAppCache() {
// TODO: clear cache on browserviews, not in the renderer.
const mainWindow = WindowManager.getMainWindow();
const mainWindow = MainWindow.get();
if (mainWindow) {
mainWindow.webContents.session.clearCache().then(mainWindow.reload);
} else {