From e0d5b913546d1ec0bbdda535b2f746d331ebe8d3 Mon Sep 17 00:00:00 2001 From: tiddlygit-test Date: Sat, 9 Jan 2021 22:36:16 +0800 Subject: [PATCH] fix: make no error in setupViewEventHandlers --- src/services/view/index.ts | 13 +- src/services/view/setupViewEventHandlers.ts | 161 ++++++++++++-------- src/services/windows/WindowProperties.ts | 1 + src/services/windows/index.ts | 3 - src/services/windows/webpackEntry.d.ts | 2 + 5 files changed, 105 insertions(+), 75 deletions(-) create mode 100644 src/services/windows/webpackEntry.d.ts diff --git a/src/services/view/index.ts b/src/services/view/index.ts index 339c098b..17511564 100644 --- a/src/services/view/index.ts +++ b/src/services/view/index.ts @@ -7,14 +7,13 @@ import { Workspace } from '@services/workspaces'; import { Wiki } from '@services/wiki'; import { Authentication } from '@services/auth'; import { Window } from '@services/windows'; +import { WindowNames } from '@services/windows/WindowProperties'; import i18n from '../libs/i18n'; import getViewBounds from '@services/libs/get-view-bounds'; import { extractDomain } from '@services/libs/url'; import { IWorkspace } from '@services/types'; import setupViewEventHandlers from './setupViewEventHandlers'; -declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string; - @injectable() export class View { constructor( @@ -101,12 +100,11 @@ export class View { enableRemoteModule: true, session: sessionOfView, preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, + additionalArguments: [WindowNames.view, JSON.stringify({ workspaceID: workspace.id })], }; const view = new BrowserView({ webPreferences: sharedWebPreferences, }); - // FIXME: put this into meta when creating window - (view.webContents as any).workspaceId = workspace.id; // background needs to explicitly set // if not, by default, the background of BrowserView is transparent // which would break the CSS of certain websites @@ -174,7 +172,12 @@ export class View { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const initialUrl = (rememberLastPageVisited && workspace.lastUrl) || workspace.homeUrl; adjustUserAgentByUrl(view.webContents, initialUrl); - setupViewEventHandlers(view, browserWindow, { shouldPauseNotifications: this.shouldPauseNotifications, workspace }, { adjustUserAgentByUrl }); + setupViewEventHandlers( + view, + browserWindow, + { shouldPauseNotifications: this.shouldPauseNotifications, workspace, sharedWebPreferences }, + { adjustUserAgentByUrl }, + ); // start wiki on startup, or on sub-wiki creation await this.wikiService.wikiStartup(workspace); void view.webContents.loadURL(initialUrl); diff --git a/src/services/view/setupViewEventHandlers.ts b/src/services/view/setupViewEventHandlers.ts index bb09cd76..cebe9a88 100644 --- a/src/services/view/setupViewEventHandlers.ts +++ b/src/services/view/setupViewEventHandlers.ts @@ -1,4 +1,4 @@ -import { app, BrowserView, ipcMain, WebContents, shell, Event as ElectronEvent, BrowserWindowConstructorOptions, BrowserWindow } from 'electron'; +import { app, BrowserView, ipcMain, WebContents, shell, NativeImage, BrowserWindowConstructorOptions, BrowserWindow } from 'electron'; import path from 'path'; import fsExtra from 'fs-extra'; @@ -10,16 +10,16 @@ import { buildResourcePath } from '@services/constants/paths'; import { Preference } from '@services/preferences'; import { Workspace } from '@services/workspaces'; import { Window } from '@services/windows'; -import { Wiki } from '@services/wiki'; -import { Authentication } from '@services/auth'; +import { WindowNames } from '@services/windows/WindowProperties'; import { container } from '@services/container'; export interface IViewContext { workspace: IWorkspace; shouldPauseNotifications: boolean; + sharedWebPreferences: BrowserWindowConstructorOptions['webPreferences']; } export interface IViewModifier { - adjustUserAgentByUrl: (_contents: WebContents, _url: string) => boolean; + adjustUserAgentByUrl: (_contents: WebContents, nextUrl: string) => boolean; } /** @@ -28,7 +28,7 @@ export interface IViewModifier { export default function setupViewEventHandlers( view: BrowserView, browserWindow: BrowserWindow, - { workspace, shouldPauseNotifications }: IViewContext, + { workspace, shouldPauseNotifications, sharedWebPreferences }: IViewContext, { adjustUserAgentByUrl }: IViewModifier, ): void { const workspaceService = container.resolve(Workspace); @@ -75,8 +75,7 @@ export default function setupViewEventHandlers( if (browserWindow !== undefined && !browserWindow.isDestroyed()) { // fix https://github.com/atomery/singlebox/issues/228 const contentSize = browserWindow.getContentSize(); - // @ts-expect-error ts-migrate(2554) FIXME: Expected 4 arguments, but got 1. - view.setBounds(getViewBounds(contentSize)); + view.setBounds(getViewBounds(contentSize as [number, number])); } } } @@ -191,7 +190,32 @@ export default function setupViewEventHandlers( } }); - view.webContents.on('new-window', handleNewWindow); + // TODO: refactor to setWindowOpenHandler + // view.webContents.setWindowOpenHandler((details: Electron.HandlerDetails) => { + // action: "deny"; + // } | { + // action: "allow"; + // overrideBrowserWindowOptions?: BrowserWindowConstructorOptions | undefined; + // }) + view.webContents.on( + 'new-window', + ( + _event: Electron.NewWindowWebContentsEvent, + nextUrl: string, + _frameName: string, + disposition: 'default' | 'new-window' | 'foreground-tab' | 'background-tab' | 'save-to-disk' | 'other', + options: BrowserWindowConstructorOptions, + _additionalFeatures: string[], + _referrer: Electron.Referrer, + _postBody: Electron.PostBody, + ) => + handleNewWindow(_event, nextUrl, _frameName, disposition, options, _additionalFeatures, _referrer, _postBody, { + workspace, + sharedWebPreferences, + view, + adjustUserAgentByUrl, + }), + ); // Handle downloads // https://electronjs.org/docs/api/download-item view.webContents.session.on('will-download', (_event, item) => { @@ -233,9 +257,8 @@ export default function setupViewEventHandlers( app.badgeCount = count; if (process.platform === 'win32') { if (count > 0) { - // TODO: seems this is not good? - // @ts-expect-error should be Electron.NativeImage here - browserWindow.setOverlayIcon(path.resolve(buildResourcePath, 'overlay-icon.png'), `You have ${count} new messages.`); + const icon = NativeImage.createFromPath(path.resolve(buildResourcePath, 'overlay-icon.png')); + browserWindow.setOverlayIcon(icon, `You have ${count} new messages.`); } else { // eslint-disable-next-line unicorn/no-null browserWindow.setOverlayIcon(null, ''); @@ -257,18 +280,26 @@ export default function setupViewEventHandlers( }); } +export interface INewWindowContext { + view: BrowserView; + workspace: IWorkspace; + sharedWebPreferences: BrowserWindowConstructorOptions['webPreferences']; + adjustUserAgentByUrl: (_contents: WebContents, nextUrl: string) => boolean; +} + function handleNewWindow( - event: ElectronEvent, - view: BrowserView, + event: Electron.NewWindowWebContentsEvent, nextUrl: string, _frameName: string, - disposition: string, - workspace: IWorkspace, - sharedWebPreferences: BrowserWindowConstructorOptions['webPreferences'], - options?: BrowserWindowConstructorOptions, + disposition: 'default' | 'new-window' | 'foreground-tab' | 'background-tab' | 'save-to-disk' | 'other', + options: BrowserWindowConstructorOptions, + _additionalFeatures: string[], + _referrer: Electron.Referrer, + _postBody: Electron.PostBody, + newWindowContext: INewWindowContext, ): void { const workspaceService = container.resolve(Workspace); - const preferenceService = container.resolve(Preference); + const { view, workspace, sharedWebPreferences, adjustUserAgentByUrl } = newWindowContext; const appUrl = workspaceService.get(workspace.id)?.homeUrl; if (appUrl === undefined) { @@ -285,20 +316,33 @@ function handleNewWindow( // options is undefined // https://github.com/atomery/webcatalog/issues/842 const cmdClick = options === undefined; - const newOptions = cmdClick + const metadataConfig = { + additionalArguments: [WindowNames.newWindow, JSON.stringify({ isPopup: true, ...JSON.parse(sharedWebPreferences?.additionalArguments?.[1] ?? '{}') })], + preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY, + }; + const newOptions: BrowserWindowConstructorOptions = cmdClick ? { show: true, width: 1200, height: 800, - webPreferences: sharedWebPreferences, + webPreferences: { ...sharedWebPreferences, ...metadataConfig }, } - : { ...options, width: 1200, height: 800 }; + : { ...options, width: 1200, height: 800, webPreferences: metadataConfig }; const popupWin = new BrowserWindow(newOptions); - // FIXME: WebCatalog internal value to determine whether BrowserWindow is popup - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access - popupWin.isPopup = true; popupWin.setMenuBarVisibility(false); - popupWin.webContents.on('new-window', this.handleNewWindow); + popupWin.webContents.on( + 'new-window', + ( + _event: Electron.NewWindowWebContentsEvent, + nextUrl: string, + _frameName: string, + disposition: 'default' | 'new-window' | 'foreground-tab' | 'background-tab' | 'save-to-disk' | 'other', + options: BrowserWindowConstructorOptions, + _additionalFeatures: string[], + _referrer: Electron.Referrer, + _postBody: Electron.PostBody, + ) => handleNewWindow(_event, nextUrl, _frameName, disposition, options, _additionalFeatures, _referrer, _postBody, newWindowContext), + ); // fix Google prevents signing in because of security concerns // https://github.com/atomery/webcatalog/issues/455 // https://github.com/meetfranz/franz/issues/1720#issuecomment-566460763 @@ -320,8 +364,6 @@ function handleNewWindow( if (cmdClick) { void popupWin.loadURL(nextUrl); } - // FIXME: type definition of event - // @ts-expect-error Property 'newGuest' does not exist on type 'Event'.ts(2339) event.newGuest = popupWin; }; // Conditions are listed by order of priority @@ -329,18 +371,18 @@ function handleNewWindow( // or regular new-window event // or if in Google Drive app, open Google Docs files internally https://github.com/atomery/webcatalog/issues/800 // the next external link request will be opened in new window - if ( - // FIXME: WebCatalog internal value to determine whether BrowserWindow is popup - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access - global.forceNewWindow === true || - disposition === 'new-window' || - disposition === 'default' || - (appDomain === 'drive.google.com' && nextDomain === 'docs.google.com') - ) { - global.forceNewWindow = false; - openInNewWindow(); - return; - } + // if ( + // // FIXME: WebCatalog internal value to determine whether BrowserWindow is popup + // // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access + // global.forceNewWindow === true || + // disposition === 'new-window' || + // disposition === 'default' || + // (appDomain === 'drive.google.com' && nextDomain === 'docs.google.com') + // ) { + // global.forceNewWindow = false; + // openInNewWindow(); + // return; + // } // load in same window if ( // Google: Add account @@ -365,32 +407,6 @@ function handleNewWindow( openInNewWindow(); return; } - // special case for Roam Research - // if popup window is not opened and loaded, Roam crashes (shows white page) - // https://github.com/atomery/webcatalog/issues/793 - if (appDomain === 'roamresearch.com' && nextDomain !== undefined && (disposition === 'foreground-tab' || disposition === 'background-tab')) { - event.preventDefault(); - void shell.openExternal(nextUrl); - // mock window - // close as soon as it did-navigate - const newOptions: BrowserWindowConstructorOptions = { - ...options, - show: false, - }; - const popupWin = new BrowserWindow(newOptions); - // WebCatalog internal value to determine whether BrowserWindow is popup - // FIXME: WebCatalog internal value to determine whether BrowserWindow is popup - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access - popupWin.isPopup = true; - // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. - popupWin.once('did-navigate', () => { - popupWin.close(); - }); - // FIXME: type definition of event - // @ts-expect-error Property 'newGuest' does not exist on type 'Event'.ts(2339) - event.newGuest = popupWin; - return; - } // open external url in browser if (nextDomain !== undefined && (disposition === 'foreground-tab' || disposition === 'background-tab')) { event.preventDefault(); @@ -408,7 +424,19 @@ function handleNewWindow( }; const popupWin = new BrowserWindow(newOptions); popupWin.setMenuBarVisibility(false); - popupWin.webContents.on('new-window', handleNewWindow); + popupWin.webContents.on( + 'new-window', + ( + _event: Electron.NewWindowWebContentsEvent, + nextUrl: string, + _frameName: string, + disposition: 'default' | 'new-window' | 'foreground-tab' | 'background-tab' | 'save-to-disk' | 'other', + options: BrowserWindowConstructorOptions, + _additionalFeatures: string[], + _referrer: Electron.Referrer, + _postBody: Electron.PostBody, + ) => handleNewWindow(_event, nextUrl, _frameName, disposition, options, _additionalFeatures, _referrer, _postBody, newWindowContext), + ); popupWin.webContents.once('will-navigate', (_event, url) => { // if the window is used for the current app, then use default behavior if (isInternalUrl(url, [appUrl, currentUrl])) { @@ -421,7 +449,6 @@ function handleNewWindow( } }); // FIXME: type definition of event - // @ts-expect-error Property 'newGuest' does not exist on type 'Event'.ts(2339) event.newGuest = popupWin; } } diff --git a/src/services/windows/WindowProperties.ts b/src/services/windows/WindowProperties.ts index e4de4037..6125cb09 100644 --- a/src/services/windows/WindowProperties.ts +++ b/src/services/windows/WindowProperties.ts @@ -1,4 +1,5 @@ export enum WindowNames { + newWindow = 'newWindow', main = 'main', view = 'view', addWorkspace = 'addWorkspace', diff --git a/src/services/windows/index.ts b/src/services/windows/index.ts index 6ccbd7e4..d0ddf6ae 100644 --- a/src/services/windows/index.ts +++ b/src/services/windows/index.ts @@ -11,9 +11,6 @@ import { WindowNames, windowDimension, WindowMeta, CodeInjectionType } from '@se import i18n from '@services/libs/i18n'; import getViewBounds from '@services/libs/get-view-bounds'; -declare const MAIN_WINDOW_WEBPACK_ENTRY: string; -declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string; - @injectable() export class Window { private windows = {} as Record; diff --git a/src/services/windows/webpackEntry.d.ts b/src/services/windows/webpackEntry.d.ts new file mode 100644 index 00000000..ff55f4ec --- /dev/null +++ b/src/services/windows/webpackEntry.d.ts @@ -0,0 +1,2 @@ +declare const MAIN_WINDOW_WEBPACK_ENTRY: string; +declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;