diff --git a/__mocks__/jquery.mjs b/__mocks__/jquery.mjs index a48be3ab1..60665db83 100644 --- a/__mocks__/jquery.mjs +++ b/__mocks__/jquery.mjs @@ -14,3 +14,6 @@ window.matchMedia = window.matchMedia || function() removeListener: function() {} }; }; + +// Mocking requestAnimationFrame since it's not usually defined but we use it +global.requestAnimationFrame = callback => callback(); diff --git a/__tests__/__main__/main-window.mjs b/__tests__/__main__/main-window.mjs index 06c278887..69df18f53 100644 --- a/__tests__/__main__/main-window.mjs +++ b/__tests__/__main__/main-window.mjs @@ -47,17 +47,21 @@ describe('main-window.mjs', () => assert.strictEqual(getLeaveByInterval(), null); }); - it('Should get window', () => + it('Should get window', (done) => { createWindow(); - assert.strictEqual(showSpy.calledOnce, true); assert.strictEqual(getMainWindow() instanceof BrowserWindow, true); + getMainWindow().webContents.ipc.on(IpcConstants.WindowReadyToShow, () => + { + assert.strictEqual(showSpy.calledOnce, true); + done(); + }); }); }); describe('createWindow()', () => { - it('Should create and get window default behaviour', () => + it('Should create and get window default behaviour', (done) => { const loadFileSpy = spy(BrowserWindow.prototype, 'loadFile'); createWindow(); @@ -73,9 +77,13 @@ describe('main-window.mjs', () => assert.strictEqual(mainWindow.listenerCount('minimize'), 2); assert.strictEqual(mainWindow.listenerCount('close'), 2); assert.strictEqual(loadFileSpy.calledOnce, true); - assert.strictEqual(showSpy.calledOnce, true); assert.notStrictEqual(getLeaveByInterval(), null); assert.strictEqual(getLeaveByInterval()._idleNext.expiry > 0, true); + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => + { + assert.strictEqual(showSpy.calledOnce, true); + done(); + }); }); }); @@ -88,7 +96,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', async() => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, async() => { // Wait a bit for values to accomodate await new Promise(res => setTimeout(res, 500)); @@ -114,7 +122,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', async() => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, async() => { // Wait a bit for values to accomodate await new Promise(res => setTimeout(res, 500)); @@ -144,7 +152,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', async() => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, async() => { // Wait a bit for values to accomodate await new Promise(res => setTimeout(res, 500)); @@ -170,7 +178,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', () => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => { stub(Notification, 'createLeaveNotification').callsFake(() => { @@ -200,7 +208,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', () => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => { const now = new Date(); ipcMain.emit( @@ -223,7 +231,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', () => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => { showSpy.callsFake(() => { @@ -245,7 +253,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', () => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => { const trayStub = stub(global.tray, 'popUpContextMenu').callsFake(() => { @@ -272,7 +280,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', () => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => { mainWindow.emit('minimize', { preventDefault: () => {} @@ -295,7 +303,7 @@ describe('main-window.mjs', () => */ const mainWindow = getMainWindow(); const minimizeSpy = spy(mainWindow, 'minimize'); - mainWindow.on('ready-to-show', () => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => { mainWindow.emit('minimize', {}); assert.strictEqual(minimizeSpy.called, true); @@ -318,7 +326,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', () => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => { mainWindow.emit('close', { preventDefault: () => {} @@ -341,7 +349,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', () => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => { // Force the exit mainWindow.on('close', () => @@ -396,7 +404,7 @@ describe('main-window.mjs', () => * @type {BrowserWindow} */ const mainWindow = getMainWindow(); - mainWindow.on('ready-to-show', () => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => { mainWindow.emit('close', { preventDefault: () => {} @@ -422,7 +430,7 @@ describe('main-window.mjs', () => clock.restore(); done(); }); - mainWindow.on('ready-to-show', () => + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => { mainWindow.emit('close', { preventDefault: () => {} diff --git a/__tests__/__main__/windows.mjs b/__tests__/__main__/windows.mjs index 314b8a0aa..ba2118010 100644 --- a/__tests__/__main__/windows.mjs +++ b/__tests__/__main__/windows.mjs @@ -1,10 +1,11 @@ 'use strict'; import assert from 'assert'; -import { BrowserWindow } from 'electron'; -import { stub } from 'sinon'; +import { BrowserWindow, ipcMain } from 'electron'; +import { spy, stub } from 'sinon'; import { getDateStr } from '../../js/date-aux.mjs'; +import IpcConstants from '../../js/ipc-constants.mjs'; import Windows from '../../js/windows.mjs'; describe('Windows tests', () => @@ -14,9 +15,36 @@ describe('Windows tests', () => before(() => { // Avoid window being shown - // TODO: might not always be working? showSpy = stub(BrowserWindow.prototype, 'show'); - loadSpy = stub(BrowserWindow.prototype, 'loadURL'); + loadSpy = spy(BrowserWindow.prototype, 'loadURL'); + + // Mocking for tests below + ipcMain.handle(IpcConstants.GetWaiverDay, () => + { + return new Promise((resolve) => + { + resolve(global.waiverDay); + }); + }); + ipcMain.removeHandler(IpcConstants.GetLanguageData); + ipcMain.handle(IpcConstants.GetLanguageData, () => ({ + 'language': 'en', + 'data': { + 'translation': { + '$Preferences': { + 'hideNonWorkingDay': '' + } + } + } + })); + ipcMain.handle(IpcConstants.GetWaiverStoreContents, () => + { + return new Promise(resolve => resolve({})); + }); + ipcMain.handle(IpcConstants.GetCountries, () => + { + return new Promise(resolve => resolve([])); + }); }); it('Elements should be null on starting', () => @@ -24,7 +52,7 @@ describe('Windows tests', () => assert.strictEqual(Windows.getWaiverWindow(), null); assert.strictEqual(global.tray, null); assert.strictEqual(global.contextMenu, null); - assert.strictEqual(global.prefWindow, null); + assert.strictEqual(Windows.getPreferencesWindow(), null); }); it('Should create waiver window', (done) => @@ -41,24 +69,41 @@ describe('Windows tests', () => assert.strictEqual(Math.abs(size[0] - 600) < 10, true); assert.strictEqual(Math.abs(size[1] - 500) < 10, true); - assert.strictEqual(showSpy.calledOnce, true); assert.strictEqual(loadSpy.calledOnce, true); - done(); + Windows.getWaiverWindow().webContents.ipc.on(IpcConstants.WindowReadyToShow, () => + { + assert.strictEqual(showSpy.calledOnce, true); + done(); + }); }); - it('Should show waiver window it has been created', (done) => + it('Should show waiver window when it has been created', (done) => { const mainWindow = new BrowserWindow({ show: false }); + let firstShow = true; + showSpy.callsFake(() => + { + if (firstShow) + { + firstShow = false; + Windows.openWaiverManagerWindow(mainWindow); + } + else + { + assert.notStrictEqual(Windows.getWaiverWindow(), null); + + // It should only load once the URL because it already exists + assert.strictEqual(loadSpy.calledOnce, true); + assert.strictEqual(showSpy.calledTwice, true); + showSpy.restore(); + showSpy = stub(BrowserWindow.prototype, 'show'); + done(); + } + }); Windows.openWaiverManagerWindow(mainWindow); - Windows.openWaiverManagerWindow(mainWindow); - assert.notStrictEqual(Windows.getWaiverWindow(), null); - // It should only load once the URL because it already exists - assert.strictEqual(showSpy.calledTwice, true); - assert.strictEqual(loadSpy.calledOnce, true); - done(); }); it('Should set global waiverDay when event is sent', (done) => @@ -67,19 +112,101 @@ describe('Windows tests', () => show: false }); Windows.openWaiverManagerWindow(mainWindow, true); - assert.notStrictEqual(Windows.getWaiverWindow(), null); - assert.strictEqual(global.waiverDay, getDateStr(new Date())); - done(); + Windows.getWaiverWindow().webContents.ipc.on(IpcConstants.WindowReadyToShow, () => + { + assert.strictEqual(showSpy.calledOnce, true); + assert.notStrictEqual(Windows.getWaiverWindow(), null); + assert.strictEqual(global.waiverDay, getDateStr(new Date())); + done(); + }); }); - it('Should reset waiverWindow on close', () => + it('Should reset waiverWindow on close', (done) => { const mainWindow = new BrowserWindow({ show: false }); Windows.openWaiverManagerWindow(mainWindow, true); - Windows.getWaiverWindow().close(); - assert.strictEqual(Windows.getWaiverWindow(), null); + Windows.getWaiverWindow().webContents.ipc.on(IpcConstants.WindowReadyToShow, () => + { + assert.strictEqual(showSpy.calledOnce, true); + Windows.getWaiverWindow().close(); + assert.strictEqual(Windows.getWaiverWindow(), null); + done(); + }); + }); + + it('Should create preferences window', function(done) + { + // For some reason this test takes longer in the CI for windows-latest. + // The last requestAnimationFrame() call inside preferences.js has been taking ~2s. + this.timeout(5000); + + const mainWindow = new BrowserWindow({ + show: false + }); + + showSpy.callsFake(() => + { + assert.notStrictEqual(Windows.getPreferencesWindow(), null); + assert.strictEqual(Windows.getPreferencesWindow() instanceof BrowserWindow, true); + + // Values can vary about 10px from 600, 500 + const size = Windows.getPreferencesWindow().getSize(); + assert.strictEqual(Math.abs(size[0] - 550) < 10, true); + assert.strictEqual(Math.abs(size[1] - 620) < 10, true); + + assert.strictEqual(loadSpy.calledOnce, true); + + showSpy.restore(); + showSpy = stub(BrowserWindow.prototype, 'show'); + done(); + }); + + Windows.openPreferencesWindow(mainWindow); + }); + + it('Should show preferences window when it has been created', (done) => + { + const mainWindow = new BrowserWindow({ + show: false + }); + let firstShow = true; + showSpy.callsFake(() => + { + if (firstShow) + { + firstShow = false; + Windows.openPreferencesWindow(mainWindow); + } + else + { + assert.notStrictEqual(Windows.getPreferencesWindow(), null); + + // It should only load once the URL because it already exists + assert.strictEqual(loadSpy.calledOnce, true); + assert.strictEqual(showSpy.calledTwice, true); + showSpy.restore(); + showSpy = stub(BrowserWindow.prototype, 'show'); + done(); + } + }); + Windows.openPreferencesWindow(mainWindow); + }); + + it('Should reset preferences window on close', (done) => + { + const mainWindow = new BrowserWindow({ + show: false + }); + Windows.openPreferencesWindow(mainWindow, true); + Windows.getPreferencesWindow().webContents.ipc.on(IpcConstants.WindowReadyToShow, () => + { + assert.strictEqual(showSpy.calledOnce, true); + Windows.getPreferencesWindow().close(); + assert.strictEqual(Windows.getPreferencesWindow(), null); + done(); + }); }); it('Should get dialog coordinates', () => @@ -109,5 +236,10 @@ describe('Windows tests', () => { showSpy.restore(); loadSpy.restore(); + + ipcMain.removeHandler(IpcConstants.GetWaiverDay); + ipcMain.removeHandler(IpcConstants.GetLanguageData); + ipcMain.removeHandler(IpcConstants.GetWaiverStoreContents); + ipcMain.removeHandler(IpcConstants.GetCountries); }); -}); \ No newline at end of file +}); diff --git a/__tests__/__renderer__/preferences.mjs b/__tests__/__renderer__/preferences.mjs index 60f94c275..a6008ca39 100644 --- a/__tests__/__renderer__/preferences.mjs +++ b/__tests__/__renderer__/preferences.mjs @@ -105,7 +105,8 @@ describe('Test Preferences Window', () => })); }, getOriginalUserPreferences: () => { return testPreferences; }, - showDialog: () => { return new Promise((resolve) => resolve({ response: 0 })); } + notifyWindowReadyToShow: () => {}, + showDialog: () => { return new Promise((resolve) => resolve({ response: 0 })); }, }; // Stub methods diff --git a/__tests__/__renderer__/workday-waiver-aux.mjs b/__tests__/__renderer__/workday-waiver-aux.mjs index bdb6562ff..7b5b2adb6 100644 --- a/__tests__/__renderer__/workday-waiver-aux.mjs +++ b/__tests__/__renderer__/workday-waiver-aux.mjs @@ -3,22 +3,59 @@ import '../../__mocks__/jquery.mjs'; import assert from 'assert'; +import { BrowserWindow, ipcMain } from 'electron'; +import { stub } from 'sinon'; import { formatDayId, displayWaiverWindow } from '../../renderer/workday-waiver-aux.js'; +import IpcConstants from '../../js/ipc-constants.mjs'; +import Windows from '../../js/windows.mjs'; const window_backup = global.window; describe('Workday Waiver Aux', function() { + let showStub; + let parentWindow; before(() => { + showStub = stub(BrowserWindow.prototype, 'show'); + + parentWindow = new BrowserWindow({ + show: false}); + // Mocking call - // TODO: find a better way to mock this or even really test it + // TODO: find a better way to mock this or even really test it, we're just copying the IPC implementation here global.window = { calendarApi: { - displayWaiverWindow: () => {} + displayWaiverWindow: (waiverDay) => + { + global.waiverDay = waiverDay; + Windows.openWaiverManagerWindow(parentWindow); + } } }; + + // Mocking for tests below + ipcMain.handle(IpcConstants.GetWaiverDay, () => + { + return new Promise((resolve) => + { + resolve(global.waiverDay); + }); + }); + ipcMain.removeHandler(IpcConstants.GetLanguageData); + ipcMain.handle(IpcConstants.GetLanguageData, () => ({ + 'language': 'en', + 'data': {} + })); + ipcMain.handle(IpcConstants.GetWaiverStoreContents, () => + { + return new Promise(resolve => resolve({})); + }); + ipcMain.handle(IpcConstants.GetCountries, () => + { + return new Promise(resolve => resolve([])); + }); }); const validJSDay = '2020-03-10'; @@ -43,18 +80,56 @@ describe('Workday Waiver Aux', function() describe('displayWaiverWindow(dayId)', function() { - it('should do seamless call', async() => + it('should do seamless call 1', (done) => { - await displayWaiverWindow(validJSDay); - await displayWaiverWindow(validJSDay2); - await displayWaiverWindow(garbageString); - await displayWaiverWindow(incompleteDate); + displayWaiverWindow(validJSDay); + Windows.getWaiverWindow().webContents.ipc.once(IpcConstants.WindowReadyToShow, () => + { + Windows.getWaiverWindow().close(); + done(); + }); + }); + + it('should do seamless call 2', (done) => + { + displayWaiverWindow(validJSDay2); + Windows.getWaiverWindow().webContents.ipc.once(IpcConstants.WindowReadyToShow, () => + { + Windows.getWaiverWindow().close(); + done(); + }); + }); + + it('should do seamless call 3', (done) => + { + displayWaiverWindow(garbageString); + Windows.getWaiverWindow().webContents.ipc.once(IpcConstants.WindowReadyToShow, () => + { + Windows.getWaiverWindow().close(); + done(); + }); + }); + + it('should do seamless call 4', (done) => + { + displayWaiverWindow(incompleteDate); + Windows.getWaiverWindow().webContents.ipc.once(IpcConstants.WindowReadyToShow, () => + { + Windows.getWaiverWindow().close(); + done(); + }); }); }); after(() => { + showStub.restore(); global.window = window_backup; + + ipcMain.removeHandler(IpcConstants.GetWaiverDay); + ipcMain.removeHandler(IpcConstants.GetLanguageData); + ipcMain.removeHandler(IpcConstants.GetWaiverStoreContents); + ipcMain.removeHandler(IpcConstants.GetCountries); }); // TODO: Come up with a way to test displayWaiverWindow's opening of a window diff --git a/__tests__/__renderer__/workday-waiver.mjs b/__tests__/__renderer__/workday-waiver.mjs index 024ce0e61..fb42b07a7 100644 --- a/__tests__/__renderer__/workday-waiver.mjs +++ b/__tests__/__renderer__/workday-waiver.mjs @@ -189,6 +189,7 @@ describe('Test Workday Waiver Window', function() return getUserPreferences(); }; window.rendererApi.showDay = showDay; + window.rendererApi.notifyWindowReadyToShow = () => {}; window.workdayWaiverApi.showDialogSync = () => {}; diff --git a/js/ipc-constants.mjs b/js/ipc-constants.mjs index e21b00b55..d79261221 100644 --- a/js/ipc-constants.mjs +++ b/js/ipc-constants.mjs @@ -32,6 +32,7 @@ const IpcConstants = Object.freeze( SwitchView: 'SWITCH_VIEW', ToggleTrayPunchTime: 'TOGGLE_TRAY_PUNCH_TIME', WaiverSaved: 'WAIVER_SAVED', + WindowReadyToShow: 'WINDOW_READY_TO_SHOW', }); export default IpcConstants; diff --git a/js/main-window.mjs b/js/main-window.mjs index 97c62d9b8..049277aab 100644 --- a/js/main-window.mjs +++ b/js/main-window.mjs @@ -93,9 +93,6 @@ function createWindow() createMenu(); - // Prevents flickering from maximize - mainWindow.show(); - // and load the main html of the app as the default window mainWindow.loadFile(path.join(rootDir, 'src/calendar.html')); @@ -157,6 +154,12 @@ function createWindow() } }); + // Prevents flickering from maximize + mainWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => + { + mainWindow.show(); + }); + // Emitted when the window is closed. mainWindow.on('close', (event) => { diff --git a/js/menus.mjs b/js/menus.mjs index c8116e1dc..a0d243511 100644 --- a/js/menus.mjs +++ b/js/menus.mjs @@ -2,15 +2,12 @@ import { app, BrowserWindow, clipboard, dialog, shell } from 'electron'; import Store from 'electron-store'; -import path from 'path'; -import { appConfig, getDetails, rootDir } from './app-config.mjs'; +import { appConfig, getDetails } from './app-config.mjs'; import { getCurrentDateTimeStr } from './date-aux.mjs'; import ImportExport from './import-export.mjs'; import Notification from './notification.mjs'; -import { getSavedPreferences } from './saved-preferences.mjs'; import UpdateManager from './update-manager.mjs'; -import { getUserPreferences, savePreferences } from './user-preferences.mjs'; import Windows from './windows.mjs'; import i18NextConfig from '../src/configs/i18next.config.mjs'; import IpcConstants from './ipc-constants.mjs'; @@ -129,51 +126,7 @@ function getEditMenuTemplate(mainWindow) accelerator: appConfig.macOS ? 'Command+,' : 'Control+,', click() { - if (global.prefWindow !== null) - { - global.prefWindow.show(); - return; - } - - const htmlPath = path.join('file://', rootDir, 'src/preferences.html'); - const dialogCoordinates = Windows.getDialogCoordinates(550, 620, mainWindow); - const userPreferences = getUserPreferences(); - global.prefWindow = new BrowserWindow({ width: 550, - height: 620, - minWidth: 480, - x: dialogCoordinates.x, - y: dialogCoordinates.y, - parent: mainWindow, - resizable: true, - icon: appConfig.iconpath, - webPreferences: { - nodeIntegration: true, - preload: path.join(rootDir, '/renderer/preload-scripts/preferences-bridge.mjs'), - contextIsolation: true, - additionalArguments: [ - `--preferences=${JSON.stringify(userPreferences)}`, - ], - } }); - global.prefWindow.setMenu(null); - global.prefWindow.loadURL(htmlPath); - global.prefWindow.show(); - global.prefWindow.on('close', function() - { - global.prefWindow = null; - const savedPreferences = getSavedPreferences(); - if (savedPreferences !== null) - { - savePreferences(savedPreferences); - mainWindow.webContents.send(IpcConstants.PreferencesSaved, savedPreferences); - } - }); - global.prefWindow.webContents.on('before-input-event', (event, input) => - { - if (input.control && input.shift && input.key.toLowerCase() === 'i') - { - BrowserWindow.getFocusedWindow().webContents.toggleDevTools(); - } - }); + Windows.openPreferencesWindow(mainWindow); } }, { type: 'separator' }, diff --git a/js/windows.mjs b/js/windows.mjs index 2dac285aa..72d86b306 100644 --- a/js/windows.mjs +++ b/js/windows.mjs @@ -5,7 +5,8 @@ import path from 'path'; import { appConfig, rootDir } from './app-config.mjs'; import { getDateStr } from './date-aux.mjs'; -import { getUserPreferences } from './user-preferences.mjs'; +import { getSavedPreferences } from './saved-preferences.mjs'; +import { getUserPreferences, savePreferences } from './user-preferences.mjs'; import IpcConstants from './ipc-constants.mjs'; // Keep a global reference of the window object, if you don't, the window will @@ -39,6 +40,7 @@ class Windows y: dialogCoordinates.y, parent: mainWindow, resizable: true, + show: false, icon: appConfig.iconpath, webPreferences: { nodeIntegration: true, @@ -50,7 +52,10 @@ class Windows } }); global.waiverWindow.setMenu(null); global.waiverWindow.loadURL(htmlPath); - global.waiverWindow.show(); + global.waiverWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => + { + global.waiverWindow.show(); + }); global.waiverWindow.on('close', function() { global.waiverWindow = null; @@ -65,6 +70,59 @@ class Windows }); } + static openPreferencesWindow(mainWindow) + { + if (global.prefWindow !== null) + { + global.prefWindow.show(); + return; + } + + const htmlPath = path.join('file://', rootDir, 'src/preferences.html'); + const dialogCoordinates = Windows.getDialogCoordinates(550, 620, mainWindow); + const userPreferences = getUserPreferences(); + global.prefWindow = new BrowserWindow({ width: 550, + height: 620, + minWidth: 480, + x: dialogCoordinates.x, + y: dialogCoordinates.y, + parent: mainWindow, + show: false, + resizable: true, + icon: appConfig.iconpath, + webPreferences: { + nodeIntegration: true, + preload: path.join(rootDir, '/renderer/preload-scripts/preferences-bridge.mjs'), + contextIsolation: true, + additionalArguments: [ + `--preferences=${JSON.stringify(userPreferences)}`, + ], + } }); + global.prefWindow.setMenu(null); + global.prefWindow.loadURL(htmlPath); + global.prefWindow.webContents.ipc.on(IpcConstants.WindowReadyToShow, () => + { + global.prefWindow.show(); + }); + global.prefWindow.on('close', function() + { + global.prefWindow = null; + const savedPreferences = getSavedPreferences(); + if (savedPreferences !== null) + { + savePreferences(savedPreferences); + mainWindow.webContents.send(IpcConstants.PreferencesSaved, savedPreferences); + } + }); + global.prefWindow.webContents.on('before-input-event', (event, input) => + { + if (input.control && input.shift && input.key.toLowerCase() === 'i') + { + BrowserWindow.getFocusedWindow().webContents.toggleDevTools(); + } + }); + } + /** * Return the x and y coordinate for a dialog window, * so the dialog window is centered on the TTL window. @@ -86,6 +144,11 @@ class Windows return global.waiverWindow; } + static getPreferencesWindow() + { + return global.prefWindow; + } + static resetWindowsElements() { global.waiverWindow = null; diff --git a/renderer/preload-scripts/renderer-api.mjs b/renderer/preload-scripts/renderer-api.mjs index 01403ce87..57f0a1efc 100644 --- a/renderer/preload-scripts/renderer-api.mjs +++ b/renderer/preload-scripts/renderer-api.mjs @@ -13,7 +13,6 @@ function getLanguageDataPromise() function getOriginalUserPreferences() { const preferences = process.argv.filter((arg) => arg.startsWith('--preferences='))[0]?.split('=')?.[1]; - console.log(preferences); return JSON.parse(preferences || '{}'); } @@ -22,6 +21,11 @@ function getWaiverStoreContents() return ipcRenderer.invoke(IpcConstants.GetWaiverStoreContents); } +function notifyWindowReadyToShow() +{ + ipcRenderer.send(IpcConstants.WindowReadyToShow); +} + function showDialog(dialogOptions) { return ipcRenderer.invoke(IpcConstants.ShowDialog, dialogOptions); @@ -31,6 +35,7 @@ const rendererApi = { getLanguageDataPromise, getOriginalUserPreferences, getWaiverStoreContents, + notifyWindowReadyToShow, showDay, showDialog, }; diff --git a/src/calendar.js b/src/calendar.js index e4f32f7d8..4b04620d0 100644 --- a/src/calendar.js +++ b/src/calendar.js @@ -74,5 +74,15 @@ window.calendarApi.handleLeaveBy(searchLeaveByElement); $(() => { const preferences = window.rendererApi.getOriginalUserPreferences(); - setupCalendar(preferences); + requestAnimationFrame(() => + { + setupCalendar(preferences); + requestAnimationFrame(() => + { + setTimeout(() => + { + window.rendererApi.notifyWindowReadyToShow(); + }, 100); + }); + }); }); diff --git a/src/preferences.js b/src/preferences.js index d9dfa7199..f83f01c12 100644 --- a/src/preferences.js +++ b/src/preferences.js @@ -102,7 +102,7 @@ function convertTimeFormat(entry) return entry; } -function renderPreferencesWindow() +function renderWindowTheme() { // Theme-handling should be towards the top. Applies theme early so it's more natural. const theme = 'theme'; @@ -117,7 +117,10 @@ function renderPreferencesWindow() .val(); preferences[theme] = selectedThemeOption; applyTheme(selectedThemeOption); +} +function renderPreferencesWindow() +{ /* istanbul ignore else */ if ('view' in preferences) { @@ -262,6 +265,17 @@ function setupListeners() $(() => { preferences = window.rendererApi.getOriginalUserPreferences(); + requestAnimationFrame(() => + { + renderWindowTheme(); + requestAnimationFrame(() => + { + setTimeout(() => + { + window.rendererApi.notifyWindowReadyToShow(); + }, 100); + }); + }); renderPreferencesWindow(); setupListeners(); setupLanguages(); diff --git a/src/workday-waiver.js b/src/workday-waiver.js index 7a71dc83c..fabe610ae 100644 --- a/src/workday-waiver.js +++ b/src/workday-waiver.js @@ -441,7 +441,18 @@ async function initializeHolidayInfo() $(async() => { userPreferences = window.rendererApi.getOriginalUserPreferences(); - applyTheme(userPreferences.theme); + + requestAnimationFrame(() => + { + applyTheme(userPreferences.theme); + requestAnimationFrame(() => + { + setTimeout(() => + { + window.rendererApi.notifyWindowReadyToShow(); + }, 100); + }); + }); const waiverDay = await window.workdayWaiverApi.getWaiverDay(); languageData = await window.rendererApi.getLanguageDataPromise();