aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2023-12-28 22:17:38 -0500
committerGitHub <noreply@github.com>2023-12-29 03:17:38 +0000
commit1e254fd1d4423b984e176547ef36a14383bbd7f5 (patch)
tree8aae2c47f80265d5f1f39c927e19455ec3986387
parenta51ae1533c54162f14785652e9128f90afb86aed (diff)
Event dispatcher refactor (#463)
* Refactor EventDispatcher template type * Update core types * Update log * Update clipboard monitor * Update application events * Update popup events * Update text scanner * Update cross frame API * Update display events * Type updates * Update display history * Update query parser * Update search persistent state controller * Update panel element * Update popup menu * Update audio system * Update hotkey handler * Update settings controller * Update audio controller * Update types * Update types * Update types * Add event handler types * Update type * Fix issues * Remove error suppression * Fix typo
-rw-r--r--ext/js/app/popup-proxy.js4
-rw-r--r--ext/js/app/popup-window.js2
-rw-r--r--ext/js/app/popup.js8
-rw-r--r--ext/js/background/backend.js2
-rw-r--r--ext/js/comm/clipboard-monitor.js4
-rw-r--r--ext/js/comm/cross-frame-api.js4
-rw-r--r--ext/js/core.js44
-rw-r--r--ext/js/display/display-anki.js6
-rw-r--r--ext/js/display/display-audio.js8
-rw-r--r--ext/js/display/display-history.js4
-rw-r--r--ext/js/display/display.js32
-rw-r--r--ext/js/display/query-parser.js8
-rw-r--r--ext/js/display/search-display-controller.js4
-rw-r--r--ext/js/display/search-persistent-state-controller.js2
-rw-r--r--ext/js/dom/panel-element.js15
-rw-r--r--ext/js/dom/popup-menu.js4
-rw-r--r--ext/js/input/hotkey-handler.js22
-rw-r--r--ext/js/language/text-scanner.js4
-rw-r--r--ext/js/media/audio-system.js2
-rw-r--r--ext/js/pages/settings/anki-controller.js4
-rw-r--r--ext/js/pages/settings/anki-templates-controller.js2
-rw-r--r--ext/js/pages/settings/audio-controller.js6
-rw-r--r--ext/js/pages/settings/backup-controller.js4
-rw-r--r--ext/js/pages/settings/collapsible-dictionary-controller.js2
-rw-r--r--ext/js/pages/settings/dictionary-controller.js6
-rw-r--r--ext/js/pages/settings/dictionary-import-controller.js2
-rw-r--r--ext/js/pages/settings/extension-keyboard-shortcuts-controller.js2
-rw-r--r--ext/js/pages/settings/keyboard-mouse-input-field.js6
-rw-r--r--ext/js/pages/settings/keyboard-shortcuts-controller.js4
-rw-r--r--ext/js/pages/settings/nested-popups-controller.js2
-rw-r--r--ext/js/pages/settings/permissions-origin-controller.js2
-rw-r--r--ext/js/pages/settings/permissions-toggle-controller.js4
-rw-r--r--ext/js/pages/settings/persistent-storage-controller.js2
-rw-r--r--ext/js/pages/settings/popup-preview-frame.js2
-rw-r--r--ext/js/pages/settings/profile-conditions-ui.js33
-rw-r--r--ext/js/pages/settings/profile-controller.js2
-rw-r--r--ext/js/pages/settings/recommended-permissions-controller.js2
-rw-r--r--ext/js/pages/settings/scan-inputs-controller.js10
-rw-r--r--ext/js/pages/settings/scan-inputs-simple-controller.js6
-rw-r--r--ext/js/pages/settings/secondary-search-dictionary-controller.js2
-rw-r--r--ext/js/pages/settings/sentence-termination-characters-controller.js2
-rw-r--r--ext/js/pages/settings/settings-controller.js12
-rw-r--r--ext/js/pages/settings/sort-frequency-dictionary-controller.js2
-rw-r--r--ext/js/pages/settings/translation-text-replacements-controller.js2
-rw-r--r--ext/js/yomitan.js14
-rw-r--r--types/ext/application.d.ts20
-rw-r--r--types/ext/audio-controller.d.ts8
-rw-r--r--types/ext/audio-system.d.ts8
-rw-r--r--types/ext/clipboard-monitor.d.ts14
-rw-r--r--types/ext/core.d.ts14
-rw-r--r--types/ext/cross-frame-api.d.ts5
-rw-r--r--types/ext/display-history.d.ts11
-rw-r--r--types/ext/display.d.ts82
-rw-r--r--types/ext/dynamic-property.d.ts10
-rw-r--r--types/ext/event-listener-collection.d.ts9
-rw-r--r--types/ext/extension.d.ts2
-rw-r--r--types/ext/hotkey-handler.d.ts13
-rw-r--r--types/ext/keyboard-mouse-input-field.d.ts15
-rw-r--r--types/ext/log.d.ts14
-rw-r--r--types/ext/panel-element.d.ts23
-rw-r--r--types/ext/popup-menu.d.ts29
-rw-r--r--types/ext/popup.d.ts28
-rw-r--r--types/ext/profile-conditions-ui.d.ts15
-rw-r--r--types/ext/query-parser.d.ts39
-rw-r--r--types/ext/search-persistent-state-controller.d.ts27
-rw-r--r--types/ext/settings-controller.d.ts33
-rw-r--r--types/ext/text-scanner.d.ts12
67 files changed, 430 insertions, 317 deletions
diff --git a/ext/js/app/popup-proxy.js b/ext/js/app/popup-proxy.js
index 924175e2..d141d35b 100644
--- a/ext/js/app/popup-proxy.js
+++ b/ext/js/app/popup-proxy.js
@@ -22,7 +22,7 @@ import {yomitan} from '../yomitan.js';
/**
* This class is a proxy for a Popup that is hosted in a different frame.
* It effectively forwards all API calls to the underlying Popup.
- * @augments EventDispatcher<import('popup').PopupAnyEventType>
+ * @augments EventDispatcher<import('popup').Events>
*/
export class PopupProxy extends EventDispatcher {
/**
@@ -361,7 +361,7 @@ export class PopupProxy extends EventDispatcher {
} else {
this._frameOffsetX = 0;
this._frameOffsetY = 0;
- this.trigger('offsetNotFound');
+ this.trigger('offsetNotFound', {});
return;
}
this._frameOffsetUpdatedAt = now;
diff --git a/ext/js/app/popup-window.js b/ext/js/app/popup-window.js
index 9a0f8011..0b083d80 100644
--- a/ext/js/app/popup-window.js
+++ b/ext/js/app/popup-window.js
@@ -21,7 +21,7 @@ import {yomitan} from '../yomitan.js';
/**
* This class represents a popup that is hosted in a new native window.
- * @augments EventDispatcher<import('popup').PopupAnyEventType>
+ * @augments EventDispatcher<import('popup').Events>
*/
export class PopupWindow extends EventDispatcher {
/**
diff --git a/ext/js/app/popup.js b/ext/js/app/popup.js
index a0712604..4f2368d4 100644
--- a/ext/js/app/popup.js
+++ b/ext/js/app/popup.js
@@ -26,7 +26,7 @@ import {ThemeController} from './theme-controller.js';
/**
* This class is the container which hosts the display of search results.
- * @augments EventDispatcher<import('popup').PopupAnyEventType>
+ * @augments EventDispatcher<import('popup').Events>
*/
export class Popup extends EventDispatcher {
/**
@@ -360,9 +360,7 @@ export class Popup extends EventDispatcher {
parentNode = this._shadow;
}
const node = await loadStyle('yomitan-popup-outer-user-stylesheet', 'code', css, useWebExtensionApi, parentNode);
- /** @type {import('popup').CustomOuterCssChangedEvent} */
- const event = {node, useWebExtensionApi, inShadow};
- this.trigger('customOuterCssChanged', event);
+ this.trigger('customOuterCssChanged', {node, useWebExtensionApi, inShadow});
}
/**
@@ -653,7 +651,7 @@ export class Popup extends EventDispatcher {
}
/**
- * @param {import('dynamic-property').ChangeEventDetails<boolean>} event
+ * @param {import('dynamic-property').EventArgument<boolean, 'change'>} event
*/
_onVisibleChange({value}) {
if (this._visibleValue === value) { return; }
diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js
index 68d4e0c8..b523cd6e 100644
--- a/ext/js/background/backend.js
+++ b/ext/js/background/backend.js
@@ -315,7 +315,7 @@ export class Backend {
// Event handlers
/**
- * @param {{text: string}} params
+ * @param {import('clipboard-monitor').EventArgument<'change'>} details
*/
async _onClipboardTextChange({text}) {
const {clipboard: {maximumSearchLength}} = this._getProfileOptions({current: true}, false);
diff --git a/ext/js/comm/clipboard-monitor.js b/ext/js/comm/clipboard-monitor.js
index 3b3a56a9..d717dff2 100644
--- a/ext/js/comm/clipboard-monitor.js
+++ b/ext/js/comm/clipboard-monitor.js
@@ -19,7 +19,7 @@
import {EventDispatcher} from '../core.js';
/**
- * @augments EventDispatcher<import('clipboard-monitor').EventType>
+ * @augments EventDispatcher<import('clipboard-monitor').Events>
*/
export class ClipboardMonitor extends EventDispatcher {
/**
@@ -71,7 +71,7 @@ export class ClipboardMonitor extends EventDispatcher {
) {
this._previousText = text;
if (canChange && this._japaneseUtil.isStringPartiallyJapanese(text)) {
- this.trigger('change', /** @type {import('clipboard-monitor').ChangeEvent} */ ({text}));
+ this.trigger('change', {text});
}
}
diff --git a/ext/js/comm/cross-frame-api.js b/ext/js/comm/cross-frame-api.js
index 023ca18e..14e410a8 100644
--- a/ext/js/comm/cross-frame-api.js
+++ b/ext/js/comm/cross-frame-api.js
@@ -22,9 +22,9 @@ import {parseJson} from '../core/json.js';
import {yomitan} from '../yomitan.js';
/**
- * @augments EventDispatcher<import('cross-frame-api').CrossFrameAPIPortEventType>
+ * @augments EventDispatcher<import('cross-frame-api').CrossFrameAPIPortEvents>
*/
-class CrossFrameAPIPort extends EventDispatcher {
+export class CrossFrameAPIPort extends EventDispatcher {
/**
* @param {number} otherTabId
* @param {number} otherFrameId
diff --git a/ext/js/core.js b/ext/js/core.js
index 63c2f527..c9c989ac 100644
--- a/ext/js/core.js
+++ b/ext/js/core.js
@@ -353,22 +353,30 @@ export function invokeMessageHandler(handler, params, callback, ...extraArgs) {
}
/**
- * @template {string} TEventName
+ * The following typedef is required because the JSDoc `implements` tag doesn't work with `import()`.
+ * https://github.com/microsoft/TypeScript/issues/49905
+ * @typedef {import('core').EventDispatcherOffGeneric} EventDispatcherOffGeneric
+ */
+
+/**
* Base class controls basic event dispatching.
+ * @template {import('core').EventSurface} TSurface
+ * @implements {EventDispatcherOffGeneric}
*/
export class EventDispatcher {
/**
* Creates a new instance.
*/
constructor() {
- /** @type {Map<string, ((details: import('core').SafeAny) => void)[]>} */
+ /** @type {Map<import('core').EventNames<TSurface>, import('core').EventHandlerAny[]>} */
this._eventMap = new Map();
}
/**
* Triggers an event with the given name and specified argument.
- * @param {TEventName} eventName The string representing the event's name.
- * @param {unknown} [details] The argument passed to the callback functions.
+ * @template {import('core').EventNames<TSurface>} TName
+ * @param {TName} eventName The string representing the event's name.
+ * @param {import('core').EventArgument<TSurface, TName>} details The argument passed to the callback functions.
* @returns {boolean} `true` if any callbacks were registered, `false` otherwise.
*/
trigger(eventName, details) {
@@ -383,8 +391,9 @@ export class EventDispatcher {
/**
* Adds a single event listener to a specific event.
- * @param {TEventName} eventName The string representing the event's name.
- * @param {(details: import('core').SafeAny) => void} callback The event listener callback to add.
+ * @template {import('core').EventNames<TSurface>} TName
+ * @param {TName} eventName The string representing the event's name.
+ * @param {import('core').EventHandler<TSurface, TName>} callback The event listener callback to add.
*/
on(eventName, callback) {
let callbacks = this._eventMap.get(eventName);
@@ -397,8 +406,9 @@ export class EventDispatcher {
/**
* Removes a single event listener from a specific event.
- * @param {TEventName} eventName The string representing the event's name.
- * @param {(details: import('core').SafeAny) => void} callback The event listener callback to add.
+ * @template {import('core').EventNames<TSurface>} TName
+ * @param {TName} eventName The string representing the event's name.
+ * @param {import('core').EventHandler<TSurface, TName>} callback The event listener callback to add.
* @returns {boolean} `true` if the callback was removed, `false` otherwise.
*/
off(eventName, callback) {
@@ -420,7 +430,8 @@ export class EventDispatcher {
/**
* Checks if an event has any listeners.
- * @param {TEventName} eventName The string representing the event's name.
+ * @template {import('core').EventNames<TSurface>} TName
+ * @param {TName} eventName The string representing the event's name.
* @returns {boolean} `true` if the event has listeners, `false` otherwise.
*/
hasListeners(eventName) {
@@ -476,10 +487,11 @@ export class EventListenerCollection {
/**
* Adds an event listener using `object.on`. The listener will later be removed using `object.off`.
- * @template {string} TEventName
- * @param {EventDispatcher<TEventName>} target The object to add the event listener to.
- * @param {TEventName} eventName The string representing the event's name.
- * @param {(details: import('core').SafeAny) => void} callback The event listener callback to add.
+ * @template {import('core').EventSurface} TSurface
+ * @template {import('core').EventNames<TSurface>} TName
+ * @param {EventDispatcher<TSurface>} target The object to add the event listener to.
+ * @param {TName} eventName The string representing the event's name.
+ * @param {import('core').EventHandler<TSurface, TName>} callback The event listener callback to add.
*/
on(target, eventName, callback) {
target.on(eventName, callback);
@@ -512,7 +524,7 @@ export class EventListenerCollection {
* Class representing a generic value with an override stack.
* Changes can be observed by listening to the 'change' event.
* @template [T=unknown]
- * @augments EventDispatcher<import('dynamic-property').EventType>
+ * @augments EventDispatcher<import('dynamic-property').Events<T>>
*/
export class DynamicProperty extends EventDispatcher {
/**
@@ -615,14 +627,14 @@ export class DynamicProperty extends EventDispatcher {
const value = this._overrides.length > 0 ? this._overrides[0].value : this._defaultValue;
if (this._value === value) { return; }
this._value = value;
- this.trigger('change', /** @type {import('dynamic-property').ChangeEventDetails<T>} */ ({value}));
+ this.trigger('change', {value});
}
}
/**
* This class handles logging of messages to the console and triggering
* an event for log calls.
- * @augments EventDispatcher<import('log').LoggerEventType>
+ * @augments EventDispatcher<import('log').Events>
*/
export class Logger extends EventDispatcher {
/**
diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js
index 423cdfdc..759998c4 100644
--- a/ext/js/display/display-anki.js
+++ b/ext/js/display/display-anki.js
@@ -182,7 +182,7 @@ export class DisplayAnki {
// Private
/**
- * @param {import('display').OptionsUpdatedEvent} details
+ * @param {import('display').EventArgument<'optionsUpdated'>} details
*/
_onOptionsUpdated({options}) {
const {
@@ -238,7 +238,7 @@ export class DisplayAnki {
}
/**
- * @param {import('display').ContentUpdateEntryEvent} details
+ * @param {import('display').EventArgument<'contentUpdateEntry'>} details
*/
_onContentUpdateEntry({element}) {
const eventListeners = this._eventListeners;
@@ -261,7 +261,7 @@ export class DisplayAnki {
}
/**
- * @param {import('display').LogDictionaryEntryDataEvent} details
+ * @param {import('display').EventArgument<'logDictionaryEntryData'>} details
*/
_onLogDictionaryEntryData({dictionaryEntry, promises}) {
promises.push(this.getLogData(dictionaryEntry));
diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js
index 30cf2b92..cba9c43c 100644
--- a/ext/js/display/display-audio.js
+++ b/ext/js/display/display-audio.js
@@ -162,7 +162,7 @@ export class DisplayAudio {
// Private
/**
- * @param {import('display').OptionsUpdatedEvent} details
+ * @param {import('display').EventArgument<'optionsUpdated'>} details
*/
_onOptionsUpdated({options}) {
const {enabled, autoPlay, volume, sources} = options.audio;
@@ -201,7 +201,7 @@ export class DisplayAudio {
}
/**
- * @param {import('display').ContentUpdateEntryEvent} details
+ * @param {import('display').EventArgument<'contentUpdateEntry'>} details
*/
_onContentUpdateEntry({element}) {
const eventListeners = this._eventListeners;
@@ -237,7 +237,7 @@ export class DisplayAudio {
}
/**
- * @param {import('display').FrameVisibilityChangeEvent} details
+ * @param {import('display').EventArgument<'frameVisibilityChange'>} details
*/
_onFrameVisibilityChange({value}) {
if (!value) {
@@ -779,7 +779,7 @@ export class DisplayAudio {
}
/**
- * @param {import('popup-menu').MenuCloseEventDetails} details
+ * @param {import('popup-menu').EventArgument<'close'>} details
*/
_onPopupMenuClose({menu}) {
this._openMenus.delete(menu);
diff --git a/ext/js/display/display-history.js b/ext/js/display/display-history.js
index af6d734e..30bc3eec 100644
--- a/ext/js/display/display-history.js
+++ b/ext/js/display/display-history.js
@@ -19,7 +19,7 @@
import {EventDispatcher, generateId, isObject} from '../core.js';
/**
- * @augments EventDispatcher<import('display-history').EventType>
+ * @augments EventDispatcher<import('display-history').Events>
*/
export class DisplayHistory extends EventDispatcher {
/**
@@ -161,7 +161,7 @@ export class DisplayHistory extends EventDispatcher {
* @param {boolean} synthetic
*/
_triggerStateChanged(synthetic) {
- this.trigger('stateChanged', /** @type {import('display-history').StateChangedEvent} */ ({synthetic}));
+ this.trigger('stateChanged', {synthetic});
}
/**
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index 79cf79a8..08f640d0 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -34,7 +34,7 @@ import {OptionToggleHotkeyHandler} from './option-toggle-hotkey-handler.js';
import {QueryParser} from './query-parser.js';
/**
- * @augments EventDispatcher<import('display').DisplayEventType>
+ * @augments EventDispatcher<import('display').Events>
*/
export class Display extends EventDispatcher {
/**
@@ -449,9 +449,7 @@ export class Display extends EventDispatcher {
this._updateNestedFrontend(options);
this._updateContentTextScanner(options);
- /** @type {import('display').OptionsUpdatedEvent} */
- const event = {options};
- this.trigger('optionsUpdated', event);
+ this.trigger('optionsUpdated', {options});
}
/**
@@ -716,9 +714,7 @@ export class Display extends EventDispatcher {
*/
_onMessageVisibilityChanged({value}) {
this._frameVisible = value;
- /** @type {import('display').FrameVisibilityChangeEvent} */
- const event = {value};
- this.trigger('frameVisibilityChange', event);
+ this.trigger('frameVisibilityChange', {value});
}
/** */
@@ -796,7 +792,7 @@ export class Display extends EventDispatcher {
}
/**
- * @param {import('display').QueryParserSearchedEvent} details
+ * @param {import('query-parser').EventArgument<'searched'>} details
*/
_onQueryParserSearch({type, dictionaryEntries, sentence, inputInfo: {eventType}, textSource, optionsContext, sentenceOffset}) {
const query = textSource.text();
@@ -869,7 +865,7 @@ export class Display extends EventDispatcher {
}
/**
- * @param {import('dynamic-property').ChangeEventDetails<boolean>} details
+ * @param {import('dynamic-property').EventArgument<boolean, 'change'>} details
*/
_onProgressIndicatorVisibleChanged({value}) {
if (this._progressIndicatorTimer !== null) {
@@ -1646,7 +1642,7 @@ export class Display extends EventDispatcher {
/** */
_closePopups() {
- yomitan.trigger('closePopups');
+ yomitan.triggerClosePopups();
}
/**
@@ -2011,9 +2007,7 @@ export class Display extends EventDispatcher {
/** @type {Promise<unknown>[]} */
const promises = [];
- /** @type {import('display').LogDictionaryEntryDataEvent} */
- const event = {dictionaryEntry, promises};
- this.trigger('logDictionaryEntryData', event);
+ this.trigger('logDictionaryEntryData', {dictionaryEntry, promises});
if (promises.length > 0) {
for (const result2 of await Promise.all(promises)) {
Object.assign(result, result2);
@@ -2031,9 +2025,7 @@ export class Display extends EventDispatcher {
/** */
_triggerContentUpdateStart() {
- /** @type {import('display').ContentUpdateStartEvent} */
- const event = {type: this._contentType, query: this._query};
- this.trigger('contentUpdateStart', event);
+ this.trigger('contentUpdateStart', {type: this._contentType, query: this._query});
}
/**
@@ -2042,15 +2034,11 @@ export class Display extends EventDispatcher {
* @param {number} index
*/
_triggerContentUpdateEntry(dictionaryEntry, element, index) {
- /** @type {import('display').ContentUpdateEntryEvent} */
- const event = {dictionaryEntry, element, index};
- this.trigger('contentUpdateEntry', event);
+ this.trigger('contentUpdateEntry', {dictionaryEntry, element, index});
}
/** */
_triggerContentUpdateComplete() {
- /** @type {import('display').ContentUpdateCompleteEvent} */
- const event = {type: this._contentType};
- this.trigger('contentUpdateComplete', event);
+ this.trigger('contentUpdateComplete', {type: this._contentType});
}
}
diff --git a/ext/js/display/query-parser.js b/ext/js/display/query-parser.js
index 0e7e1e1a..11c5a4ec 100644
--- a/ext/js/display/query-parser.js
+++ b/ext/js/display/query-parser.js
@@ -22,7 +22,7 @@ import {TextScanner} from '../language/text-scanner.js';
import {yomitan} from '../yomitan.js';
/**
- * @augments EventDispatcher<import('display').QueryParserEventType>
+ * @augments EventDispatcher<import('query-parser').Events>
*/
export class QueryParser extends EventDispatcher {
/**
@@ -160,8 +160,7 @@ export class QueryParser extends EventDispatcher {
} = e;
if (type === null || dictionaryEntries === null || sentence === null || optionsContext === null) { return; }
- /** @type {import('display').QueryParserSearchedEvent} */
- const event2 = {
+ this.trigger('searched', {
textScanner,
type,
dictionaryEntries,
@@ -170,8 +169,7 @@ export class QueryParser extends EventDispatcher {
textSource,
optionsContext,
sentenceOffset: this._getSentenceOffset(e.textSource)
- };
- this.trigger('searched', event2);
+ });
}
/**
diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js
index 6767d201..3df3a332 100644
--- a/ext/js/display/search-display-controller.js
+++ b/ext/js/display/search-display-controller.js
@@ -183,7 +183,7 @@ export class SearchDisplayController {
}
/**
- * @param {import('display').OptionsUpdatedEvent} details
+ * @param {import('display').EventArgument<'optionsUpdated'>} details
*/
_onDisplayOptionsUpdated({options}) {
this._clipboardMonitorEnabled = options.clipboard.enableSearchPageMonitor;
@@ -195,7 +195,7 @@ export class SearchDisplayController {
}
/**
- * @param {import('display').ContentUpdateStartEvent} details
+ * @param {import('display').EventArgument<'contentUpdateStart'>} details
*/
_onContentUpdateStart({type, query}) {
let animate = false;
diff --git a/ext/js/display/search-persistent-state-controller.js b/ext/js/display/search-persistent-state-controller.js
index d92ddf68..1bd32f5b 100644
--- a/ext/js/display/search-persistent-state-controller.js
+++ b/ext/js/display/search-persistent-state-controller.js
@@ -19,7 +19,7 @@
import {EventDispatcher} from '../core.js';
/**
- * @augments EventDispatcher<import('display').SearchPersistentStateControllerEventType>
+ * @augments EventDispatcher<import('search-persistent-state-controller').Events>
*/
export class SearchPersistentStateController extends EventDispatcher {
constructor() {
diff --git a/ext/js/dom/panel-element.js b/ext/js/dom/panel-element.js
index d4cb28fd..959ca420 100644
--- a/ext/js/dom/panel-element.js
+++ b/ext/js/dom/panel-element.js
@@ -19,7 +19,7 @@
import {EventDispatcher} from '../core.js';
/**
- * @augments EventDispatcher<import('panel-element').EventType>
+ * @augments EventDispatcher<import('panel-element').Events>
*/
export class PanelElement extends EventDispatcher {
/**
@@ -84,9 +84,9 @@ export class PanelElement extends EventDispatcher {
}
/**
- * @param {import('panel-element').EventType} eventName
- * @param {(details: import('core').SafeAny) => void} callback
- * @returns {void}
+ * @template {import('core').EventNames<import('panel-element').Events>} TName
+ * @param {TName} eventName
+ * @param {(details: import('core').EventArgument<import('panel-element').Events, TName>) => void} callback
*/
on(eventName, callback) {
if (eventName === 'visibilityChanged') {
@@ -100,12 +100,13 @@ export class PanelElement extends EventDispatcher {
});
}
}
- return super.on(eventName, callback);
+ super.on(eventName, callback);
}
/**
- * @param {import('panel-element').EventType} eventName
- * @param {(details: import('core').SafeAny) => void} callback
+ * @template {import('core').EventNames<import('panel-element').Events>} TName
+ * @param {TName} eventName
+ * @param {(details: import('core').EventArgument<import('panel-element').Events, TName>) => void} callback
* @returns {boolean}
*/
off(eventName, callback) {
diff --git a/ext/js/dom/popup-menu.js b/ext/js/dom/popup-menu.js
index 72df82a0..61f20ba8 100644
--- a/ext/js/dom/popup-menu.js
+++ b/ext/js/dom/popup-menu.js
@@ -20,7 +20,7 @@ import {EventDispatcher, EventListenerCollection} from '../core.js';
import {querySelectorNotNull} from './query-selector.js';
/**
- * @augments EventDispatcher<import('popup-menu').EventType>
+ * @augments EventDispatcher<import('popup-menu').Events>
*/
export class PopupMenu extends EventDispatcher {
/**
@@ -247,7 +247,7 @@ export class PopupMenu extends EventDispatcher {
{altKey: false, ctrlKey: false, metaKey: false, shiftKey: false}
);
- /** @type {import('popup-menu').MenuCloseEventDetails} */
+ /** @type {import('popup-menu').EventArgument<'close'>} */
const detail = {
menu: this,
item,
diff --git a/ext/js/input/hotkey-handler.js b/ext/js/input/hotkey-handler.js
index da763662..48c2de57 100644
--- a/ext/js/input/hotkey-handler.js
+++ b/ext/js/input/hotkey-handler.js
@@ -22,7 +22,7 @@ import {yomitan} from '../yomitan.js';
/**
* Class which handles hotkey events and actions.
- * @augments EventDispatcher<import('hotkey-handler').EventType>
+ * @augments EventDispatcher<import('hotkey-handler').Events>
*/
export class HotkeyHandler extends EventDispatcher {
/**
@@ -120,25 +120,21 @@ export class HotkeyHandler extends EventDispatcher {
}
/**
- * Adds a single event listener to a specific event.
- * @template [TEventDetails=unknown]
- * @param {import('hotkey-handler').EventType} eventName The string representing the event's name.
- * @param {(details: TEventDetails) => void} callback The event listener callback to add.
- * @returns {void}
+ * @template {import('core').EventNames<import('hotkey-handler').Events>} TName
+ * @param {TName} eventName
+ * @param {(details: import('core').EventArgument<import('hotkey-handler').Events, TName>) => void} callback
*/
on(eventName, callback) {
- const result = super.on(eventName, callback);
+ super.on(eventName, callback);
this._updateHasEventListeners();
this._updateEventHandlers();
- return result;
}
/**
- * Removes a single event listener from a specific event.
- * @template [TEventDetails=unknown]
- * @param {import('hotkey-handler').EventType} eventName The string representing the event's name.
- * @param {(details: TEventDetails) => void} callback The event listener callback to add.
- * @returns {boolean} `true` if the callback was removed, `false` otherwise.
+ * @template {import('core').EventNames<import('hotkey-handler').Events>} TName
+ * @param {TName} eventName
+ * @param {(details: import('core').EventArgument<import('hotkey-handler').Events, TName>) => void} callback
+ * @returns {boolean}
*/
off(eventName, callback) {
const result = super.off(eventName, callback);
diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js
index 164e150e..9c254e44 100644
--- a/ext/js/language/text-scanner.js
+++ b/ext/js/language/text-scanner.js
@@ -22,7 +22,7 @@ import {TextSourceElement} from '../dom/text-source-element.js';
import {yomitan} from '../yomitan.js';
/**
- * @augments EventDispatcher<import('text-scanner').EventType>
+ * @augments EventDispatcher<import('text-scanner').Events>
*/
export class TextScanner extends EventDispatcher {
/**
@@ -1597,7 +1597,7 @@ export class TextScanner extends EventDispatcher {
}
/**
- * @param {string} reason
+ * @param {import('text-scanner').ClearReason} reason
*/
_triggerClear(reason) {
this.trigger('clear', {reason});
diff --git a/ext/js/media/audio-system.js b/ext/js/media/audio-system.js
index 1e8f1be2..c311b96c 100644
--- a/ext/js/media/audio-system.js
+++ b/ext/js/media/audio-system.js
@@ -20,7 +20,7 @@ import {EventDispatcher} from '../core.js';
import {TextToSpeechAudio} from './text-to-speech-audio.js';
/**
- * @augments EventDispatcher<import('audio-system').EventType>
+ * @augments EventDispatcher<import('audio-system').Events>
*/
export class AudioSystem extends EventDispatcher {
constructor() {
diff --git a/ext/js/pages/settings/anki-controller.js b/ext/js/pages/settings/anki-controller.js
index aea94b65..d64034a5 100644
--- a/ext/js/pages/settings/anki-controller.js
+++ b/ext/js/pages/settings/anki-controller.js
@@ -221,7 +221,7 @@ export class AnkiController {
}
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
async _onOptionsChanged({options: {anki}}) {
/** @type {?string} */
@@ -964,7 +964,7 @@ class AnkiCardController {
}
/**
- * @param {import('settings-controller').PermissionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'permissionsChanged'>} details
*/
_onPermissionsChanged({permissions: {permissions}}) {
const permissionsSet = new Set(permissions);
diff --git a/ext/js/pages/settings/anki-templates-controller.js b/ext/js/pages/settings/anki-templates-controller.js
index ac0cc9c2..56e992b0 100644
--- a/ext/js/pages/settings/anki-templates-controller.js
+++ b/ext/js/pages/settings/anki-templates-controller.js
@@ -94,7 +94,7 @@ export class AnkiTemplatesController {
// Private
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
let templates = options.anki.fieldTemplates;
diff --git a/ext/js/pages/settings/audio-controller.js b/ext/js/pages/settings/audio-controller.js
index af05ee70..2b46455f 100644
--- a/ext/js/pages/settings/audio-controller.js
+++ b/ext/js/pages/settings/audio-controller.js
@@ -21,7 +21,7 @@ import {querySelectorNotNull} from '../../dom/query-selector.js';
import {AudioSystem} from '../../media/audio-system.js';
/**
- * @augments EventDispatcher<import('audio-controller').EventType>
+ * @augments EventDispatcher<import('audio-controller').Events>
*/
export class AudioController extends EventDispatcher {
/**
@@ -117,7 +117,7 @@ export class AudioController extends EventDispatcher {
// Private
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
for (const entry of this._audioSourceEntries) {
@@ -163,7 +163,7 @@ export class AudioController extends EventDispatcher {
);
voices.sort(this._textToSpeechVoiceCompare.bind(this));
this._voices = voices;
- this.trigger('voicesUpdated');
+ this.trigger('voicesUpdated', {});
}
/**
diff --git a/ext/js/pages/settings/backup-controller.js b/ext/js/pages/settings/backup-controller.js
index c0e56e96..2ae52925 100644
--- a/ext/js/pages/settings/backup-controller.js
+++ b/ext/js/pages/settings/backup-controller.js
@@ -290,7 +290,7 @@ export class BackupController {
modal.setVisible(false);
};
/**
- * @param {import('panel-element').VisibilityChangedEvent} details
+ * @param {import('panel-element').EventArgument<'visibilityChanged'>} details
*/
const onModalVisibilityChanged = ({visible}) => {
if (visible) { return; }
@@ -644,7 +644,7 @@ export class BackupController {
await yomitan.api.purgeDatabase();
await Dexie.import(file, {progressCallback: this._databaseImportProgressCallback});
yomitan.api.triggerDatabaseUpdated('dictionary', 'import');
- yomitan.trigger('storageChanged');
+ yomitan.triggerStorageChanged();
}
/** */
diff --git a/ext/js/pages/settings/collapsible-dictionary-controller.js b/ext/js/pages/settings/collapsible-dictionary-controller.js
index cff3ad20..341522cf 100644
--- a/ext/js/pages/settings/collapsible-dictionary-controller.js
+++ b/ext/js/pages/settings/collapsible-dictionary-controller.js
@@ -70,7 +70,7 @@ export class CollapsibleDictionaryController {
}
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
this._eventListeners.removeAllEventListeners();
diff --git a/ext/js/pages/settings/dictionary-controller.js b/ext/js/pages/settings/dictionary-controller.js
index db6a73d4..0132fe9e 100644
--- a/ext/js/pages/settings/dictionary-controller.js
+++ b/ext/js/pages/settings/dictionary-controller.js
@@ -473,7 +473,7 @@ export class DictionaryController {
value: dictionaries
}]);
- /** @type {import('settings-controller').DictionarySettingsReorderedEvent} */
+ /** @type {import('settings-controller').EventArgument<'dictionarySettingsReordered'>} */
const event = {source: this};
this._settingsController.trigger('dictionarySettingsReordered', event);
@@ -577,7 +577,7 @@ export class DictionaryController {
// Private
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
this._updateDictionariesEnabledWarnings(options);
@@ -930,7 +930,7 @@ export class DictionaryController {
/** */
_triggerStorageChanged() {
- yomitan.trigger('storageChanged');
+ yomitan.triggerStorageChanged();
}
/** */
diff --git a/ext/js/pages/settings/dictionary-import-controller.js b/ext/js/pages/settings/dictionary-import-controller.js
index 79a62d32..eadfcb91 100644
--- a/ext/js/pages/settings/dictionary-import-controller.js
+++ b/ext/js/pages/settings/dictionary-import-controller.js
@@ -398,6 +398,6 @@ export class DictionaryImportController {
/** */
_triggerStorageChanged() {
- yomitan.trigger('storageChanged');
+ yomitan.triggerStorageChanged();
}
}
diff --git a/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js b/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js
index e92d9e93..e3d84ac2 100644
--- a/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js
+++ b/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js
@@ -313,7 +313,7 @@ class ExtensionKeyboardShortcutHotkeyEntry {
// Private
/**
- * @param {import('keyboard-mouse-input-field').ChangeEvent} e
+ * @param {import('keyboard-mouse-input-field').EventArgument<'change'>} e
*/
_onInputFieldChange(e) {
const {key, modifiers} = e;
diff --git a/ext/js/pages/settings/keyboard-mouse-input-field.js b/ext/js/pages/settings/keyboard-mouse-input-field.js
index f50ca112..0628d065 100644
--- a/ext/js/pages/settings/keyboard-mouse-input-field.js
+++ b/ext/js/pages/settings/keyboard-mouse-input-field.js
@@ -21,7 +21,7 @@ import {DocumentUtil} from '../../dom/document-util.js';
import {HotkeyUtil} from '../../input/hotkey-util.js';
/**
- * @augments EventDispatcher<import('keyboard-mouse-input-field').EventType>
+ * @augments EventDispatcher<import('keyboard-mouse-input-field').Events>
*/
export class KeyboardMouseInputField extends EventDispatcher {
/**
@@ -308,9 +308,7 @@ export class KeyboardMouseInputField extends EventDispatcher {
this._updateDisplayString();
if (changed) {
- /** @type {import('keyboard-mouse-input-field').ChangeEvent} */
- const event = {modifiers: this._modifiers, key: this._key};
- this.trigger('change', event);
+ this.trigger('change', {modifiers: this._modifiers, key: this._key});
}
}
diff --git a/ext/js/pages/settings/keyboard-shortcuts-controller.js b/ext/js/pages/settings/keyboard-shortcuts-controller.js
index cbdae77d..b45c656a 100644
--- a/ext/js/pages/settings/keyboard-shortcuts-controller.js
+++ b/ext/js/pages/settings/keyboard-shortcuts-controller.js
@@ -160,7 +160,7 @@ export class KeyboardShortcutController {
// Private
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
for (const entry of this._entries) {
@@ -395,7 +395,7 @@ class KeyboardShortcutHotkeyEntry {
}
/**
- * @param {import('keyboard-mouse-input-field').ChangeEvent} details
+ * @param {import('keyboard-mouse-input-field').EventArgument<'change'>} details
*/
_onInputFieldChange({key, modifiers}) {
/** @type {import('input').ModifierKey[]} */
diff --git a/ext/js/pages/settings/nested-popups-controller.js b/ext/js/pages/settings/nested-popups-controller.js
index 7eb78148..4f0aa761 100644
--- a/ext/js/pages/settings/nested-popups-controller.js
+++ b/ext/js/pages/settings/nested-popups-controller.js
@@ -50,7 +50,7 @@ export class NestedPopupsController {
// Private
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
this._updatePopupNestingMaxDepth(options.scanning.popupNestingMaxDepth);
diff --git a/ext/js/pages/settings/permissions-origin-controller.js b/ext/js/pages/settings/permissions-origin-controller.js
index 6dacced8..3a9db602 100644
--- a/ext/js/pages/settings/permissions-origin-controller.js
+++ b/ext/js/pages/settings/permissions-origin-controller.js
@@ -60,7 +60,7 @@ export class PermissionsOriginController {
// Private
/**
- * @param {import('settings-controller').PermissionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'permissionsChanged'>} details
*/
_onPermissionsChanged({permissions}) {
this._eventListeners.removeAllEventListeners();
diff --git a/ext/js/pages/settings/permissions-toggle-controller.js b/ext/js/pages/settings/permissions-toggle-controller.js
index 85752a7e..055ce1f4 100644
--- a/ext/js/pages/settings/permissions-toggle-controller.js
+++ b/ext/js/pages/settings/permissions-toggle-controller.js
@@ -47,7 +47,7 @@ export class PermissionsToggleController {
// Private
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
let accessor = null;
@@ -104,7 +104,7 @@ export class PermissionsToggleController {
}
/**
- * @param {import('settings-controller').PermissionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'permissionsChanged'>} details
*/
_onPermissionsChanged({permissions}) {
const permissions2 = permissions.permissions;
diff --git a/ext/js/pages/settings/persistent-storage-controller.js b/ext/js/pages/settings/persistent-storage-controller.js
index 7386edd7..70c9a177 100644
--- a/ext/js/pages/settings/persistent-storage-controller.js
+++ b/ext/js/pages/settings/persistent-storage-controller.js
@@ -82,7 +82,7 @@ export class PersistentStorageController {
const node = document.querySelector('#storage-persistent-fail-warning');
if (node !== null) { node.hidden = isStoragePeristent; }
- yomitan.trigger('storageChanged');
+ yomitan.triggerStorageChanged();
}
/**
diff --git a/ext/js/pages/settings/popup-preview-frame.js b/ext/js/pages/settings/popup-preview-frame.js
index 7828a025..609710ba 100644
--- a/ext/js/pages/settings/popup-preview-frame.js
+++ b/ext/js/pages/settings/popup-preview-frame.js
@@ -140,7 +140,7 @@ export class PopupPreviewFrame {
}
/**
- * @param {import('popup').CustomOuterCssChangedEvent} details
+ * @param {import('popup').EventArgument<'customOuterCssChanged'>} details
*/
_onCustomOuterCssChanged({node, inShadow}) {
if (node === null || inShadow) { return; }
diff --git a/ext/js/pages/settings/profile-conditions-ui.js b/ext/js/pages/settings/profile-conditions-ui.js
index 29e7460f..22e47a9b 100644
--- a/ext/js/pages/settings/profile-conditions-ui.js
+++ b/ext/js/pages/settings/profile-conditions-ui.js
@@ -22,7 +22,7 @@ import {querySelectorNotNull} from '../../dom/query-selector.js';
import {KeyboardMouseInputField} from './keyboard-mouse-input-field.js';
/**
- * @augments EventDispatcher<import('profile-conditions-ui').EventType>
+ * @augments EventDispatcher<import('profile-conditions-ui').Events>
*/
export class ProfileConditionsUI extends EventDispatcher {
/**
@@ -440,9 +440,7 @@ export class ProfileConditionsUI extends EventDispatcher {
* @param {number} count
*/
_triggerConditionGroupCountChanged(count) {
- /** @type {import('profile-conditions-ui').ConditionGroupCountChangedEvent} */
- const event = {count, profileIndex: this._profileIndex};
- this.trigger('conditionGroupCountChanged', event);
+ this.trigger('conditionGroupCountChanged', {count, profileIndex: this._profileIndex});
}
}
@@ -747,7 +745,7 @@ class ProfileConditionUI {
/**
* @param {import('profile-conditions-ui').InputData} details
- * @param {import('keyboard-mouse-input-field').ChangeEvent} event
+ * @param {import('keyboard-mouse-input-field').EventArgument<'change'>} event
*/
_onModifierInputChange({validate, normalize}, event) {
const modifiers = this._joinModifiers(event.modifiers);
@@ -863,10 +861,6 @@ class ProfileConditionUI {
let inputValue = value;
let inputStep = null;
let showMouseButton = false;
- /** @type {import('event-listener-collection').AddEventListenerArgs[]} */
- const events1 = [];
- /** @type {import('event-listener-collection').OnArgs[]} */
- const events2 = [];
/** @type {import('profile-conditions-ui').InputData} */
const inputData = {validate, normalize};
const node = this._valueInput;
@@ -875,7 +869,6 @@ class ProfileConditionUI {
case 'integer':
inputType = 'number';
inputStep = '1';
- events1.push([node, 'change', this._onValueInputChange.bind(this, inputData), false]);
break;
case 'modifierKeys':
case 'modifierInputs':
@@ -883,10 +876,6 @@ class ProfileConditionUI {
showMouseButton = (type === 'modifierInputs');
this._kbmInputField = this._parent.parent.createKeyboardMouseInputField(node, this._mouseButton);
this._kbmInputField.prepare(null, this._splitModifiers(value), showMouseButton, false);
- events2.push([this._kbmInputField, 'change', this._onModifierInputChange.bind(this, inputData)]);
- break;
- default: // 'string'
- events1.push([node, 'change', this._onValueInputChange.bind(this, inputData), false]);
break;
}
@@ -902,11 +891,17 @@ class ProfileConditionUI {
node.removeAttribute('step');
}
this._mouseButtonContainer.hidden = !showMouseButton;
- for (const args of events1) {
- this._inputEventListeners.addEventListener(...args);
- }
- for (const args of events2) {
- this._inputEventListeners.on(...args);
+
+ switch (type) {
+ case 'modifierKeys':
+ case 'modifierInputs':
+ if (this._kbmInputField !== null) {
+ this._inputEventListeners.on(this._kbmInputField, 'change', this._onModifierInputChange.bind(this, inputData));
+ }
+ break;
+ default: // 'integer', 'string'
+ this._inputEventListeners.addEventListener(node, 'change', this._onValueInputChange.bind(this, inputData), false);
+ break;
}
return this._validateValue(value, validate);
diff --git a/ext/js/pages/settings/profile-controller.js b/ext/js/pages/settings/profile-controller.js
index c54bfe73..54a41058 100644
--- a/ext/js/pages/settings/profile-controller.js
+++ b/ext/js/pages/settings/profile-controller.js
@@ -475,7 +475,7 @@ export class ProfileController {
}
/**
- * @param {import('profile-conditions-ui').ConditionGroupCountChangedEvent} details
+ * @param {import('profile-conditions-ui').EventArgument<'conditionGroupCountChanged'>} details
*/
_onConditionGroupCountChanged({count, profileIndex}) {
if (profileIndex >= 0 && profileIndex < this._profileEntryList.length) {
diff --git a/ext/js/pages/settings/recommended-permissions-controller.js b/ext/js/pages/settings/recommended-permissions-controller.js
index b19311aa..a870de50 100644
--- a/ext/js/pages/settings/recommended-permissions-controller.js
+++ b/ext/js/pages/settings/recommended-permissions-controller.js
@@ -48,7 +48,7 @@ export class RecommendedPermissionsController {
// Private
/**
- * @param {import('settings-controller').PermissionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'permissionsChanged'>} details
*/
_onPermissionsChanged({permissions}) {
this._eventListeners.removeAllEventListeners();
diff --git a/ext/js/pages/settings/scan-inputs-controller.js b/ext/js/pages/settings/scan-inputs-controller.js
index eb526863..4854c28f 100644
--- a/ext/js/pages/settings/scan-inputs-controller.js
+++ b/ext/js/pages/settings/scan-inputs-controller.js
@@ -110,7 +110,7 @@ export class ScanInputsController {
// Private
/**
- * @param {import('settings-controller').ScanInputsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'scanInputsChanged'>} details
*/
_onScanInputsChanged({source}) {
if (source === this) { return; }
@@ -118,7 +118,7 @@ export class ScanInputsController {
}
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
const {inputs} = options.scanning;
@@ -190,7 +190,7 @@ export class ScanInputsController {
/** */
_triggerScanInputsChanged() {
- /** @type {import('settings-controller').ScanInputsChangedEvent} */
+ /** @type {import('settings-controller').EventArgument<'scanInputsChanged'>} */
const event = {source: this};
this._settingsController.trigger('scanInputsChanged', event);
}
@@ -312,7 +312,7 @@ class ScanInputField {
// Private
/**
- * @param {import('keyboard-mouse-input-field').ChangeEvent} details
+ * @param {import('keyboard-mouse-input-field').EventArgument<'change'>} details
*/
_onIncludeValueChange({modifiers}) {
const modifiers2 = this._joinModifiers(modifiers);
@@ -320,7 +320,7 @@ class ScanInputField {
}
/**
- * @param {import('keyboard-mouse-input-field').ChangeEvent} details
+ * @param {import('keyboard-mouse-input-field').EventArgument<'change'>} details
*/
_onExcludeValueChange({modifiers}) {
const modifiers2 = this._joinModifiers(modifiers);
diff --git a/ext/js/pages/settings/scan-inputs-simple-controller.js b/ext/js/pages/settings/scan-inputs-simple-controller.js
index ddb68825..f0255595 100644
--- a/ext/js/pages/settings/scan-inputs-simple-controller.js
+++ b/ext/js/pages/settings/scan-inputs-simple-controller.js
@@ -67,7 +67,7 @@ export class ScanInputsSimpleController {
// Private
/**
- * @param {import('settings-controller').ScanInputsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'scanInputsChanged'>} details
*/
_onScanInputsChanged({source}) {
if (source === this) { return; }
@@ -75,7 +75,7 @@ export class ScanInputsSimpleController {
}
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
const {scanning: {inputs}} = options;
@@ -236,7 +236,7 @@ export class ScanInputsSimpleController {
*/
async _modifyProfileSettings(targets) {
await this._settingsController.modifyProfileSettings(targets);
- /** @type {import('settings-controller').ScanInputsChangedEvent} */
+ /** @type {import('settings-controller').EventArgument<'scanInputsChanged'>} */
const event = {source: this};
this._settingsController.trigger('scanInputsChanged', event);
}
diff --git a/ext/js/pages/settings/secondary-search-dictionary-controller.js b/ext/js/pages/settings/secondary-search-dictionary-controller.js
index f24f6ea3..7f0882b8 100644
--- a/ext/js/pages/settings/secondary-search-dictionary-controller.js
+++ b/ext/js/pages/settings/secondary-search-dictionary-controller.js
@@ -66,7 +66,7 @@ export class SecondarySearchDictionaryController {
}
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
this._eventListeners.removeAllEventListeners();
diff --git a/ext/js/pages/settings/sentence-termination-characters-controller.js b/ext/js/pages/settings/sentence-termination-characters-controller.js
index 7fd90b28..f7793943 100644
--- a/ext/js/pages/settings/sentence-termination-characters-controller.js
+++ b/ext/js/pages/settings/sentence-termination-characters-controller.js
@@ -105,7 +105,7 @@ export class SentenceTerminationCharactersController {
// Private
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
for (const entry of this._entries) {
diff --git a/ext/js/pages/settings/settings-controller.js b/ext/js/pages/settings/settings-controller.js
index 1b46c745..52b777a3 100644
--- a/ext/js/pages/settings/settings-controller.js
+++ b/ext/js/pages/settings/settings-controller.js
@@ -23,7 +23,7 @@ import {HtmlTemplateCollection} from '../../dom/html-template-collection.js';
import {yomitan} from '../../yomitan.js';
/**
- * @augments EventDispatcher<import('settings-controller').EventType>
+ * @augments EventDispatcher<import('settings-controller').Events>
*/
export class SettingsController extends EventDispatcher {
constructor() {
@@ -234,7 +234,7 @@ export class SettingsController extends EventDispatcher {
*/
_setProfileIndex(value, canUpdateProfileIndex) {
this._profileIndex = value;
- this.trigger('optionsContextChanged');
+ this.trigger('optionsContextChanged', {});
this._onOptionsUpdatedInternal(canUpdateProfileIndex);
}
@@ -253,9 +253,7 @@ export class SettingsController extends EventDispatcher {
const optionsContext = this.getOptionsContext();
try {
const options = await this.getOptions();
- /** @type {import('settings-controller').OptionsChangedEvent} */
- const event = {options, optionsContext};
- this.trigger('optionsChanged', event);
+ this.trigger('optionsChanged', {options, optionsContext});
} catch (e) {
if (canUpdateProfileIndex) {
this._setProfileIndex(0, false);
@@ -339,9 +337,7 @@ export class SettingsController extends EventDispatcher {
if (!this.hasListeners(eventName)) { return; }
const permissions = await this._permissionsUtil.getAllPermissions();
- /** @type {import('settings-controller').PermissionsChangedEvent} */
- const event = {permissions};
- this.trigger(eventName, event);
+ this.trigger(eventName, {permissions});
}
/**
diff --git a/ext/js/pages/settings/sort-frequency-dictionary-controller.js b/ext/js/pages/settings/sort-frequency-dictionary-controller.js
index 2c56f023..3fdd66c7 100644
--- a/ext/js/pages/settings/sort-frequency-dictionary-controller.js
+++ b/ext/js/pages/settings/sort-frequency-dictionary-controller.js
@@ -68,7 +68,7 @@ export class SortFrequencyDictionaryController {
}
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
const {sortFrequencyDictionary, sortFrequencyDictionaryOrder} = options.general;
diff --git a/ext/js/pages/settings/translation-text-replacements-controller.js b/ext/js/pages/settings/translation-text-replacements-controller.js
index ebd1b58d..9f3fda00 100644
--- a/ext/js/pages/settings/translation-text-replacements-controller.js
+++ b/ext/js/pages/settings/translation-text-replacements-controller.js
@@ -110,7 +110,7 @@ export class TranslationTextReplacementsController {
// Private
/**
- * @param {import('settings-controller').OptionsChangedEvent} details
+ * @param {import('settings-controller').EventArgument<'optionsChanged'>} details
*/
_onOptionsChanged({options}) {
for (const entry of this._entries) {
diff --git a/ext/js/yomitan.js b/ext/js/yomitan.js
index 621e9cf0..8980c589 100644
--- a/ext/js/yomitan.js
+++ b/ext/js/yomitan.js
@@ -50,7 +50,7 @@ if (checkChromeNotAvailable()) {
/**
* The Yomitan class is a core component through which various APIs are handled and invoked.
- * @augments EventDispatcher<import('extension').ExtensionEventType>
+ * @augments EventDispatcher<import('application').Events>
*/
export class Yomitan extends EventDispatcher {
/**
@@ -208,12 +208,22 @@ export class Yomitan extends EventDispatcher {
if (this._isTriggeringExtensionUnloaded) { return; }
try {
this._isTriggeringExtensionUnloaded = true;
- this.trigger('extensionUnloaded');
+ this.trigger('extensionUnloaded', {});
} finally {
this._isTriggeringExtensionUnloaded = false;
}
}
+ /** */
+ triggerStorageChanged() {
+ this.trigger('storageChanged', {});
+ }
+
+ /** */
+ triggerClosePopups() {
+ this.trigger('closePopups', {});
+ }
+
// Private
/**
diff --git a/types/ext/application.d.ts b/types/ext/application.d.ts
index ac594abc..5c103fd7 100644
--- a/types/ext/application.d.ts
+++ b/types/ext/application.d.ts
@@ -19,6 +19,7 @@ import type {TokenString} from './core';
import type {SearchMode} from './display';
import type {FrameEndpointReadyDetails, FrameEndpointConnectedDetails} from './frame-client';
import type {DatabaseUpdateType, DatabaseUpdateCause} from './backend';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
import type {
ApiMap as BaseApiMap,
ApiHandler as BaseApiHandler,
@@ -146,3 +147,22 @@ export type ApiMap = BaseApiMap<ApiSurface>;
export type ApiHandler<TName extends ApiNames> = BaseApiHandler<ApiSurface[TName]>;
export type ApiReturn<TName extends ApiNames> = BaseApiReturn<ApiSurface[TName]>;
+
+export type Events = {
+ extensionUnloaded: Record<string, never>;
+ optionsUpdated: {
+ source: string;
+ };
+ databaseUpdated: {
+ type: DatabaseUpdateType;
+ cause: DatabaseUpdateCause;
+ };
+ zoomChanged: {
+ oldZoomFactor: number;
+ newZoomFactor: number;
+ };
+ closePopups: Record<string, never>;
+ storageChanged: Record<string, never>;
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
diff --git a/types/ext/audio-controller.d.ts b/types/ext/audio-controller.d.ts
index e8317aaf..cc1887fb 100644
--- a/types/ext/audio-controller.d.ts
+++ b/types/ext/audio-controller.d.ts
@@ -15,7 +15,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-export type EventType = 'voicesUpdated';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
+
+export type Events = {
+ voicesUpdated: Record<string, never>;
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
export type VoiceInfo = {
voice: SpeechSynthesisVoice;
diff --git a/types/ext/audio-system.d.ts b/types/ext/audio-system.d.ts
index e9766ed1..715f6afe 100644
--- a/types/ext/audio-system.d.ts
+++ b/types/ext/audio-system.d.ts
@@ -15,4 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-export type EventType = 'voiceschanged';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
+
+export type Events = {
+ voiceschanged: Event;
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
diff --git a/types/ext/clipboard-monitor.d.ts b/types/ext/clipboard-monitor.d.ts
index f8cf7d02..b0bb840b 100644
--- a/types/ext/clipboard-monitor.d.ts
+++ b/types/ext/clipboard-monitor.d.ts
@@ -15,12 +15,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-export type EventType = 'change';
-
-export type ChangeEvent = {
- text: string;
-};
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
export type ClipboardReaderLike = {
getText: (useRichText: boolean) => Promise<string>;
};
+
+export type Events = {
+ change: {
+ text: string;
+ };
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
diff --git a/types/ext/core.d.ts b/types/ext/core.d.ts
index c71a8ec4..b94b649b 100644
--- a/types/ext/core.d.ts
+++ b/types/ext/core.d.ts
@@ -88,3 +88,17 @@ export type MessageHandlerMapInit = MessageHandlerMapInitItem[];
export type MessageHandlerMapInitItem = [key: string, handlerDetails: MessageHandler];
export type Timeout = number | NodeJS.Timeout;
+
+export type EventSurface = {[name: string]: unknown};
+
+export type EventNames<TSurface extends EventSurface> = keyof TSurface & string;
+
+export type EventArgument<TSurface extends EventSurface, TName extends EventNames<TSurface>> = TSurface[TName];
+
+export type EventDispatcherOffGeneric = {
+ off(eventName: string, callback: (...args: SafeAny) => void): boolean;
+};
+
+export type EventHandler<TSurface extends EventSurface, TName extends EventNames<TSurface>> = (details: EventArgument<TSurface, TName>) => void;
+
+export type EventHandlerAny = (details: SafeAny) => void;
diff --git a/types/ext/cross-frame-api.d.ts b/types/ext/cross-frame-api.d.ts
index b9cf8ad1..8ddca6e7 100644
--- a/types/ext/cross-frame-api.d.ts
+++ b/types/ext/cross-frame-api.d.ts
@@ -15,9 +15,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import type {CrossFrameAPIPort} from '../../ext/js/comm/cross-frame-api.js';
import type * as Core from './core';
-export type CrossFrameAPIPortEventType = 'disconnect';
+export type CrossFrameAPIPortEvents = {
+ disconnect: CrossFrameAPIPort;
+};
export type AcknowledgeMessage = {
type: 'ack';
diff --git a/types/ext/display-history.d.ts b/types/ext/display-history.d.ts
index 2ba5006b..3a99d443 100644
--- a/types/ext/display-history.d.ts
+++ b/types/ext/display-history.d.ts
@@ -15,6 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
import type * as Display from './display';
export type Entry = {
@@ -30,8 +31,10 @@ export type EntryState = Display.HistoryState;
export type EntryContent = Display.HistoryContent;
-export type EventType = 'stateChanged';
-
-export type StateChangedEvent = {
- synthetic: boolean;
+export type Events = {
+ stateChanged: {
+ synthetic: boolean;
+ };
};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
diff --git a/types/ext/display.d.ts b/types/ext/display.d.ts
index aa0f0353..bafb1fa1 100644
--- a/types/ext/display.d.ts
+++ b/types/ext/display.d.ts
@@ -18,13 +18,12 @@
import type {DisplayContentManager} from '../../ext/js/display/display-content-manager';
import type {HotkeyHelpController} from '../../ext/js/input/hotkey-help-controller';
import type {JapaneseUtil} from '../../ext/js/language/sandbox/japanese-util';
-import type {TextScanner} from '../../ext/js/language/text-scanner';
import type * as Core from './core';
import type * as Dictionary from './dictionary';
import type * as Extension from './extension';
import type * as Settings from './settings';
import type * as TextScannerTypes from './text-scanner';
-import type * as TextSource from './text-source';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
export type HistoryMode = 'clear' | 'overwrite' | 'new';
@@ -114,8 +113,6 @@ export type HistoryContent = {
contentOrigin?: Extension.ContentOrigin;
};
-export type SearchPersistentStateControllerEventType = 'modeChange';
-
export type SearchMode = null | 'popup' | 'action-popup';
export type GetSearchContextCallback = TextScannerTypes.GetSearchContextCallbackSync;
@@ -134,56 +131,33 @@ export type QueryParserOptions = {
scanning: TextScannerTypes.Options;
};
-export type QueryParserEventType = 'searched';
-
-export type QueryParserSearchedEvent = {
- textScanner: TextScanner;
- type: PageType;
- dictionaryEntries: Dictionary.DictionaryEntry[];
- sentence: HistoryStateSentence;
- inputInfo: TextScannerTypes.InputInfo;
- textSource: TextSource.TextSource;
- optionsContext: Settings.OptionsContext;
- sentenceOffset: number | null;
-};
-
-export type DisplayEventType = (
- 'optionsUpdated' |
- 'frameVisibilityChange' |
- 'logDictionaryEntryData' |
- 'contentClear' |
- 'contentUpdateStart' |
- 'contentUpdateEntry' |
- 'contentUpdateComplete'
-);
-
-export type OptionsUpdatedEvent = {
- options: Settings.ProfileOptions;
-};
-
-export type FrameVisibilityChangeEvent = {
- value: boolean;
-};
-
-export type LogDictionaryEntryDataEvent = {
- dictionaryEntry: Dictionary.DictionaryEntry;
- promises: Promise<unknown>[];
-};
-
-export type ContentUpdateStartEvent = {
- type: PageType;
- query: string;
-};
-
-export type ContentUpdateEntryEvent = {
- dictionaryEntry: Dictionary.DictionaryEntry;
- element: Element;
- index: number;
-};
-
-export type ContentUpdateCompleteEvent = {
- type: PageType;
-};
+export type Events = {
+ optionsUpdated: {
+ options: Settings.ProfileOptions;
+ };
+ frameVisibilityChange: {
+ value: boolean;
+ };
+ logDictionaryEntryData: {
+ dictionaryEntry: Dictionary.DictionaryEntry;
+ promises: Promise<unknown>[];
+ };
+ contentClear: Record<string, never>;
+ contentUpdateStart: {
+ type: PageType;
+ query: string;
+ };
+ contentUpdateEntry: {
+ dictionaryEntry: Dictionary.DictionaryEntry;
+ element: Element;
+ index: number;
+ };
+ contentUpdateComplete: {
+ type: PageType;
+ };
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
export type ConfigureMessageDetails = {
depth: number;
diff --git a/types/ext/dynamic-property.d.ts b/types/ext/dynamic-property.d.ts
index ba15257a..8dde372b 100644
--- a/types/ext/dynamic-property.d.ts
+++ b/types/ext/dynamic-property.d.ts
@@ -15,8 +15,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-export type EventType = 'change';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
-export type ChangeEventDetails<T = unknown> = {
- value: T;
+export type Events<T = unknown> = {
+ change: {
+ value: T;
+ };
};
+
+export type EventArgument<T, TName extends EventNames<Events<T>>> = BaseEventArgument<Events<T>, TName>;
diff --git a/types/ext/event-listener-collection.d.ts b/types/ext/event-listener-collection.d.ts
index 988baa76..415c48c4 100644
--- a/types/ext/event-listener-collection.d.ts
+++ b/types/ext/event-listener-collection.d.ts
@@ -15,7 +15,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import type {EventDispatcher} from '../../ext/js/core';
import type * as Core from './core';
export type EventListenerFunction = (...args: Core.SafeAny[]) => unknown;
@@ -55,7 +54,7 @@ export type ExtensionEventDetails = {
export type EventDispatcherDetails = {
type: 'off';
- target: EventDispatcher<string>;
+ target: Core.EventDispatcherOffGeneric;
eventName: string;
callback: EventListenerFunction;
};
@@ -68,9 +67,3 @@ export type AddEventListenerArgs = [
listener: EventListener | EventListenerObject | EventListenerFunction,
options?: AddEventListenerOptions | boolean,
];
-
-export type OnArgs = [
- target: EventDispatcher<string>,
- eventName: string,
- callback: (details: Core.SafeAny) => void,
-];
diff --git a/types/ext/extension.d.ts b/types/ext/extension.d.ts
index 5a244566..5c4aa175 100644
--- a/types/ext/extension.d.ts
+++ b/types/ext/extension.d.ts
@@ -47,8 +47,6 @@ export type ChromeRuntimeSendMessageArgs5 = [
export type ChromeRuntimeSendMessageArgs = ChromeRuntimeSendMessageArgs1 | ChromeRuntimeSendMessageArgs2 | ChromeRuntimeSendMessageArgs3 | ChromeRuntimeSendMessageArgs4 | ChromeRuntimeSendMessageArgs5;
-export type ExtensionEventType = 'extensionUnloaded' | 'optionsUpdated' | 'databaseUpdated' | 'zoomChanged' | 'closePopups' | 'dynamicLoaderSentinel' | 'storageChanged';
-
export type HtmlElementWithContentWindow = HTMLIFrameElement | HTMLFrameElement | HTMLObjectElement;
export type ContentOrigin = {
diff --git a/types/ext/hotkey-handler.d.ts b/types/ext/hotkey-handler.d.ts
index 7b2b4cb3..c108d347 100644
--- a/types/ext/hotkey-handler.d.ts
+++ b/types/ext/hotkey-handler.d.ts
@@ -15,12 +15,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import type * as Input from './input';
-
-export type EventType = 'keydownNonHotkey';
+import type {ModifierKey} from './input';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
export type HotkeyInfo = {
- modifiers: Set<Input.ModifierKey>;
+ modifiers: Set<ModifierKey>;
action: string;
argument: unknown;
};
@@ -28,3 +27,9 @@ export type HotkeyInfo = {
export type HotkeyHandlers = {
handlers: HotkeyInfo[];
};
+
+export type Events = {
+ keydownNonHotkey: KeyboardEvent;
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
diff --git a/types/ext/keyboard-mouse-input-field.d.ts b/types/ext/keyboard-mouse-input-field.d.ts
index 321e49cc..572ffc56 100644
--- a/types/ext/keyboard-mouse-input-field.d.ts
+++ b/types/ext/keyboard-mouse-input-field.d.ts
@@ -15,11 +15,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import type * as Input from './input';
+import type {Modifier} from './input';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
-export type EventType = 'change';
-
-export type ChangeEvent = {
- key: string | null;
- modifiers: Input.Modifier[];
+export type Events = {
+ change: {
+ key: string | null;
+ modifiers: Modifier[];
+ };
};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
diff --git a/types/ext/log.d.ts b/types/ext/log.d.ts
index 904bf848..e8ca4c43 100644
--- a/types/ext/log.d.ts
+++ b/types/ext/log.d.ts
@@ -15,9 +15,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-export type LogLevel = 'log' | 'info' | 'debug' | 'warn' | 'error';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
-export type LoggerEventType = 'log';
+export type LogLevel = 'log' | 'info' | 'debug' | 'warn' | 'error';
export type LogContext = {
url: string;
@@ -33,3 +33,13 @@ export type LogContext = {
* `2` _error_ level.
*/
export type LogErrorLevelValue = 0 | 1 | 2;
+
+export type Events = {
+ log: {
+ error: unknown;
+ level: LogLevel;
+ context: LogContext;
+ };
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
diff --git a/types/ext/panel-element.d.ts b/types/ext/panel-element.d.ts
index d267b836..164acba5 100644
--- a/types/ext/panel-element.d.ts
+++ b/types/ext/panel-element.d.ts
@@ -15,23 +15,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-export type EventType = 'visibilityChanged' | 'closeCompleted';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
-export type VisibilityChangedEvent = {
- visible: boolean;
+export type Events = {
+ visibilityChanged: {
+ visible: boolean;
+ };
+ closeCompleted: {
+ reopening: boolean;
+ };
};
-export type CloseCompletedEvent = {
- reopening: boolean;
-};
-
-/* eslint-disable @stylistic/ts/indent */
-export type Event<T extends EventType> = (
- T extends 'visibilityChanged' ? VisibilityChangedEvent :
- T extends 'closeCompleted' ? CloseCompletedEvent :
- never
-);
-/* eslint-enable @stylistic/ts/indent */
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
export type ConstructorDetails = {
node: HTMLElement;
diff --git a/types/ext/popup-menu.d.ts b/types/ext/popup-menu.d.ts
index b6e37316..71b94468 100644
--- a/types/ext/popup-menu.d.ts
+++ b/types/ext/popup-menu.d.ts
@@ -16,8 +16,22 @@
*/
import type {PopupMenu} from '../../ext/js/dom/popup-menu';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
-export type EventType = 'close';
+export type Events = {
+ close: {
+ menu: PopupMenu;
+ item: HTMLElement | null;
+ action: string | null;
+ cause: CloseReason;
+ altKey: boolean;
+ ctrlKey: boolean;
+ metaKey: boolean;
+ shiftKey: boolean;
+ };
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
export type CloseReason = 'close' | 'outside' | 'item' | 'resize';
@@ -25,17 +39,6 @@ export type MenuOpenEventDetails = {
menu: PopupMenu;
};
-export type MenuCloseEventDetails = {
- menu: PopupMenu;
- item: HTMLElement | null;
- action: string | null;
- cause: CloseReason;
- altKey: boolean;
- ctrlKey: boolean;
- metaKey: boolean;
- shiftKey: boolean;
-};
-
export type MenuOpenEvent = CustomEvent<MenuOpenEventDetails>;
-export type MenuCloseEvent = CustomEvent<MenuCloseEventDetails>;
+export type MenuCloseEvent = CustomEvent<EventArgument<'close'>>;
diff --git a/types/ext/popup.d.ts b/types/ext/popup.d.ts
index 65725f96..6f39f1e4 100644
--- a/types/ext/popup.d.ts
+++ b/types/ext/popup.d.ts
@@ -21,6 +21,7 @@ import type {PopupWindow} from '../../ext/js/app/popup-window';
import type {FrameOffsetForwarder} from '../../ext/js/comm/frame-offset-forwarder';
import type * as DocumentUtil from './document-util';
import type * as Settings from './settings';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
export type PopupAny = Popup | PopupWindow | PopupProxy;
@@ -90,20 +91,6 @@ export type ValidSize = {
valid: boolean;
};
-export type CustomOuterCssChangedEvent = {
- node: HTMLStyleElement | HTMLLinkElement | null;
- useWebExtensionApi: boolean;
- inShadow: boolean;
-};
-
-export type PopupAnyEventType = PopupEventType | PopupProxyEventType | PopupWindowEventType;
-
-export type PopupEventType = 'customOuterCssChanged' | 'framePointerOver' | 'framePointerOut' | 'offsetNotFound';
-
-export type PopupProxyEventType = 'offsetNotFound';
-
-export type PopupWindowEventType = never;
-
export type PopupConstructorDetails = {
/** The ID of the popup. */
id: string;
@@ -134,3 +121,16 @@ export type PopupProxyConstructorDetails = {
/** A `FrameOffsetForwarder` instance which is used to determine frame positioning. */
frameOffsetForwarder: FrameOffsetForwarder | null;
};
+
+export type Events = {
+ customOuterCssChanged: {
+ node: HTMLStyleElement | HTMLLinkElement | null;
+ useWebExtensionApi: boolean;
+ inShadow: boolean;
+ };
+ framePointerOver: Record<string, never>;
+ framePointerOut: Record<string, never>;
+ offsetNotFound: Record<string, never>;
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
diff --git a/types/ext/profile-conditions-ui.d.ts b/types/ext/profile-conditions-ui.d.ts
index 7aa22e93..4e326781 100644
--- a/types/ext/profile-conditions-ui.d.ts
+++ b/types/ext/profile-conditions-ui.d.ts
@@ -16,8 +16,16 @@
*/
import type * as Settings from './settings';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
-export type EventType = 'conditionGroupCountChanged';
+export type Events = {
+ conditionGroupCountChanged: {
+ count: number;
+ profileIndex: number;
+ };
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
export type DescriptorType = Settings.ProfileConditionType;
@@ -49,11 +57,6 @@ export type Operator = {
normalize: NormalizeFunction | null;
};
-export type ConditionGroupCountChangedEvent = {
- count: number;
- profileIndex: number;
-};
-
export type DescriptorInfo = {
name: DescriptorType;
displayName: string;
diff --git a/types/ext/query-parser.d.ts b/types/ext/query-parser.d.ts
new file mode 100644
index 00000000..ea711d9e
--- /dev/null
+++ b/types/ext/query-parser.d.ts
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 Yomitan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import type {TextScanner} from '../../ext/js/language/text-scanner';
+import type {DictionaryEntry} from './dictionary';
+import type {OptionsContext} from './settings';
+import type {InputInfo} from './text-scanner';
+import type {TextSource} from './text-source';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
+import type {HistoryStateSentence, PageType} from './display';
+
+export type Events = {
+ searched: {
+ textScanner: TextScanner;
+ type: PageType;
+ dictionaryEntries: DictionaryEntry[];
+ sentence: HistoryStateSentence;
+ inputInfo: InputInfo;
+ textSource: TextSource;
+ optionsContext: OptionsContext;
+ sentenceOffset: number | null;
+ };
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
diff --git a/types/ext/search-persistent-state-controller.d.ts b/types/ext/search-persistent-state-controller.d.ts
new file mode 100644
index 00000000..47b07119
--- /dev/null
+++ b/types/ext/search-persistent-state-controller.d.ts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 Yomitan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import type {SearchMode} from './display';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
+
+export type Events = {
+ modeChange: {
+ mode: SearchMode;
+ };
+};
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
diff --git a/types/ext/settings-controller.d.ts b/types/ext/settings-controller.d.ts
index 697de878..e0633c21 100644
--- a/types/ext/settings-controller.d.ts
+++ b/types/ext/settings-controller.d.ts
@@ -21,29 +21,30 @@ import type {ScanInputsSimpleController} from '../../ext/js/pages/settings/scan-
import type * as Core from './core';
import type * as Settings from './settings';
import type * as SettingsModifications from './settings-modifications';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
export type PageExitPrevention = {
end: () => void;
};
-export type EventType = 'optionsChanged' | 'optionsContextChanged' | 'permissionsChanged' | 'dictionarySettingsReordered' | 'scanInputsChanged';
-
-export type OptionsChangedEvent = {
- options: Settings.ProfileOptions;
- optionsContext: Settings.OptionsContext;
-};
-
-export type PermissionsChangedEvent = {
- permissions: chrome.permissions.Permissions;
+export type Events = {
+ optionsChanged: {
+ options: Settings.ProfileOptions;
+ optionsContext: Settings.OptionsContext;
+ };
+ optionsContextChanged: Record<string, never>;
+ permissionsChanged: {
+ permissions: chrome.permissions.Permissions;
+ };
+ dictionarySettingsReordered: {
+ source: DictionaryController;
+ };
+ scanInputsChanged: {
+ source: ScanInputsController | ScanInputsSimpleController;
+ };
};
-export type DictionarySettingsReorderedEvent = {
- source: DictionaryController;
-};
-
-export type ScanInputsChangedEvent = {
- source: ScanInputsController | ScanInputsSimpleController;
-};
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
export type SettingsRead<THasScope extends boolean> = THasScope extends true ? SettingsModifications.ScopedRead : SettingsModifications.Read;
diff --git a/types/ext/text-scanner.d.ts b/types/ext/text-scanner.d.ts
index d56d623a..e2779e4d 100644
--- a/types/ext/text-scanner.d.ts
+++ b/types/ext/text-scanner.d.ts
@@ -21,6 +21,7 @@ import type * as Display from './display';
import type * as Input from './input';
import type * as Settings from './settings';
import type * as TextSource from './text-source';
+import type {EventNames, EventArgument as BaseEventArgument} from './core';
export type SearchResultDetail = {
documentTitle: string;
@@ -118,7 +119,16 @@ export type InputInfoDetail = {
restoreSelection: boolean;
};
-export type EventType = 'searched' | 'clear';
+export type Events = {
+ searched: SearchedEventDetails;
+ clear: {
+ reason: ClearReason;
+ };
+};
+
+export type ClearReason = 'mousedown';
+
+export type EventArgument<TName extends EventNames<Events>> = BaseEventArgument<Events, TName>;
export type GetSearchContextCallback = GetSearchContextCallbackSync | GetSearchContextCallbackAsync;