From 12ef49e4f608324ffb5982ff4435623b43ece6f2 Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Thu, 1 Oct 2020 20:15:01 -0700 Subject: [PATCH] fix: Window state loading (#1758) * Remove unused typings * Fix app state hydratation * Use auxiliar function to export localStorage to main process * Apply initial window state earlier * Trick server-url handler to ignore unregistered webviews --- src/app/main/data.ts | 8 ------ src/app/main/persistence.ts | 8 +----- src/main.ts | 16 ++++------- src/types/electron-reloader.d.ts | 5 ---- src/ui/common.ts | 4 +-- src/ui/main/rootWindow.ts | 43 +++++++++++++++++++++++++----- src/ui/main/webviews.ts | 4 ++- src/ui/reducers/rootWindowState.ts | 9 ++++--- 8 files changed, 53 insertions(+), 44 deletions(-) delete mode 100644 src/types/electron-reloader.d.ts diff --git a/src/app/main/data.ts b/src/app/main/data.ts index 4b7fc03b86..f0e18a4ccf 100644 --- a/src/app/main/data.ts +++ b/src/app/main/data.ts @@ -4,18 +4,10 @@ import path from 'path'; import { app } from 'electron'; import { select, dispatch, watch } from '../../store'; -import { getRootWindow } from '../../ui/main/rootWindow'; import { APP_SETTINGS_LOADED } from '../actions'; import { selectPersistableValues } from '../selectors'; import { getPersistedValues, persistValues } from './persistence'; -export const getLocalStorage = (): Promise> => - getRootWindow().webContents.executeJavaScript('({...localStorage})'); - -export const purgeLocalStorage = async (): Promise => { - await getRootWindow().webContents.executeJavaScript('localStorage.clear()'); -}; - export const mergePersistableValues = async (localStorage: Record): Promise => { const initialValues = select(selectPersistableValues); diff --git a/src/app/main/persistence.ts b/src/app/main/persistence.ts index 4077295d4e..ec85dcc679 100644 --- a/src/app/main/persistence.ts +++ b/src/app/main/persistence.ts @@ -21,13 +21,7 @@ const getElectronStore = (): ElectronStore => { }; export const getPersistedValues = (): PersistableValues => - selectPersistableValues( - Object.fromEntries( - Array.from( - getElectronStore(), - ), - ), - ); + getElectronStore().store; export const persistValues = (values: PersistableValues): void => { getElectronStore().set(values); diff --git a/src/main.ts b/src/main.ts index 935e9f2ea8..ac3a363586 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,9 +2,7 @@ import { app } from 'electron'; import { performElectronStartup, setupApp } from './app/main/app'; import { - getLocalStorage, mergePersistableValues, - purgeLocalStorage, watchAndPersistChanges, } from './app/main/data'; import { setUserDataDirectory } from './app/main/dev'; @@ -21,8 +19,8 @@ import dock from './ui/main/dock'; import menuBar from './ui/main/menuBar'; import { createRootWindow, - applyRootWindowState, showRootWindow, + exportLocalStorage, } from './ui/main/rootWindow'; import touchBar from './ui/main/touchBar'; import trayIcon from './ui/main/trayIcon'; @@ -39,8 +37,11 @@ const start = async (): Promise => { await app.whenReady(); - i18n.setUp(); + const localStorage = await exportLocalStorage(); + await mergePersistableValues(localStorage); + await setupServers(localStorage); + i18n.setUp(); await i18n.wait(); const rootWindow = createRootWindow(); @@ -58,10 +59,6 @@ const start = async (): Promise => { setupNotifications(); setupScreenSharing(); - const localStorage = await getLocalStorage(); - - await mergePersistableValues(localStorage); - await setupServers(localStorage); await setupSpellChecking(); setupDeepLinks(); @@ -81,9 +78,6 @@ const start = async (): Promise => { trayIcon.tearDown(); }); - applyRootWindowState(); - - await purgeLocalStorage(); watchAndPersistChanges(); await processDeepLinksInArgs(); diff --git a/src/types/electron-reloader.d.ts b/src/types/electron-reloader.d.ts deleted file mode 100644 index 6e12404281..0000000000 --- a/src/types/electron-reloader.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module 'electron-reloader' { - function setupElectronReloader(module: NodeJS.Module, options?: Record): void; - - export = setupElectronReloader; -} diff --git a/src/ui/common.ts b/src/ui/common.ts index 657650af63..e02b88f2a8 100644 --- a/src/ui/common.ts +++ b/src/ui/common.ts @@ -15,8 +15,8 @@ export type WindowState = { fullscreen: boolean; normal: boolean; bounds: { - x: number | undefined, - y: number | undefined, + x?: number, + y?: number, width: number, height: number, } diff --git a/src/ui/main/rootWindow.ts b/src/ui/main/rootWindow.ts index 88d550eaa6..daaa429a8a 100644 --- a/src/ui/main/rootWindow.ts +++ b/src/ui/main/rootWindow.ts @@ -7,6 +7,7 @@ import { screen, Rectangle, NativeImage, + WebPreferences, } from 'electron'; import i18next from 'i18next'; import { createStructuredSelector } from 'reselect'; @@ -25,6 +26,14 @@ import { } from '../selectors'; import { getTrayIconPath } from './icons'; + +const webPreferences: WebPreferences = { + nodeIntegration: true, + nodeIntegrationInSubFrames: true, + webviewTag: true, + worldSafeExecuteJavaScript: true, +}; + const selectRootWindowState = ({ rootWindowState }: RootState): WindowState => rootWindowState ?? { bounds: { x: 0, @@ -54,12 +63,7 @@ export const createRootWindow = (): BrowserWindow => { titleBarStyle: 'hidden', backgroundColor: '#2f343d', show: false, - webPreferences: { - nodeIntegration: true, - nodeIntegrationInSubFrames: true, - webviewTag: true, - worldSafeExecuteJavaScript: true, - }, + webPreferences, }); rootWindow.addListener('close', (event) => { @@ -298,8 +302,35 @@ export const showRootWindow = async (rootWindow: BrowserWindow): Promise = return new Promise((resolve) => { rootWindow.addListener('ready-to-show', () => { + applyRootWindowState(); setupRootWindow(); resolve(); }); }); }; + +export const exportLocalStorage = async (): Promise> => { + try { + const tempWindow = new BrowserWindow({ + show: false, + webPreferences, + }); + + tempWindow.loadFile(path.join(app.getAppPath(), 'app/index.html')); + + await new Promise((resolve) => { + tempWindow.addListener('ready-to-show', () => { + resolve(); + }); + }); + + return tempWindow.webContents.executeJavaScript(`(() => { + const data = ({...localStorage}) + localStorage.clear(); + return data; + })()`); + } catch (error) { + console.error(error); + return {}; + } +}; diff --git a/src/ui/main/webviews.ts b/src/ui/main/webviews.ts index d29147eaa0..5995b1c7c0 100644 --- a/src/ui/main/webviews.ts +++ b/src/ui/main/webviews.ts @@ -468,6 +468,8 @@ export const attachGuestWebContentsEvents = (rootWindow: BrowserWindow): void => ipcMain.handle( 'server-url', (event) => - Array.from(webContentsByServerUrl.entries()).find(([, v]) => v === event.sender)[0], + Array.from(webContentsByServerUrl.entries()) + .filter(([, v]) => v === event.sender) + .map(([k]) => k)[0], ); }; diff --git a/src/ui/reducers/rootWindowState.ts b/src/ui/reducers/rootWindowState.ts index 7e986903f2..a135a23d6d 100644 --- a/src/ui/reducers/rootWindowState.ts +++ b/src/ui/reducers/rootWindowState.ts @@ -29,10 +29,11 @@ export const rootWindowState: Reducer = (sta return action.payload; case APP_SETTINGS_LOADED: { - const { rootWindowState: mainWindowState = state } = action.payload; - return mainWindowState; + const { rootWindowState = state } = action.payload; + return rootWindowState; } - } - return state; + default: + return state; + } };