From 0e4ae922451af967c78616057ed26b85ba5d4b5c Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Tue, 20 Feb 2024 10:12:27 -0500 Subject: Popup preview frame API map (#712) * Add API map type safety * Add API map types * Simplify names * Remove unused type --- ext/js/pages/settings/popup-preview-controller.js | 17 ++++--- ext/js/pages/settings/popup-preview-frame.js | 62 ++++++++--------------- 2 files changed, 31 insertions(+), 48 deletions(-) (limited to 'ext/js/pages') diff --git a/ext/js/pages/settings/popup-preview-controller.js b/ext/js/pages/settings/popup-preview-controller.js index 8361809d..e661b738 100644 --- a/ext/js/pages/settings/popup-preview-controller.js +++ b/ext/js/pages/settings/popup-preview-controller.js @@ -71,38 +71,41 @@ export class PopupPreviewController { /** */ _onCustomCssChange() { const css = /** @type {HTMLTextAreaElement} */ (this._customCss).value; - this._invoke('PopupPreviewFrame.setCustomCss', {css}); + this._invoke('setCustomCss', {css}); } /** */ _onCustomOuterCssChange() { const css = /** @type {HTMLTextAreaElement} */ (this._customOuterCss).value; - this._invoke('PopupPreviewFrame.setCustomOuterCss', {css}); + this._invoke('setCustomOuterCss', {css}); } /** */ _onOptionsContextChange() { const optionsContext = this._settingsController.getOptionsContext(); - this._invoke('PopupPreviewFrame.updateOptionsContext', {optionsContext}); + this._invoke('updateOptionsContext', {optionsContext}); } /** * @param {import('settings-controller').EventArgument<'optionsChanged'>} details */ _onOptionsChanged({options}) { - this._invoke('PopupPreviewFrame.optionsChanged', {options}); + this._invoke('setLanguageExampleText', {language: options.general.language}); } /** * @param {import('dom-data-binder').SettingChangedEvent} settingChangedEvent */ _onLanguageSelectChanged(settingChangedEvent) { - this._invoke('PopupPreviewFrame.setLanguageExampleText', {language: settingChangedEvent.detail.value}); + const {value} = settingChangedEvent.detail; + if (typeof value !== 'string') { return; } + this._invoke('setLanguageExampleText', {language: value}); } /** - * @param {string} action - * @param {import('core').SerializableObject} params + * @template {import('popup-preview-frame').ApiNames} TName + * @param {TName} action + * @param {import('popup-preview-frame').ApiParams} params */ _invoke(action, params) { if (this._frame === null || this._frame.contentWindow === null) { return; } diff --git a/ext/js/pages/settings/popup-preview-frame.js b/ext/js/pages/settings/popup-preview-frame.js index 8d881cc6..ad6e420f 100644 --- a/ext/js/pages/settings/popup-preview-frame.js +++ b/ext/js/pages/settings/popup-preview-frame.js @@ -18,6 +18,7 @@ import * as wanakana from '../../../lib/wanakana.js'; import {Frontend} from '../../app/frontend.js'; +import {createApiMap, invokeApiMapHandler} from '../../core/api-map.js'; import {querySelectorNotNull} from '../../dom/query-selector.js'; import {TextSourceRange} from '../../dom/text-source-range.js'; @@ -58,15 +59,14 @@ export class PopupPreviewFrame { this._wanakanaBound = false; /* eslint-disable @stylistic/no-multi-spaces */ - /** @type {Map void>} */ - this._windowMessageHandlers = new Map(/** @type {[key: string, handler: (params: import('core').SerializableObjectAny) => void][]} */ ([ - ['PopupPreviewFrame.setText', this._onSetText.bind(this)], - ['PopupPreviewFrame.setCustomCss', this._setCustomCss.bind(this)], - ['PopupPreviewFrame.setCustomOuterCss', this._setCustomOuterCss.bind(this)], - ['PopupPreviewFrame.updateOptionsContext', this._updateOptionsContext.bind(this)], - ['PopupPreviewFrame.optionsChanged', this._onOptionsChanged.bind(this)], - ['PopupPreviewFrame.setLanguageExampleText', this._setLanguageExampleText.bind(this)] - ])); + /** @type {import('popup-preview-frame').ApiMap} */ + this._windowMessageHandlers = createApiMap([ + ['setText', this._onSetText.bind(this)], + ['setCustomCss', this._setCustomCss.bind(this)], + ['setCustomOuterCss', this._setCustomOuterCss.bind(this)], + ['updateOptionsContext', this._updateOptionsContext.bind(this)], + ['setLanguageExampleText', this._setLanguageExampleText.bind(this)] + ]); /* eslint-enable @stylistic/no-multi-spaces */ } @@ -89,7 +89,7 @@ export class PopupPreviewFrame { this._languageSummaries = await this._application.api.getLanguageSummaries(); const options = await this._application.api.optionsGet({current: true}); - void this._onOptionsChanged({options, optionsContext: {current: true}}); + void this._setLanguageExampleText({language: options.general.language}); // Overwrite frontend this._frontend = new Frontend({ @@ -156,16 +156,13 @@ export class PopupPreviewFrame { } /** - * @param {MessageEvent<{action: string, params: import('core').SerializableObject}>} e + * @param {MessageEvent} event */ - _onMessage(e) { - if (e.origin !== this._targetOrigin) { return; } - - const {action, params} = e.data; - const handler = this._windowMessageHandlers.get(action); - if (typeof handler !== 'function') { return; } - - handler(params); + _onMessage(event) { + if (event.origin !== this._targetOrigin) { return; } + const {action, params} = event.data; + const callback = () => {}; // NOP + invokeApiMapHandler(this._windowMessageHandlers, action, params, [], callback); } /** @@ -209,9 +206,7 @@ export class PopupPreviewFrame { this._setText(element.value, false); } - /** - * @param {{text: string}} details - */ + /** @type {import('popup-preview-frame').ApiHandler<'setText'>} */ _onSetText({text}) { this._setText(text, true); } @@ -242,9 +237,7 @@ export class PopupPreviewFrame { node.classList.toggle('placeholder-info-visible', visible); } - /** - * @param {{css: string}} details - */ + /** @type {import('popup-preview-frame').ApiHandler<'setCustomCss'>} */ _setCustomCss({css}) { if (this._frontend === null) { return; } const popup = this._frontend.popup; @@ -252,9 +245,7 @@ export class PopupPreviewFrame { void popup.setCustomCss(css); } - /** - * @param {{css: string}} details - */ + /** @type {import('popup-preview-frame').ApiHandler<'setCustomOuterCss'>} */ _setCustomOuterCss({css}) { if (this._frontend === null) { return; } const popup = this._frontend.popup; @@ -262,9 +253,7 @@ export class PopupPreviewFrame { void popup.setCustomOuterCss(css, false); } - /** - * @param {{optionsContext: import('settings').OptionsContext}} details - */ + /** @type {import('popup-preview-frame').ApiHandler<'updateOptionsContext'>} */ async _updateOptionsContext(details) { const {optionsContext} = details; this._optionsContext = optionsContext; @@ -274,16 +263,7 @@ export class PopupPreviewFrame { await this._updateSearch(); } - /** - * @param {import('settings-controller').EventArgument<'optionsChanged'>} details - */ - async _onOptionsChanged({options: {general: {language}}}) { - this._setLanguageExampleText({language}); - } - - /** - * @param {{language: string}} details - */ + /** @type {import('popup-preview-frame').ApiHandler<'setLanguageExampleText'>} */ _setLanguageExampleText({language}) { const activeLanguage = /** @type {import('language').LanguageSummary} */ (this._languageSummaries.find(({iso}) => iso === language)); -- cgit v1.2.3