From f7b757785c0df8bec6da6b5e08c3ddbd421e0649 Mon Sep 17 00:00:00 2001 From: Kieran O'Neill Date: Fri, 8 Mar 2024 03:41:44 -0700 Subject: [PATCH] fix: set focus to new app window upon creation (#202) refactor: move window creation to app window service feat: set app window position to middle of current window --- .../AppWindowManagerService.ts | 97 +++++++++++++++---- .../types/ICreateWindowOptions.ts | 11 +++ .../AppWindowManagerService/types/index.ts | 1 + .../BackgroundEventListener.ts | 34 +------ .../BackgroundMessageHandler.ts | 40 ++------ 5 files changed, 101 insertions(+), 82 deletions(-) create mode 100644 src/extension/services/AppWindowManagerService/types/ICreateWindowOptions.ts diff --git a/src/extension/services/AppWindowManagerService/AppWindowManagerService.ts b/src/extension/services/AppWindowManagerService/AppWindowManagerService.ts index 60e74e9f..7b6de2f1 100644 --- a/src/extension/services/AppWindowManagerService/AppWindowManagerService.ts +++ b/src/extension/services/AppWindowManagerService/AppWindowManagerService.ts @@ -1,7 +1,11 @@ import browser, { Windows } from 'webextension-polyfill'; // constants -import { APP_WINDOW_KEY_PREFIX } from '@extension/constants'; +import { + APP_WINDOW_KEY_PREFIX, + DEFAULT_POPUP_HEIGHT, + DEFAULT_POPUP_WIDTH, +} from '@extension/constants'; // enums import { AppTypeEnum } from '@extension/enums'; @@ -12,7 +16,7 @@ import StorageManager from '../StorageManager'; // types import type { ILogger } from '@common/types'; import type { IAppWindow } from '@extension/types'; -import type { ICreateOptions } from './types'; +import type { ICreateOptions, ICreateWindowOptions } from './types'; /** * Manages app windows in storage. @@ -45,6 +49,77 @@ export default class AppWindowManagerService { * public functions */ + public async createWindow({ + left, + searchParams, + top, + type, + }: ICreateWindowOptions): Promise { + const _functionName: string = 'createWindow'; + const currentWindow: Windows.Window = await browser.windows.getCurrent(); + let appWindow: Windows.Window; + let defaultLeftPosition: number | undefined; + let defaultTopPosition: number | undefined; + let windowURL: string | null = null; + + switch (type) { + case AppTypeEnum.BackgroundApp: + windowURL = 'background-app.html'; + break; + case AppTypeEnum.MainApp: + windowURL = 'main-app.html'; + break; + case AppTypeEnum.RegistrationApp: + windowURL = 'registration-app.html'; + break; + default: + break; + } + + if (!windowURL) { + this.logger?.debug( + `${AppWindowManagerService.name}#${_functionName}: unknown app type "${type}"` + ); + + return null; + } + + defaultLeftPosition = currentWindow.width + ? Math.round(currentWindow.width / 2 - DEFAULT_POPUP_WIDTH / 2) + : undefined; + defaultTopPosition = currentWindow.height + ? Math.round(currentWindow.height / 2 - DEFAULT_POPUP_HEIGHT / 2) + : undefined; + appWindow = await browser.windows.create({ + focused: true, + height: DEFAULT_POPUP_HEIGHT, + left: left ?? defaultLeftPosition, + top: top ?? defaultTopPosition, + type: 'popup', + url: `${windowURL}${searchParams ? `?${searchParams.toString()}` : ''}`, + width: DEFAULT_POPUP_WIDTH, + }); + + if (!appWindow.id) { + this.logger?.debug( + `${AppWindowManagerService.name}#${_functionName}: no window id for window "${type}"` + ); + + return null; + } + + await this.storageManager.setItems({ + [this.createAppWindowItemKey(appWindow.id)]: { + left: appWindow.left || 0, + top: appWindow.top || 0, + type, + windowId: appWindow.id, + }, + }); + + return appWindow; + } + public async getAll(): Promise { const items: Record = await this.storageManager.getAllItems(); @@ -104,22 +179,4 @@ export default class AppWindowManagerService { appWindows.map((value) => this.createAppWindowItemKey(value.windowId)) ); } - - public async saveByBrowserWindowAndType( - window: Windows.Window, - type: AppTypeEnum - ): Promise { - if (!window.id) { - return; - } - - return await this.storageManager.setItems({ - [this.createAppWindowItemKey(window.id)]: { - left: window.left || 0, - top: window.top || 0, - type, - windowId: window.id, - }, - }); - } } diff --git a/src/extension/services/AppWindowManagerService/types/ICreateWindowOptions.ts b/src/extension/services/AppWindowManagerService/types/ICreateWindowOptions.ts new file mode 100644 index 00000000..3920efbd --- /dev/null +++ b/src/extension/services/AppWindowManagerService/types/ICreateWindowOptions.ts @@ -0,0 +1,11 @@ +// types +import { AppTypeEnum } from '@extension/enums'; + +interface ICreateWindowOptions { + left?: number; + searchParams?: URLSearchParams; + top?: number; + type: AppTypeEnum; +} + +export default ICreateWindowOptions; diff --git a/src/extension/services/AppWindowManagerService/types/index.ts b/src/extension/services/AppWindowManagerService/types/index.ts index 731c7f6e..a839f56e 100644 --- a/src/extension/services/AppWindowManagerService/types/index.ts +++ b/src/extension/services/AppWindowManagerService/types/index.ts @@ -1 +1,2 @@ export type { default as ICreateOptions } from './ICreateOptions'; +export type { default as ICreateWindowOptions } from './ICreateWindowOptions'; diff --git a/src/extension/services/BackgroundEventListener/BackgroundEventListener.ts b/src/extension/services/BackgroundEventListener/BackgroundEventListener.ts index 30b5d4f5..1607e023 100644 --- a/src/extension/services/BackgroundEventListener/BackgroundEventListener.ts +++ b/src/extension/services/BackgroundEventListener/BackgroundEventListener.ts @@ -1,11 +1,7 @@ import browser, { Alarms, Tabs, Windows } from 'webextension-polyfill'; // constants -import { - DEFAULT_POPUP_HEIGHT, - DEFAULT_POPUP_WIDTH, - PASSWORD_LOCK_ALARM, -} from '@extension/constants'; +import { PASSWORD_LOCK_ALARM } from '@extension/constants'; // enums import { AppTypeEnum } from '@extension/enums'; @@ -119,9 +115,7 @@ export default class BackgroundEventListener { const _functionName: string = 'onExtensionClick'; const isInitialized: boolean = await this.privateKeyService.isInitialized(); let mainAppWindows: IAppWindow[]; - let mainWindow: Windows.Window; let registrationAppWindows: IAppWindow[]; - let registrationWindow: Windows.Window; this.logger?.debug( `${BackgroundEventListener.name}#${_functionName}(): browser extension clicked` @@ -156,18 +150,9 @@ export default class BackgroundEventListener { await this.storageManager.removeAll(); // if there is no registration app window up, we can open a new one - registrationWindow = await browser.windows.create({ - height: DEFAULT_POPUP_HEIGHT, - type: 'popup', - url: 'registration-app.html', - width: DEFAULT_POPUP_WIDTH, + await this.appWindowManagerService.createWindow({ + type: AppTypeEnum.RegistrationApp, }); - - // save the registration window to storage - return await this.appWindowManagerService.saveByBrowserWindowAndType( - registrationWindow, - AppTypeEnum.RegistrationApp - ); } mainAppWindows = await this.appWindowManagerService.getByType( @@ -192,18 +177,9 @@ export default class BackgroundEventListener { ); // if there is no main app window up, we can open the app - mainWindow = await browser.windows.create({ - height: DEFAULT_POPUP_HEIGHT, - type: 'popup', - url: 'main-app.html', - width: DEFAULT_POPUP_WIDTH, + await this.appWindowManagerService.createWindow({ + type: AppTypeEnum.MainApp, }); - - // save the main app window to storage - await this.appWindowManagerService.saveByBrowserWindowAndType( - mainWindow, - AppTypeEnum.MainApp - ); } public async onFocusChanged(windowId: number): Promise { diff --git a/src/extension/services/BackgroundMessageHandler/BackgroundMessageHandler.ts b/src/extension/services/BackgroundMessageHandler/BackgroundMessageHandler.ts index 9d55ff0d..91594e4b 100644 --- a/src/extension/services/BackgroundMessageHandler/BackgroundMessageHandler.ts +++ b/src/extension/services/BackgroundMessageHandler/BackgroundMessageHandler.ts @@ -12,10 +12,6 @@ import { networks } from '@extension/config'; // constants import { HOST, ICON_URI } from '@common/constants'; -import { - DEFAULT_POPUP_HEIGHT, - DEFAULT_POPUP_WIDTH, -} from '@extension/constants'; // enums import { @@ -75,7 +71,6 @@ import type { IInternalRequestMessage, INetwork, ISession, - ISettings, } from '@extension/types'; // utils @@ -341,26 +336,16 @@ export default class BackgroundMessageHandler { await this.appWindowManagerService.getByType(AppTypeEnum.MainApp); const registrationAppWindows: IAppWindow[] = await this.appWindowManagerService.getByType(AppTypeEnum.RegistrationApp); - let mainWindow: Windows.Window; // if there is no main app windows, create a new one if (mainAppWindows.length <= 0) { - mainWindow = await browser.windows.create({ - height: DEFAULT_POPUP_HEIGHT, - type: 'popup', - url: 'main-app.html', - width: DEFAULT_POPUP_WIDTH, + await this.appWindowManagerService.createWindow({ + type: AppTypeEnum.MainApp, ...(registrationAppWindows[0] && { left: registrationAppWindows[0].left, top: registrationAppWindows[0].top, }), }); - - // save to storage - await this.appWindowManagerService.saveByBrowserWindowAndType( - mainWindow, - AppTypeEnum.MainApp - ); } // if registration app windows exist remove them @@ -602,8 +587,6 @@ export default class BackgroundMessageHandler { const isInitialized: boolean = await this.privateKeyService.isInitialized(); const mainAppWindows: IAppWindow[] = await this.appWindowManagerService.getByType(AppTypeEnum.MainApp); - let backgroundWindow: Windows.Window; - let searchParams: URLSearchParams; // not initialized, ignore it if (!isInitialized) { @@ -635,21 +618,12 @@ export default class BackgroundMessageHandler { `${BackgroundMessageHandler.name}#${_functionName}(): main app window not open, opening background app window for "${event.type}" event` ); - searchParams = new URLSearchParams({ - eventId: encodeURIComponent(event.id), // add the event id to the url search params, so the app knows which event to use - }); - backgroundWindow = await browser.windows.create({ - height: DEFAULT_POPUP_HEIGHT, - type: 'popup', - url: `background-app.html?${searchParams.toString()}`, - width: DEFAULT_POPUP_WIDTH, + await this.appWindowManagerService.createWindow({ + searchParams: new URLSearchParams({ + eventId: encodeURIComponent(event.id), // add the event id to the url search params, so the app knows which event to use + }), + type: AppTypeEnum.BackgroundApp, }); - - // save to app window storage - await this.appWindowManagerService.saveByBrowserWindowAndType( - backgroundWindow, - AppTypeEnum.BackgroundApp - ); } private async sendResponse(