From 75d2e066731959f35a51b02397e44d54e2d7da49 Mon Sep 17 00:00:00 2001 From: Kiran Niranjan Date: Wed, 1 Aug 2018 14:51:29 +0530 Subject: [PATCH] ELECTRON-591 - Add logic to close up child windows whenever parent window is navigated or reloaded (#446) --- js/mainApiMgr.js | 2 + js/notify/electron-notify.js | 33 ++++++- js/preload/preloadMain.js | 2 +- js/windowMgr.js | 24 ++++- .../spectron/closePopOutsOnReload.spectron.js | 90 +++++++++++++++++++ 5 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 tests/spectron/closePopOutsOnReload.spectron.js diff --git a/js/mainApiMgr.js b/js/mainApiMgr.js index abdc2b7d..b523a34e 100644 --- a/js/mainApiMgr.js +++ b/js/mainApiMgr.js @@ -67,6 +67,8 @@ function sanitize(windowName) { if (!isMac) { eventEmitter.emit('killScreenSnippet'); } + // Closes all the child windows + windowMgr.cleanUpChildWindows(); } } diff --git a/js/notify/electron-notify.js b/js/notify/electron-notify.js index 5fc99bbf..db79078d 100644 --- a/js/notify/electron-notify.js +++ b/js/notify/electron-notify.js @@ -487,7 +487,7 @@ function buildCloseNotification(notificationWindow, notificationObj, getTimeoutI // safety check to prevent from using an // already destroyed notification window - if (notificationWindow.isDestroyed()) { + if (notificationWindow && notificationWindow.isDestroyed()) { return new Promise(function(exitEarly) { exitEarly() }) } @@ -699,6 +699,7 @@ function getWindow() { windowProperties.width = config.width; windowProperties.height = config.height; notificationWindow = new BrowserWindow(windowProperties); + notificationWindow.winName = 'notification-window'; notificationWindow.setVisibleOnAllWorkspaces(true); notificationWindow.loadURL(getTemplatePath()); notificationWindow.webContents.on('did-finish-load', function() { @@ -737,13 +738,39 @@ function cleanUpActiveNotification(event) { */ function cleanUpInactiveWindow() { inactiveWindows.forEach(function(window) { - if (!window.isDestroyed()) { + if (window && !window.isDestroyed()) { window.close(); } }); inactiveWindows = []; } +/** + * Closes all the notification windows + * and cleans up the reference variables + */ +function closeAll() { + resetAnimationQueue(); + const notificationWin = Object.assign([], activeNotifications); + for (let activeNotification of notificationWin) { + if (activeNotification && !activeNotification.isDestroyed()) { + activeNotification.close(); + } + } + + nextInsertPos = {}; + activeNotifications = []; + notificationQueue = []; + cleanUpInactiveWindow(); +} + +/** + * Resets the animation queue instance + */ +function resetAnimationQueue() { + animationQueue = new AnimationQueue(); +} + /** * Start a new timer to close the notification * @param event @@ -784,3 +811,5 @@ ipc.on('electron-notify-mouseover', onMouseOver); module.exports.notify = notify; module.exports.updateConfig = updateConfig; module.exports.reset = setupConfig; +module.exports.closeAll = closeAll; +module.exports.resetAnimationQueue = resetAnimationQueue; diff --git a/js/preload/preloadMain.js b/js/preload/preloadMain.js index f02cb13c..7491451a 100644 --- a/js/preload/preloadMain.js +++ b/js/preload/preloadMain.js @@ -498,7 +498,7 @@ function createAPI() { function sanitize() { local.ipcRenderer.send(apiName, { cmd: apiCmds.sanitize, - windowName: window.name + windowName: window.name || 'main' }); } diff --git a/js/windowMgr.js b/js/windowMgr.js index 4300242c..62583715 100644 --- a/js/windowMgr.js +++ b/js/windowMgr.js @@ -1102,6 +1102,27 @@ function handleKeyPress(keyCode) { } } +/** + * Finds all the child window and closes it + */ +function cleanUpChildWindows() { + const browserWindows = BrowserWindow.getAllWindows(); + notify.resetAnimationQueue(); + if (browserWindows && browserWindows.length) { + browserWindows.forEach(browserWindow => { + // Closes only child windows + if (browserWindow && !browserWindow.isDestroyed() && browserWindow.winName !== 'main') { + // clean up notification windows + if (browserWindow.winName === 'notification-window') { + notify.closeAll(); + } else { + browserWindow.close(); + } + } + }); + } +} + module.exports = { createMainWindow: createMainWindow, @@ -1115,5 +1136,6 @@ module.exports = { verifyDisplays: verifyDisplays, getMenu: getMenu, setIsAutoReload: setIsAutoReload, - handleKeyPress: handleKeyPress + handleKeyPress: handleKeyPress, + cleanUpChildWindows: cleanUpChildWindows, }; diff --git a/tests/spectron/closePopOutsOnReload.spectron.js b/tests/spectron/closePopOutsOnReload.spectron.js new file mode 100644 index 00000000..845cd0b5 --- /dev/null +++ b/tests/spectron/closePopOutsOnReload.spectron.js @@ -0,0 +1,90 @@ +const Application = require('./spectronSetup'); +const path = require('path'); + +let app = new Application({}); + +describe('Tests for pop outs reload scenario', () => { + + let originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; + jasmine.DEFAULT_TIMEOUT_INTERVAL = Application.getTimeOut(); + + beforeAll((done) => { + return app.startApplication().then((startedApp) => { + app = startedApp; + done(); + }).catch((err) => { + console.error(`Unable to start application: ${err}`); + expect(err).toBeNull(); + done(); + }); + }); + + afterAll((done) => { + if (app && app.isRunning()) { + jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout; + app.stop().then(() => { + done(); + }).catch((err) => { + done(); + }); + } + }); + + it('should launch the app', (done) => { + return app.client.waitUntilWindowLoaded().then(() => { + return app.client.getWindowCount().then((count) => { + expect(count === 1).toBeTruthy(); + done(); + }).catch((err) => { + expect(err).toBeNull(); + }); + }).catch((err) => { + expect(err).toBeNull(); + }); + }); + + it('should load the demo page', () => { + return app.client.url('file:///' + path.join(__dirname, '..', '..', 'demo/index.html')); + }); + + it('should open a new window and verify', function (done) { + app.client.waitForExist('#open-win', 2000); + app.client.moveToObject('#open-win', 10, 10); + app.client.leftClick('#open-win', 10, 10); + + setTimeout(() => { + app.client.getWindowCount().then((count) => { + expect(count === 2).toBeTruthy(); + done(); + }); + }, 2000); + }); + + it('should open a child window from pop-out and verify', function (done) { + return app.client.windowByIndex(1).then(() => { + app.client.waitForExist('#open-win', 2000); + app.client.moveToObject('#open-win', 10, 10); + app.client.leftClick('#open-win', 10, 10); + + setTimeout(() => { + app.client.getWindowCount().then((count) => { + expect(count === 3).toBeTruthy(); + done(); + }); + }, 2000); + }); + }); + + it('should close pop-out window when main window is reloaded', function (done) { + return app.client.windowByIndex(0).then(() => { + app.browserWindow.reload(); + + setTimeout(() => { + app.client.getWindowCount().then((count) => { + expect(count === 1).toBeTruthy(); + done(); + }); + }, 2000); + }); + }); +}); \ No newline at end of file