fix(electron): use dynamic load for exposed meta (#5251)

There is high possibilities of  circular dependencies when importing `exposed-meta` module. Change it to dynamic import to mitigate the issue..
This commit is contained in:
Peng Xiao
2023-12-13 05:17:17 +00:00
parent c9f900b69c
commit 31dc1f5e00
4 changed files with 56 additions and 41 deletions

View File

@@ -5,7 +5,7 @@ import { type App, type BrowserWindow, ipcMain } from 'electron';
import { buildType, CLOUD_BASE_URL, isDev } from './config'; import { buildType, CLOUD_BASE_URL, isDev } from './config';
import { logger } from './logger'; import { logger } from './logger';
import { import {
getOrCreateWindow, getMainWindow,
handleOpenUrlInHiddenWindow, handleOpenUrlInHiddenWindow,
mainWindowOrigin, mainWindowOrigin,
removeCookie, removeCookie,
@@ -39,8 +39,12 @@ export function setupDeepLink(app: App) {
// on windows & linux, we need to listen for the second-instance event // on windows & linux, we need to listen for the second-instance event
app.on('second-instance', (event, commandLine) => { app.on('second-instance', (event, commandLine) => {
getOrCreateWindow() getMainWindow()
.then(window => { .then(window => {
if (!window) {
logger.error('main window is not ready');
return;
}
window.show(); window.show();
const url = commandLine.pop(); const url = commandLine.pop();
if (url?.startsWith(`${protocol}://`)) { if (url?.startsWith(`${protocol}://`)) {
@@ -66,9 +70,9 @@ async function handleAffineUrl(url: string) {
} }
async function handleOauthJwt(url: string) { async function handleOauthJwt(url: string) {
if (url) { const mainWindow = await getMainWindow();
if (url && mainWindow) {
try { try {
const mainWindow = await getOrCreateWindow();
mainWindow.show(); mainWindow.show();
const urlObj = new URL(url); const urlObj = new URL(url);
const token = urlObj.searchParams.get('token'); const token = urlObj.searchParams.get('token');

View File

@@ -11,7 +11,7 @@ import { registerEvents } from './events';
import { registerHandlers } from './handlers'; import { registerHandlers } from './handlers';
import { ensureHelperProcess } from './helper-process'; import { ensureHelperProcess } from './helper-process';
import { logger } from './logger'; import { logger } from './logger';
import { getOrCreateWindow } from './main-window'; import { initMainWindow as initMainWindow } from './main-window';
import { registerProtocol } from './protocol'; import { registerProtocol } from './protocol';
import { registerUpdater } from './updater'; import { registerUpdater } from './updater';
@@ -56,7 +56,7 @@ app.on('window-all-closed', () => {
* @see https://www.electronjs.org/docs/v14-x-y/api/app#event-activate-macos Event: 'activate' * @see https://www.electronjs.org/docs/v14-x-y/api/app#event-activate-macos Event: 'activate'
*/ */
app.on('activate', () => { app.on('activate', () => {
getOrCreateWindow().catch(e => initMainWindow().catch(e =>
console.error('Failed to restore or create window:', e) console.error('Failed to restore or create window:', e)
); );
}); });
@@ -72,7 +72,7 @@ app
.then(registerHandlers) .then(registerHandlers)
.then(registerEvents) .then(registerEvents)
.then(ensureHelperProcess) .then(ensureHelperProcess)
.then(getOrCreateWindow) .then(initMainWindow)
.then(createApplicationMenu) .then(createApplicationMenu)
.then(registerUpdater) .then(registerUpdater)
.catch(e => console.error('Failed create window:', e)); .catch(e => console.error('Failed create window:', e));

View File

@@ -5,10 +5,9 @@ import electronWindowState from 'electron-window-state';
import { join } from 'path'; import { join } from 'path';
import { isMacOS, isWindows } from '../shared/utils'; import { isMacOS, isWindows } from '../shared/utils';
import { getExposedMeta } from './exposed';
import { ensureHelperProcess } from './helper-process'; import { ensureHelperProcess } from './helper-process';
import { logger } from './logger'; import { logger } from './logger';
import { uiSubjects } from './ui'; import { uiSubjects } from './ui/subject';
import { parseCookie } from './utils'; import { parseCookie } from './utils';
const IS_DEV: boolean = const IS_DEV: boolean =
@@ -18,7 +17,19 @@ const DEV_TOOL = process.env.DEV_TOOL === 'true';
export const mainWindowOrigin = process.env.DEV_SERVER_URL || 'file://.'; export const mainWindowOrigin = process.env.DEV_SERVER_URL || 'file://.';
async function createWindow() { // todo: not all window need all of the exposed meta
const getWindowAdditionalArguments = async () => {
const { getExposedMeta } = await import('./exposed');
const mainExposedMeta = getExposedMeta();
const helperProcessManager = await ensureHelperProcess();
const helperExposedMeta = await helperProcessManager.rpc?.getMeta();
return [
`--main-exposed-meta=` + JSON.stringify(mainExposedMeta),
`--helper-exposed-meta=` + JSON.stringify(helperExposedMeta),
];
};
async function createWindow(additionalArguments: string[]) {
logger.info('create window'); logger.info('create window');
const mainWindowState = electronWindowState({ const mainWindowState = electronWindowState({
defaultWidth: 1000, defaultWidth: 1000,
@@ -30,8 +41,6 @@ async function createWindow() {
assert(helperExposedMeta, 'helperExposedMeta should be defined'); assert(helperExposedMeta, 'helperExposedMeta should be defined');
const mainExposedMeta = getExposedMeta();
const browserWindow = new BrowserWindow({ const browserWindow = new BrowserWindow({
titleBarStyle: isMacOS() titleBarStyle: isMacOS()
? 'hiddenInset' ? 'hiddenInset'
@@ -56,10 +65,7 @@ async function createWindow() {
spellcheck: false, // FIXME: enable? spellcheck: false, // FIXME: enable?
preload: join(__dirname, './preload.js'), preload: join(__dirname, './preload.js'),
// serialize exposed meta that to be used in preload // serialize exposed meta that to be used in preload
additionalArguments: [ additionalArguments: additionalArguments,
`--main-exposed-meta=` + JSON.stringify(mainExposedMeta),
`--helper-exposed-meta=` + JSON.stringify(helperExposedMeta),
],
}, },
}); });
@@ -146,16 +152,24 @@ async function createWindow() {
let browserWindow$: Promise<BrowserWindow> | undefined; let browserWindow$: Promise<BrowserWindow> | undefined;
/** /**
* Restore existing BrowserWindow or Create new BrowserWindow * Init main BrowserWindow. Will create a new window if it's not created yet.
*/ */
export async function getOrCreateWindow() { export async function initMainWindow() {
if (!browserWindow$ || (await browserWindow$.then(w => w.isDestroyed()))) { if (!browserWindow$ || (await browserWindow$.then(w => w.isDestroyed()))) {
browserWindow$ = createWindow(); const additionalArguments = await getWindowAdditionalArguments();
browserWindow$ = createWindow(additionalArguments);
} }
const mainWindow = await browserWindow$; const mainWindow = await browserWindow$;
return mainWindow; return mainWindow;
} }
export async function getMainWindow() {
if (!browserWindow$) return;
const window = await browserWindow$;
if (window.isDestroyed()) return;
return window;
}
export async function handleOpenUrlInHiddenWindow(url: string) { export async function handleOpenUrlInHiddenWindow(url: string) {
const win = new BrowserWindow({ const win = new BrowserWindow({
width: 1200, width: 1200,

View File

@@ -1,8 +1,9 @@
import { app, BrowserWindow, nativeTheme } from 'electron'; import { app, nativeTheme } from 'electron';
import { getLinkPreview } from 'link-preview-js'; import { getLinkPreview } from 'link-preview-js';
import { isMacOS } from '../../shared/utils'; import { isMacOS } from '../../shared/utils';
import { logger } from '../logger'; import { logger } from '../logger';
import { getMainWindow } from '../main-window';
import type { NamespaceHandlers } from '../type'; import type { NamespaceHandlers } from '../type';
import { getChallengeResponse } from './challenge'; import { getChallengeResponse } from './challenge';
import { getGoogleOauthCode } from './google-auth'; import { getGoogleOauthCode } from './google-auth';
@@ -13,32 +14,28 @@ export const uiHandlers = {
}, },
handleSidebarVisibilityChange: async (_, visible: boolean) => { handleSidebarVisibilityChange: async (_, visible: boolean) => {
if (isMacOS()) { if (isMacOS()) {
const windows = BrowserWindow.getAllWindows(); const window = await getMainWindow();
windows.forEach(w => { window?.setWindowButtonVisibility(visible);
// hide window buttons when sidebar is not visible
w.setWindowButtonVisibility(visible);
});
} }
}, },
handleMinimizeApp: async () => { handleMinimizeApp: async () => {
const windows = BrowserWindow.getAllWindows(); const window = await getMainWindow();
windows.forEach(w => { window?.minimize();
w.minimize();
});
}, },
handleMaximizeApp: async () => { handleMaximizeApp: async () => {
const windows = BrowserWindow.getAllWindows(); const window = await getMainWindow();
windows.forEach(w => { if (!window) {
// allow unmaximize when in full screen mode return;
if (w.isFullScreen()) { }
w.setFullScreen(false); // allow unmaximize when in full screen mode
w.unmaximize(); if (window.isFullScreen()) {
} else if (w.isMaximized()) { window.setFullScreen(false);
w.unmaximize(); window.unmaximize();
} else { } else if (window.isMaximized()) {
w.maximize(); window.unmaximize();
} else {
window.maximize();
} }
});
}, },
handleCloseApp: async () => { handleCloseApp: async () => {
app.quit(); app.quit();