summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/js/app/content-script-main.js14
-rw-r--r--ext/js/app/frontend.js35
-rw-r--r--ext/js/app/popup-factory.js15
-rw-r--r--ext/js/app/popup-proxy.js8
-rw-r--r--ext/js/app/popup-window.js16
-rw-r--r--ext/js/app/popup.js16
-rw-r--r--ext/js/application.js (renamed from ext/js/yomitan.js)9
-rw-r--r--ext/js/background/background-main.js7
-rw-r--r--ext/js/comm/cross-frame-api.js12
-rw-r--r--ext/js/comm/frame-ancestry-handler.js10
-rw-r--r--ext/js/comm/frame-endpoint.js12
-rw-r--r--ext/js/comm/frame-offset-forwarder.js12
-rw-r--r--ext/js/data/anki-note-builder.js10
-rw-r--r--ext/js/display/display-anki.js15
-rw-r--r--ext/js/display/display-audio.js3
-rw-r--r--ext/js/display/display-content-manager.js3
-rw-r--r--ext/js/display/display-generator.js9
-rw-r--r--ext/js/display/display-profile-selection.js7
-rw-r--r--ext/js/display/display.js48
-rw-r--r--ext/js/display/option-toggle-hotkey-handler.js7
-rw-r--r--ext/js/display/popup-main.js13
-rw-r--r--ext/js/display/query-parser.js10
-rw-r--r--ext/js/display/search-display-controller.js9
-rw-r--r--ext/js/display/search-main.js14
-rw-r--r--ext/js/dom/style-util.js11
-rw-r--r--ext/js/input/hotkey-handler.js6
-rw-r--r--ext/js/input/hotkey-help-controller.js9
-rw-r--r--ext/js/language/text-scanner.js10
-rw-r--r--ext/js/pages/action-popup-main.js34
-rw-r--r--ext/js/pages/info-main.js29
-rw-r--r--ext/js/pages/permissions-main.js18
-rw-r--r--ext/js/pages/settings/anki-controller.js5
-rw-r--r--ext/js/pages/settings/anki-templates-controller.js7
-rw-r--r--ext/js/pages/settings/backup-controller.js11
-rw-r--r--ext/js/pages/settings/collapsible-dictionary-controller.js3
-rw-r--r--ext/js/pages/settings/dictionary-controller.js7
-rw-r--r--ext/js/pages/settings/dictionary-import-controller.js7
-rw-r--r--ext/js/pages/settings/extension-keyboard-shortcuts-controller.js3
-rw-r--r--ext/js/pages/settings/keyboard-shortcuts-controller.js3
-rw-r--r--ext/js/pages/settings/mecab-controller.js10
-rw-r--r--ext/js/pages/settings/persistent-storage-controller.js15
-rw-r--r--ext/js/pages/settings/popup-preview-frame-main.js13
-rw-r--r--ext/js/pages/settings/popup-preview-frame.js11
-rw-r--r--ext/js/pages/settings/popup-window-controller.js11
-rw-r--r--ext/js/pages/settings/profile-controller.js3
-rw-r--r--ext/js/pages/settings/scan-inputs-controller.js3
-rw-r--r--ext/js/pages/settings/scan-inputs-simple-controller.js3
-rw-r--r--ext/js/pages/settings/secondary-search-dictionary-controller.js3
-rw-r--r--ext/js/pages/settings/settings-controller.js27
-rw-r--r--ext/js/pages/settings/settings-main.js13
-rw-r--r--ext/js/pages/settings/sort-frequency-dictionary-controller.js5
-rw-r--r--ext/js/pages/settings/storage-controller.js3
-rw-r--r--ext/js/pages/welcome-main.js17
53 files changed, 343 insertions, 271 deletions
diff --git a/ext/js/app/content-script-main.js b/ext/js/app/content-script-main.js
index c0bea73c..d77f1fa0 100644
--- a/ext/js/app/content-script-main.js
+++ b/ext/js/app/content-script-main.js
@@ -16,29 +16,31 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import {Application} from '../application.js';
import {log} from '../core/logger.js';
import {HotkeyHandler} from '../input/hotkey-handler.js';
-import {yomitan} from '../yomitan.js';
import {Frontend} from './frontend.js';
import {PopupFactory} from './popup-factory.js';
/** Entry point. */
async function main() {
try {
- await yomitan.prepare();
+ const application = new Application();
+ await application.prepare();
- const {tabId, frameId} = await yomitan.api.frameInformationGet();
+ const {tabId, frameId} = await application.api.frameInformationGet();
if (typeof frameId !== 'number') {
throw new Error('Failed to get frameId');
}
const hotkeyHandler = new HotkeyHandler();
- hotkeyHandler.prepare();
+ hotkeyHandler.prepare(application.crossFrame);
- const popupFactory = new PopupFactory(frameId);
+ const popupFactory = new PopupFactory(application, frameId);
popupFactory.prepare();
const frontend = new Frontend({
+ application,
tabId,
frameId,
popupFactory,
@@ -54,7 +56,7 @@ async function main() {
});
await frontend.prepare();
- yomitan.ready();
+ application.ready();
} catch (e) {
log.error(e);
}
diff --git a/ext/js/app/frontend.js b/ext/js/app/frontend.js
index d1c32b03..de1c5a46 100644
--- a/ext/js/app/frontend.js
+++ b/ext/js/app/frontend.js
@@ -25,7 +25,6 @@ import {TextSourceElement} from '../dom/text-source-element.js';
import {TextSourceGenerator} from '../dom/text-source-generator.js';
import {TextSourceRange} from '../dom/text-source-range.js';
import {TextScanner} from '../language/text-scanner.js';
-import {yomitan} from '../yomitan.js';
/**
* This is the main class responsible for scanning and handling webpage content.
@@ -36,6 +35,7 @@ export class Frontend {
* @param {import('frontend').ConstructorDetails} details Details about how to set up the instance.
*/
constructor({
+ application,
pageType,
popupFactory,
depth,
@@ -49,6 +49,8 @@ export class Frontend {
childrenSupported = true,
hotkeyHandler
}) {
+ /** @type {import('../application.js').Application} */
+ this._application = application;
/** @type {import('frontend').PageType} */
this._pageType = pageType;
/** @type {import('./popup-factory.js').PopupFactory} */
@@ -89,6 +91,7 @@ export class Frontend {
this._textSourceGenerator = new TextSourceGenerator();
/** @type {TextScanner} */
this._textScanner = new TextScanner({
+ api: application.api,
node: window,
ignoreElements: this._ignoreElements.bind(this),
ignorePoint: this._ignorePoint.bind(this),
@@ -157,7 +160,7 @@ export class Frontend {
async prepare() {
await this.updateOptions();
try {
- const {zoomFactor} = await yomitan.api.getZoom();
+ const {zoomFactor} = await this._application.api.getZoom();
this._pageZoomFactor = zoomFactor;
} catch (e) {
// Ignore exceptions which may occur due to being on an unsupported page (e.g. about:blank)
@@ -174,16 +177,16 @@ export class Frontend {
visualViewport.addEventListener('resize', this._onVisualViewportResize.bind(this));
}
- yomitan.on('optionsUpdated', this.updateOptions.bind(this));
- yomitan.on('zoomChanged', this._onZoomChanged.bind(this));
- yomitan.on('closePopups', this._onClosePopups.bind(this));
+ this._application.on('optionsUpdated', this.updateOptions.bind(this));
+ this._application.on('zoomChanged', this._onZoomChanged.bind(this));
+ this._application.on('closePopups', this._onClosePopups.bind(this));
chrome.runtime.onMessage.addListener(this._onRuntimeMessage.bind(this));
this._textScanner.on('clear', this._onTextScannerClear.bind(this));
this._textScanner.on('searched', this._onSearched.bind(this));
/* eslint-disable no-multi-spaces */
- yomitan.crossFrame.registerHandlers([
+ this._application.crossFrame.registerHandlers([
['frontendClosePopup', this._onApiClosePopup.bind(this)],
['frontendCopySelection', this._onApiCopySelection.bind(this)],
['frontendGetSelectionText', this._onApiGetSelectionText.bind(this)],
@@ -230,7 +233,7 @@ export class Frontend {
try {
await this._updateOptionsInternal();
} catch (e) {
- if (!yomitan.webExtension.unloaded) {
+ if (!this._application.webExtension.unloaded) {
throw e;
}
}
@@ -372,7 +375,7 @@ export class Frontend {
const scanningOptions = /** @type {import('settings').ProfileOptions} */ (this._options).scanning;
if (error !== null) {
- if (yomitan.webExtension.unloaded) {
+ if (this._application.webExtension.unloaded) {
if (textSource !== null && !passive) {
this._showExtensionUnloaded(textSource);
}
@@ -461,7 +464,7 @@ export class Frontend {
*/
async _updateOptionsInternal() {
const optionsContext = await this._getOptionsContext();
- const options = await yomitan.api.optionsGet(optionsContext);
+ const options = await this._application.api.optionsGet(optionsContext);
const {scanning: scanningOptions, sentenceParsing: sentenceParsingOptions} = options;
this._options = options;
@@ -609,7 +612,7 @@ export class Frontend {
return await this._getDefaultPopup();
}
- const {popupId} = await yomitan.crossFrame.invoke(targetFrameId, 'frontendGetPopupInfo', void 0);
+ const {popupId} = await this._application.crossFrame.invoke(targetFrameId, 'frontendGetPopupInfo', void 0);
if (popupId === null) {
return null;
}
@@ -659,7 +662,7 @@ export class Frontend {
try {
return this._popup !== null && await this._popup.containsPoint(x, y);
} catch (e) {
- if (!yomitan.webExtension.unloaded) {
+ if (!this._application.webExtension.unloaded) {
throw e;
}
return false;
@@ -746,7 +749,7 @@ export class Frontend {
Promise.resolve()
);
this._lastShowPromise.catch((error) => {
- if (yomitan.webExtension.unloaded) { return; }
+ if (this._application.webExtension.unloaded) { return; }
log.error(error);
});
return this._lastShowPromise;
@@ -811,9 +814,9 @@ export class Frontend {
/** @type {import('application').ApiMessageNoFrameId<'frontendReady'>} */
const message = {action: 'frontendReady', params: {frameId: this._frameId}};
if (targetFrameId === null) {
- yomitan.api.broadcastTab(message);
+ this._application.api.broadcastTab(message);
} else {
- yomitan.api.sendMessageToFrame(targetFrameId, message);
+ this._application.api.sendMessageToFrame(targetFrameId, message);
}
}
@@ -857,7 +860,7 @@ export class Frontend {
}
chrome.runtime.onMessage.addListener(onMessage);
- yomitan.api.broadcastTab({action: 'frontendRequestReadyBroadcast', params: {frameId: this._frameId}});
+ this._application.api.broadcastTab({action: 'frontendRequestReadyBroadcast', params: {frameId: this._frameId}});
});
}
@@ -892,7 +895,7 @@ export class Frontend {
let documentTitle = document.title;
if (this._useProxyPopup && this._parentFrameId !== null) {
try {
- ({url, documentTitle} = await yomitan.crossFrame.invoke(this._parentFrameId, 'frontendGetPageInfo', void 0));
+ ({url, documentTitle} = await this._application.crossFrame.invoke(this._parentFrameId, 'frontendGetPageInfo', void 0));
} catch (e) {
// NOP
}
diff --git a/ext/js/app/popup-factory.js b/ext/js/app/popup-factory.js
index f9eec913..1b7d21db 100644
--- a/ext/js/app/popup-factory.js
+++ b/ext/js/app/popup-factory.js
@@ -18,7 +18,6 @@
import {FrameOffsetForwarder} from '../comm/frame-offset-forwarder.js';
import {generateId} from '../core/utilities.js';
-import {yomitan} from '../yomitan.js';
import {PopupProxy} from './popup-proxy.js';
import {PopupWindow} from './popup-window.js';
import {Popup} from './popup.js';
@@ -29,13 +28,16 @@ import {Popup} from './popup.js';
export class PopupFactory {
/**
* Creates a new instance.
+ * @param {import('../application.js').Application} application
* @param {number} frameId The frame ID of the host frame.
*/
- constructor(frameId) {
+ constructor(application, frameId) {
+ /** @type {import('../application.js').Application} */
+ this._application = application;
/** @type {number} */
this._frameId = frameId;
/** @type {FrameOffsetForwarder} */
- this._frameOffsetForwarder = new FrameOffsetForwarder(frameId);
+ this._frameOffsetForwarder = new FrameOffsetForwarder(application.crossFrame, frameId);
/** @type {Map<string, import('popup').PopupAny>} */
this._popups = new Map();
/** @type {Map<string, {popup: import('popup').PopupAny, token: string}[]>} */
@@ -48,7 +50,7 @@ export class PopupFactory {
prepare() {
this._frameOffsetForwarder.prepare();
/* eslint-disable no-multi-spaces */
- yomitan.crossFrame.registerHandlers([
+ this._application.crossFrame.registerHandlers([
['popupFactoryGetOrCreatePopup', this._onApiGetOrCreatePopup.bind(this)],
['popupFactorySetOptionsContext', this._onApiSetOptionsContext.bind(this)],
['popupFactoryHide', this._onApiHide.bind(this)],
@@ -119,6 +121,7 @@ export class PopupFactory {
id = generateId(16);
}
const popup = new PopupWindow({
+ application: this._application,
id,
depth,
frameId: this._frameId
@@ -131,6 +134,7 @@ export class PopupFactory {
id = generateId(16);
}
const popup = new Popup({
+ application: this._application,
id,
depth,
frameId: this._frameId,
@@ -152,7 +156,7 @@ export class PopupFactory {
}
const useFrameOffsetForwarder = (parentPopupId === null);
/** @type {{id: string, depth: number, frameId: number}} */
- const info = await yomitan.crossFrame.invoke(frameId, 'popupFactoryGetOrCreatePopup', /** @type {import('popup-factory').GetOrCreatePopupDetails} */ ({
+ const info = await this._application.crossFrame.invoke(frameId, 'popupFactoryGetOrCreatePopup', /** @type {import('popup-factory').GetOrCreatePopupDetails} */ ({
id,
parentPopupId,
frameId,
@@ -160,6 +164,7 @@ export class PopupFactory {
}));
id = info.id;
const popup = new PopupProxy({
+ application: this._application,
id,
depth: info.depth,
frameId: info.frameId,
diff --git a/ext/js/app/popup-proxy.js b/ext/js/app/popup-proxy.js
index 856ec086..3632b8cb 100644
--- a/ext/js/app/popup-proxy.js
+++ b/ext/js/app/popup-proxy.js
@@ -18,7 +18,6 @@
import {EventDispatcher} from '../core/event-dispatcher.js';
import {log} from '../core/logger.js';
-import {yomitan} from '../yomitan.js';
/**
* This class is a proxy for a Popup that is hosted in a different frame.
@@ -31,12 +30,15 @@ export class PopupProxy extends EventDispatcher {
* @param {import('popup').PopupProxyConstructorDetails} details Details about how to set up the instance.
*/
constructor({
+ application,
id,
depth,
frameId,
frameOffsetForwarder
}) {
super();
+ /** @type {import('../application.js').Application} */
+ this._application = application;
/** @type {string} */
this._id = id;
/** @type {number} */
@@ -305,7 +307,7 @@ export class PopupProxy extends EventDispatcher {
* @returns {Promise<import('cross-frame-api').ApiReturn<TName>>}
*/
_invoke(action, params) {
- return yomitan.crossFrame.invoke(this._frameId, action, params);
+ return this._application.crossFrame.invoke(this._frameId, action, params);
}
/**
@@ -320,7 +322,7 @@ export class PopupProxy extends EventDispatcher {
try {
return await this._invoke(action, params);
} catch (e) {
- if (!yomitan.webExtension.unloaded) { throw e; }
+ if (!this._application.webExtension.unloaded) { throw e; }
return defaultReturnValue;
}
}
diff --git a/ext/js/app/popup-window.js b/ext/js/app/popup-window.js
index 7a0b6af4..32c4d67b 100644
--- a/ext/js/app/popup-window.js
+++ b/ext/js/app/popup-window.js
@@ -17,7 +17,6 @@
*/
import {EventDispatcher} from '../core/event-dispatcher.js';
-import {yomitan} from '../yomitan.js';
/**
* This class represents a popup that is hosted in a new native window.
@@ -29,11 +28,14 @@ export class PopupWindow extends EventDispatcher {
* @param {import('popup').PopupWindowConstructorDetails} details Details about how to set up the instance.
*/
constructor({
+ application,
id,
depth,
frameId
}) {
super();
+ /** @type {import('../application.js').Application} */
+ this._application = application;
/** @type {string} */
this._id = id;
/** @type {number} */
@@ -142,7 +144,7 @@ export class PopupWindow extends EventDispatcher {
* @returns {Promise<boolean>} `true` if the popup is visible, `false` otherwise.
*/
async isVisible() {
- return (this._popupTabId !== null && await yomitan.api.isTabSearchPopup(this._popupTabId));
+ return (this._popupTabId !== null && await this._application.api.isTabSearchPopup(this._popupTabId));
}
/**
@@ -274,7 +276,7 @@ export class PopupWindow extends EventDispatcher {
* @returns {Promise<import('display').DirectApiReturn<TName>|undefined>}
*/
async _invoke(open, action, params) {
- if (yomitan.webExtension.unloaded) {
+ if (this._application.webExtension.unloaded) {
return void 0;
}
@@ -283,14 +285,14 @@ export class PopupWindow extends EventDispatcher {
const frameId = 0;
if (this._popupTabId !== null) {
try {
- return /** @type {import('display').DirectApiReturn<TName>} */ (await yomitan.crossFrame.invokeTab(
+ return /** @type {import('display').DirectApiReturn<TName>} */ (await this._application.crossFrame.invokeTab(
this._popupTabId,
frameId,
'displayPopupMessage2',
message
));
} catch (e) {
- if (yomitan.webExtension.unloaded) {
+ if (this._application.webExtension.unloaded) {
open = false;
}
}
@@ -301,10 +303,10 @@ export class PopupWindow extends EventDispatcher {
return void 0;
}
- const {tabId} = await yomitan.api.getOrCreateSearchPopup({focus: 'ifCreated'});
+ const {tabId} = await this._application.api.getOrCreateSearchPopup({focus: 'ifCreated'});
this._popupTabId = tabId;
- return /** @type {import('display').DirectApiReturn<TName>} */ (await yomitan.crossFrame.invokeTab(
+ return /** @type {import('display').DirectApiReturn<TName>} */ (await this._application.crossFrame.invokeTab(
this._popupTabId,
frameId,
'displayPopupMessage2',
diff --git a/ext/js/app/popup.js b/ext/js/app/popup.js
index c741e8f1..08ff0661 100644
--- a/ext/js/app/popup.js
+++ b/ext/js/app/popup.js
@@ -24,7 +24,6 @@ import {ExtensionError} from '../core/extension-error.js';
import {deepEqual} from '../core/utilities.js';
import {DocumentUtil} from '../dom/document-util.js';
import {loadStyle} from '../dom/style-util.js';
-import {yomitan} from '../yomitan.js';
import {ThemeController} from './theme-controller.js';
/**
@@ -37,12 +36,15 @@ export class Popup extends EventDispatcher {
* @param {import('popup').PopupConstructorDetails} details The details used to construct the new instance.
*/
constructor({
+ application,
id,
depth,
frameId,
childrenSupported
}) {
super();
+ /** @type {import('../application.js').Application} */
+ this._application = application;
/** @type {string} */
this._id = id;
/** @type {number} */
@@ -206,7 +208,7 @@ export class Popup extends EventDispatcher {
this._frame.addEventListener('scroll', (e) => e.stopPropagation());
this._frame.addEventListener('load', this._onFrameLoad.bind(this));
this._visible.on('change', this._onVisibleChange.bind(this));
- yomitan.on('extensionUnloaded', this._onExtensionUnloaded.bind(this));
+ this._application.on('extensionUnloaded', this._onExtensionUnloaded.bind(this));
this._onVisibleChange({value: this.isVisibleSync()});
this._themeController.prepare();
}
@@ -362,7 +364,7 @@ export class Popup extends EventDispatcher {
useWebExtensionApi = false;
parentNode = this._shadow;
}
- const node = await loadStyle('yomitan-popup-outer-user-stylesheet', 'code', css, useWebExtensionApi, parentNode);
+ const node = await loadStyle(this._application, 'yomitan-popup-outer-user-stylesheet', 'code', css, useWebExtensionApi, parentNode);
this.trigger('customOuterCssChanged', {node, useWebExtensionApi, inShadow});
}
@@ -575,7 +577,7 @@ export class Popup extends EventDispatcher {
useWebExtensionApi = false;
parentNode = this._shadow;
}
- await loadStyle('yomitan-popup-outer-stylesheet', fileType, '/css/popup-outer.css', useWebExtensionApi, parentNode);
+ await loadStyle(this._application, 'yomitan-popup-outer-stylesheet', fileType, '/css/popup-outer.css', useWebExtensionApi, parentNode);
}
/**
@@ -697,7 +699,7 @@ export class Popup extends EventDispatcher {
/** @type {import('display').DirectApiMessage<TName>} */
const message = {action, params};
const wrappedMessage = this._frameClient.createMessage(message);
- return /** @type {import('display').DirectApiReturn<TName>} */ (await yomitan.crossFrame.invoke(
+ return /** @type {import('display').DirectApiReturn<TName>} */ (await this._application.crossFrame.invoke(
this._frameClient.frameId,
'displayPopupMessage1',
/** @type {import('display').DirectApiFrameClientMessageAny} */ (wrappedMessage)
@@ -714,7 +716,7 @@ export class Popup extends EventDispatcher {
try {
return await this._invoke(action, params);
} catch (e) {
- if (!yomitan.webExtension.unloaded) { throw e; }
+ if (!this._application.webExtension.unloaded) { throw e; }
return void 0;
}
}
@@ -1008,7 +1010,7 @@ export class Popup extends EventDispatcher {
*/
async _setOptionsContext(optionsContext) {
this._optionsContext = optionsContext;
- const options = await yomitan.api.optionsGet(optionsContext);
+ const options = await this._application.api.optionsGet(optionsContext);
const {general} = options;
this._themeController.theme = general.popupTheme;
this._themeController.outerTheme = general.popupOuterTheme;
diff --git a/ext/js/yomitan.js b/ext/js/application.js
index 33afac27..87bd0e86 100644
--- a/ext/js/yomitan.js
+++ b/ext/js/application.js
@@ -55,7 +55,7 @@ if (checkChromeNotAvailable()) {
* The Yomitan class is a core component through which various APIs are handled and invoked.
* @augments EventDispatcher<import('application').Events>
*/
-export class Yomitan extends EventDispatcher {
+export class Application extends EventDispatcher {
/**
* Creates a new instance. The instance should not be used until it has been fully prepare()'d.
*/
@@ -158,7 +158,7 @@ export class Yomitan extends EventDispatcher {
await this._webExtension.sendMessagePromise({action: 'requestBackendReadySignal'});
await this._isBackendReadyPromise;
- this._crossFrame = new CrossFrameAPI();
+ this._crossFrame = new CrossFrameAPI(this._api);
await this._crossFrame.prepare();
log.on('log', this._onForwardLog.bind(this));
@@ -253,8 +253,3 @@ export class Yomitan extends EventDispatcher {
}
}
}
-
-/**
- * The default Yomitan class instance.
- */
-export const yomitan = new Yomitan();
diff --git a/ext/js/background/background-main.js b/ext/js/background/background-main.js
index f5871a14..b63b4396 100644
--- a/ext/js/background/background-main.js
+++ b/ext/js/background/background-main.js
@@ -16,14 +16,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {yomitan} from '../yomitan.js';
+import {Application} from '../application.js';
import {Backend} from './backend.js';
/** Entry point. */
async function main() {
- yomitan.prepare(true);
+ const application = new Application();
+ application.prepare(true);
- const backend = new Backend(yomitan.webExtension);
+ const backend = new Backend(application.webExtension);
await backend.prepare();
}
diff --git a/ext/js/comm/cross-frame-api.js b/ext/js/comm/cross-frame-api.js
index fca7c84d..eb9bed38 100644
--- a/ext/js/comm/cross-frame-api.js
+++ b/ext/js/comm/cross-frame-api.js
@@ -22,7 +22,6 @@ import {EventListenerCollection} from '../core/event-listener-collection.js';
import {ExtensionError} from '../core/extension-error.js';
import {parseJson} from '../core/json.js';
import {log} from '../core/logger.js';
-import {yomitan} from '../yomitan.js';
/**
* @augments EventDispatcher<import('cross-frame-api').CrossFrameAPIPortEvents>
@@ -290,7 +289,12 @@ export class CrossFrameAPIPort extends EventDispatcher {
}
export class CrossFrameAPI {
- constructor() {
+ /**
+ * @param {import('../comm/api.js').API} api
+ */
+ constructor(api) {
+ /** @type {import('../comm/api.js').API} */
+ this._api = api;
/** @type {number} */
this._ackTimeout = 3000; // 3 seconds
/** @type {number} */
@@ -310,7 +314,7 @@ export class CrossFrameAPI {
/** */
async prepare() {
chrome.runtime.onConnect.addListener(this._onConnect.bind(this));
- ({tabId: this._tabId = null, frameId: this._frameId = null} = await yomitan.api.frameInformationGet());
+ ({tabId: this._tabId = null, frameId: this._frameId = null} = await this._api.frameInformationGet());
}
/**
@@ -411,7 +415,7 @@ export class CrossFrameAPI {
* @returns {Promise<CrossFrameAPIPort>}
*/
async _createCommPort(otherTabId, otherFrameId) {
- await yomitan.api.openCrossFramePort(otherTabId, otherFrameId);
+ await this._api.openCrossFramePort(otherTabId, otherFrameId);
const tabPorts = this._commPorts.get(otherTabId);
if (typeof tabPorts !== 'undefined') {
diff --git a/ext/js/comm/frame-ancestry-handler.js b/ext/js/comm/frame-ancestry-handler.js
index 31739654..3e58d57b 100644
--- a/ext/js/comm/frame-ancestry-handler.js
+++ b/ext/js/comm/frame-ancestry-handler.js
@@ -17,7 +17,6 @@
*/
import {generateId} from '../core/utilities.js';
-import {yomitan} from '../yomitan.js';
/**
* This class is used to return the ancestor frame IDs for the current frame.
@@ -28,9 +27,12 @@ import {yomitan} from '../yomitan.js';
export class FrameAncestryHandler {
/**
* Creates a new instance.
+ * @param {import('../comm/cross-frame-api.js').CrossFrameAPI} crossFrameApi
* @param {number} frameId The frame ID of the current frame the instance is instantiated in.
*/
- constructor(frameId) {
+ constructor(crossFrameApi, frameId) {
+ /** @type {import('../comm/cross-frame-api.js').CrossFrameAPI} */
+ this._crossFrameApi = crossFrameApi;
/** @type {number} */
this._frameId = frameId;
/** @type {boolean} */
@@ -59,7 +61,7 @@ export class FrameAncestryHandler {
prepare() {
if (this._isPrepared) { return; }
window.addEventListener('message', this._onWindowMessage.bind(this), false);
- yomitan.crossFrame.registerHandlers([
+ this._crossFrameApi.registerHandlers([
['frameAncestryHandlerRequestFrameInfoResponse', this._onFrameAncestryHandlerRequestFrameInfoResponse.bind(this)]
]);
this._isPrepared = true;
@@ -211,7 +213,7 @@ export class FrameAncestryHandler {
const more = (window !== parent);
try {
- const response = await yomitan.crossFrame.invoke(originFrameId, 'frameAncestryHandlerRequestFrameInfoResponse', {uniqueId, frameId, nonce, more});
+ const response = await this._crossFrameApi.invoke(originFrameId, 'frameAncestryHandlerRequestFrameInfoResponse', {uniqueId, frameId, nonce, more});
if (response === null) { return; }
const nonce2 = response.nonce;
if (typeof nonce2 !== 'string') { return; }
diff --git a/ext/js/comm/frame-endpoint.js b/ext/js/comm/frame-endpoint.js
index 0008417d..d2002d2e 100644
--- a/ext/js/comm/frame-endpoint.js
+++ b/ext/js/comm/frame-endpoint.js
@@ -18,10 +18,14 @@
import {EventListenerCollection} from '../core/event-listener-collection.js';
import {generateId} from '../core/utilities.js';
-import {yomitan} from '../yomitan.js';
export class FrameEndpoint {
- constructor() {
+ /**
+ * @param {import('../comm/api.js').API} api
+ */
+ constructor(api) {
+ /** @type {import('../comm/api.js').API} */
+ this._api = api;
/** @type {string} */
this._secret = generateId(16);
/** @type {?string} */
@@ -42,7 +46,7 @@ export class FrameEndpoint {
}
/** @type {import('frame-client').FrameEndpointReadyDetails} */
const details = {secret: this._secret};
- yomitan.api.broadcastTab({action: 'frameEndpointReady', params: details});
+ this._api.broadcastTab({action: 'frameEndpointReady', params: details});
}
/**
@@ -84,6 +88,6 @@ export class FrameEndpoint {
this._eventListeners.removeAllEventListeners();
/** @type {import('frame-client').FrameEndpointConnectedDetails} */
const details = {secret, token};
- yomitan.api.sendMessageToFrame(hostFrameId, {action: 'frameEndpointConnected', params: details});
+ this._api.sendMessageToFrame(hostFrameId, {action: 'frameEndpointConnected', params: details});
}
}
diff --git a/ext/js/comm/frame-offset-forwarder.js b/ext/js/comm/frame-offset-forwarder.js
index a1f249e2..fe1ff98a 100644
--- a/ext/js/comm/frame-offset-forwarder.js
+++ b/ext/js/comm/frame-offset-forwarder.js
@@ -16,18 +16,20 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {yomitan} from '../yomitan.js';
import {FrameAncestryHandler} from './frame-ancestry-handler.js';
export class FrameOffsetForwarder {
/**
+ * @param {import('../comm/cross-frame-api.js').CrossFrameAPI} crossFrameApi
* @param {number} frameId
*/
- constructor(frameId) {
+ constructor(crossFrameApi, frameId) {
+ /** @type {import('../comm/cross-frame-api.js').CrossFrameAPI} */
+ this._crossFrameApi = crossFrameApi;
/** @type {number} */
this._frameId = frameId;
/** @type {FrameAncestryHandler} */
- this._frameAncestryHandler = new FrameAncestryHandler(frameId);
+ this._frameAncestryHandler = new FrameAncestryHandler(crossFrameApi, frameId);
}
/**
@@ -35,7 +37,7 @@ export class FrameOffsetForwarder {
*/
prepare() {
this._frameAncestryHandler.prepare();
- yomitan.crossFrame.registerHandlers([
+ this._crossFrameApi.registerHandlers([
['frameOffsetForwarderGetChildFrameRect', this._onMessageGetChildFrameRect.bind(this)]
]);
}
@@ -55,7 +57,7 @@ export class FrameOffsetForwarder {
/** @type {Promise<?import('frame-offset-forwarder').ChildFrameRect>[]} */
const promises = [];
for (const frameId of ancestorFrameIds) {
- promises.push(yomitan.crossFrame.invoke(frameId, 'frameOffsetForwarderGetChildFrameRect', {frameId: childFrameId}));
+ promises.push(this._crossFrameApi.invoke(frameId, 'frameOffsetForwarderGetChildFrameRect', {frameId: childFrameId}));
childFrameId = frameId;
}
diff --git a/ext/js/data/anki-note-builder.js b/ext/js/data/anki-note-builder.js
index 5bb943c2..a6e1aafc 100644
--- a/ext/js/data/anki-note-builder.js
+++ b/ext/js/data/anki-note-builder.js
@@ -19,15 +19,17 @@
import {ExtensionError} from '../core/extension-error.js';
import {deferPromise} from '../core/utilities.js';
import {convertHiraganaToKatakana, convertKatakanaToHiragana} from '../language/japanese.js';
-import {yomitan} from '../yomitan.js';
import {cloneFieldMarkerPattern, getRootDeckName} from './anki-util.js';
export class AnkiNoteBuilder {
/**
* Initiate an instance of AnkiNoteBuilder.
+ * @param {import('anki-note-builder').MinimalApi} api
* @param {import('../templates/template-renderer-proxy.js').TemplateRendererProxy|import('../templates/sandbox/template-renderer.js').TemplateRenderer} templateRenderer
*/
- constructor(templateRenderer) {
+ constructor(api, templateRenderer) {
+ /** @type {import('anki-note-builder').MinimalApi} */
+ this._api = api;
/** @type {RegExp} */
this._markerPattern = cloneFieldMarkerPattern(true);
/** @type {import('../templates/template-renderer-proxy.js').TemplateRendererProxy|import('../templates/sandbox/template-renderer.js').TemplateRenderer} */
@@ -431,7 +433,7 @@ export class AnkiNoteBuilder {
// Inject media
const selectionText = injectSelectionText ? this._getSelectionText() : null;
- const injectedMedia = await yomitan.api.injectAnkiNoteMedia(
+ const injectedMedia = await this._api.injectAnkiNoteMedia(
timestamp,
dictionaryEntryDetails,
audioDetails,
@@ -483,7 +485,7 @@ export class AnkiNoteBuilder {
async _getTextFurigana(entries, optionsContext, scanLength) {
const results = [];
for (const {text, readingMode} of entries) {
- const parseResults = await yomitan.api.parseText(text, optionsContext, scanLength, true, false);
+ const parseResults = await this._api.parseText(text, optionsContext, scanLength, true, false);
let data = null;
for (const {source, content} of parseResults) {
if (source !== 'scanning-parser') { continue; }
diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js
index 68d28d33..c19cfa22 100644
--- a/ext/js/display/display-anki.js
+++ b/ext/js/display/display-anki.js
@@ -24,7 +24,6 @@ import {isNoteDataValid} from '../data/anki-util.js';
import {PopupMenu} from '../dom/popup-menu.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
import {TemplateRendererProxy} from '../templates/template-renderer-proxy.js';
-import {yomitan} from '../yomitan.js';
export class DisplayAnki {
/**
@@ -41,7 +40,7 @@ export class DisplayAnki {
/** @type {?string} */
this._ankiFieldTemplatesDefault = null;
/** @type {AnkiNoteBuilder} */
- this._ankiNoteBuilder = new AnkiNoteBuilder(new TemplateRendererProxy());
+ this._ankiNoteBuilder = new AnkiNoteBuilder(display.application.api, new TemplateRendererProxy());
/** @type {?import('./display-notification.js').DisplayNotification} */
this._errorNotification = null;
/** @type {?EventListenerCollection} */
@@ -487,7 +486,7 @@ export class DisplayAnki {
let noteId = null;
let addNoteOkay = false;
try {
- noteId = await yomitan.api.addAnkiNote(note);
+ noteId = await this._display.application.api.addAnkiNote(note);
addNoteOkay = true;
} catch (e) {
allErrors.length = 0;
@@ -500,7 +499,7 @@ export class DisplayAnki {
} else {
if (this._suspendNewCards) {
try {
- await yomitan.api.suspendAnkiCardsForNote(noteId);
+ await this._display.application.api.suspendAnkiCardsForNote(noteId);
} catch (e) {
allErrors.push(toError(e));
}
@@ -605,7 +604,7 @@ export class DisplayAnki {
templates = this._ankiFieldTemplatesDefault;
if (typeof templates === 'string') { return templates; }
- templates = await yomitan.api.getDefaultAnkiFieldTemplates();
+ templates = await this._display.application.api.getDefaultAnkiFieldTemplates();
this._ankiFieldTemplatesDefault = templates;
return templates;
}
@@ -639,12 +638,12 @@ export class DisplayAnki {
let ankiError = null;
try {
if (forceCanAddValue !== null) {
- if (!await yomitan.api.isAnkiConnected()) {
+ if (!await this._display.application.api.isAnkiConnected()) {
throw new Error('Anki not connected');
}
infos = this._getAnkiNoteInfoForceValue(notes, forceCanAddValue);
} else {
- infos = await yomitan.api.getAnkiNoteInfo(notes, fetchAdditionalInfo);
+ infos = await this._display.application.api.getAnkiNoteInfo(notes, fetchAdditionalInfo);
}
} catch (e) {
infos = this._getAnkiNoteInfoForceValue(notes, false);
@@ -853,7 +852,7 @@ export class DisplayAnki {
const noteIds = this._getNodeNoteIds(node);
if (noteIds.length === 0) { return; }
try {
- await yomitan.api.noteView(noteIds[0], this._noteGuiMode, false);
+ await this._display.application.api.noteView(noteIds[0], this._noteGuiMode, false);
} catch (e) {
const displayErrors = (
toError(e).message === 'Mode not supported' ?
diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js
index 8cbfc83f..4acd6494 100644
--- a/ext/js/display/display-audio.js
+++ b/ext/js/display/display-audio.js
@@ -20,7 +20,6 @@ import {EventListenerCollection} from '../core/event-listener-collection.js';
import {PopupMenu} from '../dom/popup-menu.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
import {AudioSystem} from '../media/audio-system.js';
-import {yomitan} from '../yomitan.js';
export class DisplayAudio {
/**
@@ -676,7 +675,7 @@ export class DisplayAudio {
*/
async _getTermAudioInfoList(source, term, reading) {
const sourceData = this._getSourceData(source);
- const infoList = await yomitan.api.getTermAudioInfoList(sourceData, term, reading);
+ const infoList = await this._display.application.api.getTermAudioInfoList(sourceData, term, reading);
return infoList.map((info) => ({info, audioPromise: null, audioResolved: false, audio: null}));
}
diff --git a/ext/js/display/display-content-manager.js b/ext/js/display/display-content-manager.js
index 4465ce3e..81742279 100644
--- a/ext/js/display/display-content-manager.js
+++ b/ext/js/display/display-content-manager.js
@@ -18,7 +18,6 @@
import {EventListenerCollection} from '../core/event-listener-collection.js';
import {base64ToArrayBuffer} from '../data/sandbox/array-buffer-util.js';
-import {yomitan} from '../yomitan.js';
/**
* The content manager which is used when generating HTML display content.
@@ -140,7 +139,7 @@ export class DisplayContentManager {
*/
async _getMediaData(path, dictionary) {
const token = this._token;
- const datas = await yomitan.api.getMedia([{path, dictionary}]);
+ const datas = await this._display.application.api.getMedia([{path, dictionary}]);
if (token === this._token && datas.length > 0) {
const data = datas[0];
const buffer = base64ToArrayBuffer(data.content);
diff --git a/ext/js/display/display-generator.js b/ext/js/display/display-generator.js
index 01f6f38b..fdfe3d4a 100644
--- a/ext/js/display/display-generator.js
+++ b/ext/js/display/display-generator.js
@@ -21,7 +21,6 @@ import {isObject} from '../core/utilities.js';
import {getDisambiguations, getGroupedPronunciations, getTermFrequency, groupKanjiFrequencies, groupTermFrequencies, groupTermTags, isNonNounVerbOrAdjective} from '../dictionary/dictionary-data-util.js';
import {HtmlTemplateCollection} from '../dom/html-template-collection.js';
import {distributeFurigana, getKanaMorae, getPitchCategory, isCodePointKanji, isStringPartiallyJapanese} from '../language/japanese.js';
-import {yomitan} from '../yomitan.js';
import {createPronunciationDownstepPosition, createPronunciationGraph, createPronunciationText} from './sandbox/pronunciation-generator.js';
import {StructuredContentGenerator} from './sandbox/structured-content-generator.js';
@@ -40,9 +39,11 @@ export class DisplayGenerator {
this._structuredContentGenerator = new StructuredContentGenerator(this._contentManager, document);
}
- /** */
- async prepare() {
- const html = await yomitan.api.getDisplayTemplatesHtml();
+ /**
+ * @param {import('../comm/api.js').API} api
+ */
+ async prepare(api) {
+ const html = await api.getDisplayTemplatesHtml();
this._templates.load(html);
this.updateHotkeys();
}
diff --git a/ext/js/display/display-profile-selection.js b/ext/js/display/display-profile-selection.js
index b61b49d5..3df79b74 100644
--- a/ext/js/display/display-profile-selection.js
+++ b/ext/js/display/display-profile-selection.js
@@ -20,7 +20,6 @@ import {EventListenerCollection} from '../core/event-listener-collection.js';
import {generateId} from '../core/utilities.js';
import {PanelElement} from '../dom/panel-element.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
-import {yomitan} from '../yomitan.js';
export class DisplayProfileSelection {
/**
@@ -50,7 +49,7 @@ export class DisplayProfileSelection {
/** */
async prepare() {
- yomitan.on('optionsUpdated', this._onOptionsUpdated.bind(this));
+ this._display.application.on('optionsUpdated', this._onOptionsUpdated.bind(this));
this._profileButton.addEventListener('click', this._onProfileButtonClick.bind(this), false);
this._profileListNeedsUpdate = true;
}
@@ -92,7 +91,7 @@ export class DisplayProfileSelection {
/** */
async _updateProfileList() {
this._profileListNeedsUpdate = false;
- const options = await yomitan.api.optionsGetFull();
+ const options = await this._display.application.api.optionsGetFull();
this._eventListeners.removeAllEventListeners();
const displayGenerator = this._display.displayGenerator;
@@ -138,7 +137,7 @@ export class DisplayProfileSelection {
scope: 'global',
optionsContext: null
};
- await yomitan.api.modifySettings([modification], this._source);
+ await this._display.application.api.modifySettings([modification], this._source);
this._setProfilePanelVisible(false);
}
}
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index c7a2775d..4114cc45 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -32,7 +32,6 @@ import {ScrollElement} from '../dom/scroll-element.js';
import {TextSourceGenerator} from '../dom/text-source-generator.js';
import {HotkeyHelpController} from '../input/hotkey-help-controller.js';
import {TextScanner} from '../language/text-scanner.js';
-import {yomitan} from '../yomitan.js';
import {DisplayContentManager} from './display-content-manager.js';
import {DisplayGenerator} from './display-generator.js';
import {DisplayHistory} from './display-history.js';
@@ -46,14 +45,17 @@ import {QueryParser} from './query-parser.js';
*/
export class Display extends EventDispatcher {
/**
+ * @param {import('../application.js').Application} application
* @param {number|undefined} tabId
* @param {number|undefined} frameId
* @param {import('display').DisplayPageType} pageType
* @param {import('../dom/document-focus-controller.js').DocumentFocusController} documentFocusController
* @param {import('../input/hotkey-handler.js').HotkeyHandler} hotkeyHandler
*/
- constructor(tabId, frameId, pageType, documentFocusController, hotkeyHandler) {
+ constructor(application, tabId, frameId, pageType, documentFocusController, hotkeyHandler) {
super();
+ /** @type {import('../application.js').Application} */
+ this._application = application;
/** @type {number|undefined} */
this._tabId = tabId;
/** @type {number|undefined} */
@@ -131,6 +133,7 @@ export class Display extends EventDispatcher {
this._textSourceGenerator = new TextSourceGenerator();
/** @type {QueryParser} */
this._queryParser = new QueryParser({
+ api: application.api,
getSearchContext: this._getSearchContext.bind(this),
textSourceGenerator: this._textSourceGenerator
});
@@ -163,7 +166,7 @@ export class Display extends EventDispatcher {
/** @type {boolean} */
this._childrenSupported = true;
/** @type {?FrameEndpoint} */
- this._frameEndpoint = (pageType === 'popup' ? new FrameEndpoint() : null);
+ this._frameEndpoint = (pageType === 'popup' ? new FrameEndpoint(this._application.api) : null);
/** @type {?import('environment').Browser} */
this._browser = null;
/** @type {?HTMLTextAreaElement} */
@@ -224,6 +227,11 @@ export class Display extends EventDispatcher {
/* eslint-enable no-multi-spaces */
}
+ /** @type {import('../application.js').Application} */
+ get application() {
+ return this._application;
+ }
+
/** @type {DisplayGenerator} */
get displayGenerator() {
return this._displayGenerator;
@@ -307,7 +315,7 @@ export class Display extends EventDispatcher {
// State setup
const {documentElement} = document;
- const {browser} = await yomitan.api.getEnvironmentInfo();
+ const {browser} = await this._application.api.getEnvironmentInfo();
this._browser = browser;
if (documentElement !== null) {
@@ -315,8 +323,8 @@ export class Display extends EventDispatcher {
}
// Prepare
- await this._hotkeyHelpController.prepare();
- await this._displayGenerator.prepare();
+ await this._hotkeyHelpController.prepare(this._application.api);
+ await this._displayGenerator.prepare(this._application.api);
this._queryParser.prepare();
this._history.prepare();
this._optionToggleHotkeyHandler.prepare();
@@ -325,8 +333,8 @@ export class Display extends EventDispatcher {
this._history.on('stateChanged', this._onStateChanged.bind(this));
this._queryParser.on('searched', this._onQueryParserSearch.bind(this));
this._progressIndicatorVisible.on('change', this._onProgressIndicatorVisibleChanged.bind(this));
- yomitan.on('extensionUnloaded', this._onExtensionUnloaded.bind(this));
- yomitan.crossFrame.registerHandlers([
+ this._application.on('extensionUnloaded', this._onExtensionUnloaded.bind(this));
+ this._application.crossFrame.registerHandlers([
['displayPopupMessage1', this._onDisplayPopupMessage1.bind(this)],
['displayPopupMessage2', this._onDisplayPopupMessage2.bind(this)]
]);
@@ -384,7 +392,7 @@ export class Display extends EventDispatcher {
* @param {Error} error
*/
onError(error) {
- if (yomitan.webExtension.unloaded) { return; }
+ if (this._application.webExtension.unloaded) { return; }
log.error(error);
}
@@ -412,7 +420,7 @@ export class Display extends EventDispatcher {
/** */
async updateOptions() {
- const options = await yomitan.api.optionsGet(this.getOptionsContext());
+ const options = await this._application.api.optionsGet(this.getOptionsContext());
const {scanning: scanningOptions, sentenceParsing: sentenceParsingOptions} = options;
this._options = options;
@@ -586,7 +594,7 @@ export class Display extends EventDispatcher {
if (typeof this._contentOriginTabId !== 'number' || typeof this._contentOriginFrameId !== 'number') {
throw new Error('No content origin is assigned');
}
- return await yomitan.crossFrame.invokeTab(this._contentOriginTabId, this._contentOriginFrameId, action, params);
+ return await this._application.crossFrame.invokeTab(this._contentOriginTabId, this._contentOriginFrameId, action, params);
}
/**
@@ -599,7 +607,7 @@ export class Display extends EventDispatcher {
if (this._parentFrameId === null || this._parentFrameId === this._frameId) {
throw new Error('Invalid parent frame');
}
- return await yomitan.crossFrame.invoke(this._parentFrameId, action, params);
+ return await this._application.crossFrame.invoke(this._parentFrameId, action, params);
}
/**
@@ -721,7 +729,7 @@ export class Display extends EventDispatcher {
/** @type {import('display').WindowApiHandler<'displayExtensionUnloaded'>} */
_onMessageExtensionUnloaded() {
- yomitan.webExtension.triggerUnloaded();
+ this._application.webExtension.triggerUnloaded();
}
// Private
@@ -900,7 +908,7 @@ export class Display extends EventDispatcher {
const element = /** @type {Element} */ (e.currentTarget);
let query = element.textContent;
if (query === null) { query = ''; }
- const dictionaryEntries = await yomitan.api.kanjiFind(query, optionsContext);
+ const dictionaryEntries = await this._application.api.kanjiFind(query, optionsContext);
/** @type {import('display').ContentDetails} */
const details = {
focus: false,
@@ -1136,7 +1144,7 @@ export class Display extends EventDispatcher {
*/
async _findDictionaryEntries(isKanji, source, wildcardsEnabled, optionsContext) {
if (isKanji) {
- const dictionaryEntries = await yomitan.api.kanjiFind(source, optionsContext);
+ const dictionaryEntries = await this._application.api.kanjiFind(source, optionsContext);
return dictionaryEntries;
} else {
/** @type {import('api').FindTermsDetails} */
@@ -1155,7 +1163,7 @@ export class Display extends EventDispatcher {
}
}
- const {dictionaryEntries} = await yomitan.api.termsFind(source, findDetails, optionsContext);
+ const {dictionaryEntries} = await this._application.api.termsFind(source, findDetails, optionsContext);
return dictionaryEntries;
}
}
@@ -1640,7 +1648,7 @@ export class Display extends EventDispatcher {
/** */
_closePopups() {
- yomitan.triggerClosePopups();
+ this._application.triggerClosePopups();
}
/**
@@ -1711,11 +1719,12 @@ export class Display extends EventDispatcher {
import('../app/frontend.js')
]);
- const popupFactory = new PopupFactory(this._frameId);
+ const popupFactory = new PopupFactory(this._application, this._frameId);
popupFactory.prepare();
/** @type {import('frontend').ConstructorDetails} */
const setupNestedPopupsOptions = {
+ application: this._application,
useProxyPopup,
parentPopupId,
parentFrameId,
@@ -1828,6 +1837,7 @@ export class Display extends EventDispatcher {
if (this._contentTextScanner === null) {
this._contentTextScanner = new TextScanner({
+ api: this._application.api,
node: window,
getSearchContext: this._getSearchContext.bind(this),
searchTerms: true,
@@ -1888,7 +1898,7 @@ export class Display extends EventDispatcher {
* @param {import('text-scanner').SearchedEventDetails} details
*/
_onContentTextScannerSearched({type, dictionaryEntries, sentence, textSource, optionsContext, error}) {
- if (error !== null && !yomitan.webExtension.unloaded) {
+ if (error !== null && !this._application.webExtension.unloaded) {
log.error(error);
}
diff --git a/ext/js/display/option-toggle-hotkey-handler.js b/ext/js/display/option-toggle-hotkey-handler.js
index d9065e7f..b2f48a3e 100644
--- a/ext/js/display/option-toggle-hotkey-handler.js
+++ b/ext/js/display/option-toggle-hotkey-handler.js
@@ -16,10 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {generateId} from '../core/utilities.js';
import {ExtensionError} from '../core/extension-error.js';
import {toError} from '../core/to-error.js';
-import {yomitan} from '../yomitan.js';
+import {generateId} from '../core/utilities.js';
export class OptionToggleHotkeyHandler {
/**
@@ -72,7 +71,7 @@ export class OptionToggleHotkeyHandler {
try {
const optionsContext = this._display.getOptionsContext();
- const getSettingsResponse = (await yomitan.api.getSettings([{
+ const getSettingsResponse = (await this._display.application.api.getSettings([{
scope: 'profile',
path,
optionsContext
@@ -97,7 +96,7 @@ export class OptionToggleHotkeyHandler {
value,
optionsContext
};
- const modifySettingsResponse = (await yomitan.api.modifySettings([modification], this._source))[0];
+ const modifySettingsResponse = (await this._display.application.api.modifySettings([modification], this._source))[0];
const {error: modifySettingsError} = modifySettingsResponse;
if (typeof modifySettingsError !== 'undefined') {
throw ExtensionError.deserialize(modifySettingsError);
diff --git a/ext/js/display/popup-main.js b/ext/js/display/popup-main.js
index 870e039e..2ca2fcd3 100644
--- a/ext/js/display/popup-main.js
+++ b/ext/js/display/popup-main.js
@@ -16,10 +16,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import {Application} from '../application.js';
import {log} from '../core/logger.js';
import {DocumentFocusController} from '../dom/document-focus-controller.js';
import {HotkeyHandler} from '../input/hotkey-handler.js';
-import {yomitan} from '../yomitan.js';
import {DisplayAnki} from './display-anki.js';
import {DisplayAudio} from './display-audio.js';
import {DisplayProfileSelection} from './display-profile-selection.js';
@@ -32,14 +32,15 @@ async function main() {
const documentFocusController = new DocumentFocusController();
documentFocusController.prepare();
- await yomitan.prepare();
+ const application = new Application();
+ await application.prepare();
- const {tabId, frameId} = await yomitan.api.frameInformationGet();
+ const {tabId, frameId} = await application.api.frameInformationGet();
const hotkeyHandler = new HotkeyHandler();
- hotkeyHandler.prepare();
+ hotkeyHandler.prepare(application.crossFrame);
- const display = new Display(tabId, frameId, 'popup', documentFocusController, hotkeyHandler);
+ const display = new Display(application, tabId, frameId, 'popup', documentFocusController, hotkeyHandler);
await display.prepare();
const displayAudio = new DisplayAudio(display);
@@ -58,7 +59,7 @@ async function main() {
document.documentElement.dataset.loaded = 'true';
- yomitan.ready();
+ application.ready();
} catch (e) {
log.error(e);
}
diff --git a/ext/js/display/query-parser.js b/ext/js/display/query-parser.js
index 178bb110..daa298d2 100644
--- a/ext/js/display/query-parser.js
+++ b/ext/js/display/query-parser.js
@@ -21,7 +21,6 @@ import {log} from '../core/logger.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
import {convertHiraganaToKatakana, convertKatakanaToHiragana, isStringEntirelyKana} from '../language/japanese.js';
import {TextScanner} from '../language/text-scanner.js';
-import {yomitan} from '../yomitan.js';
/**
* @augments EventDispatcher<import('query-parser').Events>
@@ -30,8 +29,10 @@ export class QueryParser extends EventDispatcher {
/**
* @param {import('display').QueryParserConstructorDetails} details
*/
- constructor({getSearchContext, textSourceGenerator}) {
+ constructor({api, getSearchContext, textSourceGenerator}) {
super();
+ /** @type {import('../comm/api.js').API} */
+ this._api = api;
/** @type {import('display').GetSearchContextCallback} */
this._getSearchContext = getSearchContext;
/** @type {string} */
@@ -58,6 +59,7 @@ export class QueryParser extends EventDispatcher {
this._queryParserModeSelect = querySelectorNotNull(document, '#query-parser-mode-select');
/** @type {TextScanner} */
this._textScanner = new TextScanner({
+ api,
node: this._queryParser,
getSearchContext,
searchTerms: true,
@@ -128,7 +130,7 @@ export class QueryParser extends EventDispatcher {
/** @type {?import('core').TokenObject} */
const token = {};
this._setTextToken = token;
- this._parseResults = await yomitan.api.parseText(text, this._getOptionsContext(), this._scanLength, this._useInternalParser, this._useMecabParser);
+ this._parseResults = await this._api.parseText(text, this._getOptionsContext(), this._scanLength, this._useInternalParser, this._useMecabParser);
if (this._setTextToken !== token) { return; }
this._refreshSelectedParser();
@@ -214,7 +216,7 @@ export class QueryParser extends EventDispatcher {
scope: 'profile',
optionsContext
};
- yomitan.api.modifySettings([modification], 'search');
+ this._api.modifySettings([modification], 'search');
}
/**
diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js
index ff4340c1..49c69520 100644
--- a/ext/js/display/search-display-controller.js
+++ b/ext/js/display/search-display-controller.js
@@ -21,7 +21,6 @@ import {ClipboardMonitor} from '../comm/clipboard-monitor.js';
import {createApiMap, invokeApiMapHandler} from '../core/api-map.js';
import {EventListenerCollection} from '../core/event-listener-collection.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
-import {yomitan} from '../yomitan.js';
export class SearchDisplayController {
/**
@@ -71,7 +70,7 @@ export class SearchDisplayController {
/** @type {ClipboardMonitor} */
this._clipboardMonitor = new ClipboardMonitor({
clipboardReader: {
- getText: yomitan.api.clipboardGet.bind(yomitan.api)
+ getText: this._display.application.api.clipboardGet.bind(this._display.application.api)
}
});
/** @type {import('application').ApiMap} */
@@ -89,7 +88,7 @@ export class SearchDisplayController {
this._searchPersistentStateController.on('modeChange', this._onModeChange.bind(this));
chrome.runtime.onMessage.addListener(this._onMessage.bind(this));
- yomitan.on('optionsUpdated', this._onOptionsUpdated.bind(this));
+ this._display.application.on('optionsUpdated', this._onOptionsUpdated.bind(this));
this._display.on('optionsUpdated', this._onDisplayOptionsUpdated.bind(this));
this._display.on('contentUpdateStart', this._onContentUpdateStart.bind(this));
@@ -297,7 +296,7 @@ export class SearchDisplayController {
scope: 'profile',
optionsContext: this._display.getOptionsContext()
};
- yomitan.api.modifySettings([modification], 'search');
+ this._display.application.api.modifySettings([modification], 'search');
}
/**
@@ -430,7 +429,7 @@ export class SearchDisplayController {
scope: 'profile',
optionsContext: this._display.getOptionsContext()
};
- await yomitan.api.modifySettings([modification], 'search');
+ await this._display.application.api.modifySettings([modification], 'search');
}
/** */
diff --git a/ext/js/display/search-main.js b/ext/js/display/search-main.js
index dedad163..dc4f1b7e 100644
--- a/ext/js/display/search-main.js
+++ b/ext/js/display/search-main.js
@@ -16,10 +16,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import {Application} from '../application.js';
import {log} from '../core/logger.js';
import {DocumentFocusController} from '../dom/document-focus-controller.js';
import {HotkeyHandler} from '../input/hotkey-handler.js';
-import {yomitan} from '../yomitan.js';
import {DisplayAnki} from './display-anki.js';
import {DisplayAudio} from './display-audio.js';
import {Display} from './display.js';
@@ -30,6 +30,8 @@ import {SearchPersistentStateController} from './search-persistent-state-control
/** Entry point. */
async function main() {
try {
+ const application = new Application();
+
const documentFocusController = new DocumentFocusController('#search-textbox');
documentFocusController.prepare();
@@ -39,14 +41,14 @@ async function main() {
const searchActionPopupController = new SearchActionPopupController(searchPersistentStateController);
searchActionPopupController.prepare();
- await yomitan.prepare();
+ await application.prepare();
- const {tabId, frameId} = await yomitan.api.frameInformationGet();
+ const {tabId, frameId} = await application.api.frameInformationGet();
const hotkeyHandler = new HotkeyHandler();
- hotkeyHandler.prepare();
+ hotkeyHandler.prepare(application.crossFrame);
- const display = new Display(tabId, frameId, 'search', documentFocusController, hotkeyHandler);
+ const display = new Display(application, tabId, frameId, 'search', documentFocusController, hotkeyHandler);
await display.prepare();
const displayAudio = new DisplayAudio(display);
@@ -62,7 +64,7 @@ async function main() {
document.documentElement.dataset.loaded = 'true';
- yomitan.ready();
+ application.ready();
} catch (e) {
log.error(e);
}
diff --git a/ext/js/dom/style-util.js b/ext/js/dom/style-util.js
index ac20e655..e5046e5c 100644
--- a/ext/js/dom/style-util.js
+++ b/ext/js/dom/style-util.js
@@ -15,8 +15,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {yomitan} from '../yomitan.js';
-
/** @type {Map<string, ?HTMLStyleElement|HTMLLinkElement>} */
const injectedStylesheets = new Map();
/** @type {WeakMap<Node, Map<string, ?HTMLStyleElement|HTMLLinkElement>>} */
@@ -54,6 +52,7 @@ function setInjectedStylesheet(id, parentNode, value) {
}
/**
+ * @param {import('../application.js').Application} application
* @param {string} id
* @param {'code'|'file'|'file-content'} type
* @param {string} value
@@ -62,8 +61,8 @@ function setInjectedStylesheet(id, parentNode, value) {
* @returns {Promise<?HTMLStyleElement|HTMLLinkElement>}
* @throws {Error}
*/
-export async function loadStyle(id, type, value, useWebExtensionApi = false, parentNode = null) {
- if (useWebExtensionApi && yomitan.isExtensionUrl(window.location.href)) {
+export async function loadStyle(application, id, type, value, useWebExtensionApi = false, parentNode = null) {
+ if (useWebExtensionApi && application.isExtensionUrl(window.location.href)) {
// Permissions error will occur if trying to use the WebExtension API to inject into an extension page
useWebExtensionApi = false;
}
@@ -79,7 +78,7 @@ export async function loadStyle(id, type, value, useWebExtensionApi = false, par
}
if (type === 'file-content') {
- value = await yomitan.api.getStylesheetContent(value);
+ value = await application.api.getStylesheetContent(value);
type = 'code';
useWebExtensionApi = false;
}
@@ -91,7 +90,7 @@ export async function loadStyle(id, type, value, useWebExtensionApi = false, par
}
setInjectedStylesheet(id, parentNode, null);
- await yomitan.api.injectStylesheet(type, value);
+ await application.api.injectStylesheet(type, value);
return null;
}
diff --git a/ext/js/input/hotkey-handler.js b/ext/js/input/hotkey-handler.js
index 3b40a86d..9caedcc2 100644
--- a/ext/js/input/hotkey-handler.js
+++ b/ext/js/input/hotkey-handler.js
@@ -19,7 +19,6 @@
import {EventDispatcher} from '../core/event-dispatcher.js';
import {EventListenerCollection} from '../core/event-listener-collection.js';
import {DocumentUtil} from '../dom/document-util.js';
-import {yomitan} from '../yomitan.js';
/**
* Class which handles hotkey events and actions.
@@ -47,11 +46,12 @@ export class HotkeyHandler extends EventDispatcher {
/**
* Begins listening to key press events in order to detect hotkeys.
+ * @param {import('../comm/cross-frame-api.js').CrossFrameAPI} crossFrameApi
*/
- prepare() {
+ prepare(crossFrameApi) {
this._isPrepared = true;
this._updateEventHandlers();
- yomitan.crossFrame.registerHandlers([
+ crossFrameApi.registerHandlers([
['hotkeyHandlerForwardHotkey', this._onMessageForwardHotkey.bind(this)]
]);
}
diff --git a/ext/js/input/hotkey-help-controller.js b/ext/js/input/hotkey-help-controller.js
index 4c4f56d5..a75ab9db 100644
--- a/ext/js/input/hotkey-help-controller.js
+++ b/ext/js/input/hotkey-help-controller.js
@@ -16,9 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import {isObject} from '../core/utilities.js';
import {parseJson} from '../core/json.js';
-import {yomitan} from '../yomitan.js';
+import {isObject} from '../core/utilities.js';
import {HotkeyUtil} from './hotkey-util.js';
export class HotkeyHelpController {
@@ -34,10 +33,10 @@ export class HotkeyHelpController {
}
/**
- * @returns {Promise<void>}
+ * @param {import('../comm/api.js').API} api
*/
- async prepare() {
- const {platform: {os}} = await yomitan.api.getEnvironmentInfo();
+ async prepare(api) {
+ const {platform: {os}} = await api.getEnvironmentInfo();
this._hotkeyUtil.os = os;
await this._setupGlobalCommands(this._globalActionHotkeys);
}
diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js
index 6228a82c..d78c4c74 100644
--- a/ext/js/language/text-scanner.js
+++ b/ext/js/language/text-scanner.js
@@ -22,7 +22,6 @@ import {log} from '../core/logger.js';
import {clone} from '../core/utilities.js';
import {DocumentUtil} from '../dom/document-util.js';
import {TextSourceElement} from '../dom/text-source-element.js';
-import {yomitan} from '../yomitan.js';
/**
* @augments EventDispatcher<import('text-scanner').Events>
@@ -32,6 +31,7 @@ export class TextScanner extends EventDispatcher {
* @param {import('text-scanner').ConstructorDetails} details
*/
constructor({
+ api,
node,
getSearchContext,
ignoreElements = null,
@@ -43,6 +43,8 @@ export class TextScanner extends EventDispatcher {
textSourceGenerator
}) {
super();
+ /** @type {import('../comm/api.js').API} */
+ this._api = api;
/** @type {HTMLElement|Window} */
this._node = node;
/** @type {import('text-scanner').GetSearchContextCallback} */
@@ -1204,7 +1206,7 @@ export class TextScanner extends EventDispatcher {
/** @type {import('api').FindTermsDetails} */
const details = {};
if (this._matchTypePrefix) { details.matchType = 'prefix'; }
- const {dictionaryEntries, originalTextLength} = await yomitan.api.termsFind(searchText, details, optionsContext);
+ const {dictionaryEntries, originalTextLength} = await this._api.termsFind(searchText, details, optionsContext);
if (dictionaryEntries.length === 0) { return null; }
textSource.setEndOffset(originalTextLength, false, layoutAwareScan);
@@ -1236,7 +1238,7 @@ export class TextScanner extends EventDispatcher {
const searchText = this.getTextSourceContent(textSource, 1, layoutAwareScan);
if (searchText.length === 0) { return null; }
- const dictionaryEntries = await yomitan.api.kanjiFind(searchText, optionsContext);
+ const dictionaryEntries = await this._api.kanjiFind(searchText, optionsContext);
if (dictionaryEntries.length === 0) { return null; }
textSource.setEndOffset(1, false, layoutAwareScan);
@@ -1564,7 +1566,7 @@ export class TextScanner extends EventDispatcher {
*/
async _hasJapanese(text) {
try {
- return await yomitan.api.textHasJapaneseCharacters(text);
+ return await this._api.textHasJapaneseCharacters(text);
} catch (e) {
return false;
}
diff --git a/ext/js/pages/action-popup-main.js b/ext/js/pages/action-popup-main.js
index 86201e83..6d2c85ab 100644
--- a/ext/js/pages/action-popup-main.js
+++ b/ext/js/pages/action-popup-main.js
@@ -16,13 +16,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import {Application} from '../application.js';
import {getAllPermissions, hasRequiredPermissionsForOptions} from '../data/permissions-util.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
import {HotkeyHelpController} from '../input/hotkey-help-controller.js';
-import {yomitan} from '../yomitan.js';
class DisplayController {
- constructor() {
+ /**
+ * @param {import('../comm/api.js').API} api
+ */
+ constructor(api) {
+ /** @type {import('../comm/api.js').API} */
+ this._api = api;
/** @type {?import('settings').Options} */
this._optionsFull = null;
}
@@ -36,7 +41,7 @@ class DisplayController {
this._setupButtonEvents('.action-open-search', 'openSearchPage', chrome.runtime.getURL('/search.html'), this._onSearchClick.bind(this));
this._setupButtonEvents('.action-open-info', 'openInfoPage', chrome.runtime.getURL('/info.html'));
- const optionsFull = await yomitan.api.optionsGetFull();
+ const optionsFull = await this._api.optionsGetFull();
this._optionsFull = optionsFull;
this._setupHotkeys();
@@ -108,7 +113,7 @@ class DisplayController {
const result = customHandler(e);
if (typeof result !== 'undefined') { return; }
}
- yomitan.api.commandExec(command, {mode: e.ctrlKey ? 'newTab' : 'existingOrNewTab'});
+ this._api.commandExec(command, {mode: e.ctrlKey ? 'newTab' : 'existingOrNewTab'});
e.preventDefault();
};
/**
@@ -116,7 +121,7 @@ class DisplayController {
*/
const onAuxClick = (e) => {
if (e.button !== 1) { return; }
- yomitan.api.commandExec(command, {mode: 'newTab'});
+ this._api.commandExec(command, {mode: 'newTab'});
e.preventDefault();
};
node.addEventListener('click', onClick, false);
@@ -180,7 +185,7 @@ class DisplayController {
*/
_setupOptions({options}) {
const extensionEnabled = options.general.enable;
- const onToggleChanged = () => yomitan.api.commandExec('toggleTextScanning');
+ const onToggleChanged = () => this._api.commandExec('toggleTextScanning');
for (const toggle of /** @type {NodeListOf<HTMLInputElement>} */ (document.querySelectorAll('#enable-search,#enable-search2'))) {
toggle.checked = extensionEnabled;
toggle.addEventListener('change', onToggleChanged, false);
@@ -192,7 +197,7 @@ class DisplayController {
/** */
async _setupHotkeys() {
const hotkeyHelpController = new HotkeyHelpController();
- await hotkeyHelpController.prepare();
+ await hotkeyHelpController.prepare(this._api);
const {profiles, profileCurrent} = /** @type {import('settings').Options} */ (this._optionsFull);
const primaryProfile = (profileCurrent >= 0 && profileCurrent < profiles.length) ? profiles[profileCurrent] : null;
@@ -250,7 +255,7 @@ class DisplayController {
scope: 'global',
optionsContext: null
};
- await yomitan.api.modifySettings([modification], 'action-popup');
+ await this._api.modifySettings([modification], 'action-popup');
}
/**
@@ -258,7 +263,7 @@ class DisplayController {
*/
async _updateDictionariesEnabledWarnings(options) {
const noDictionariesEnabledWarnings = /** @type {NodeListOf<HTMLElement>} */ (document.querySelectorAll('.no-dictionaries-enabled-warning'));
- const dictionaries = await yomitan.api.getDictionaryInfo();
+ const dictionaries = await this._api.getDictionaryInfo();
const enabledDictionaries = new Set();
for (const {name, enabled} of options.dictionaries) {
@@ -295,21 +300,22 @@ class DisplayController {
/** @returns {Promise<boolean>} */
async _isSafari() {
- const {browser} = await yomitan.api.getEnvironmentInfo();
+ const {browser} = await this._api.getEnvironmentInfo();
return browser === 'safari';
}
}
/** Entry point. */
async function main() {
- await yomitan.prepare();
+ const application = new Application();
+ await application.prepare();
- yomitan.api.logIndicatorClear();
+ application.api.logIndicatorClear();
- const displayController = new DisplayController();
+ const displayController = new DisplayController(application.api);
displayController.prepare();
- yomitan.ready();
+ application.ready();
}
await main();
diff --git a/ext/js/pages/info-main.js b/ext/js/pages/info-main.js
index dd55ab4b..ca5094b1 100644
--- a/ext/js/pages/info-main.js
+++ b/ext/js/pages/info-main.js
@@ -16,11 +16,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import {Application} from '../application.js';
import {log} from '../core/logger.js';
import {promiseTimeout} from '../core/utilities.js';
import {DocumentFocusController} from '../dom/document-focus-controller.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
-import {yomitan} from '../yomitan.js';
import {BackupController} from './settings/backup-controller.js';
import {SettingsController} from './settings/settings-controller.js';
@@ -57,11 +57,13 @@ function getOperatingSystemDisplayName(os) {
}
}
-/** */
-async function showAnkiConnectInfo() {
+/**
+ * @param {import('../comm/api.js').API} api
+ */
+async function showAnkiConnectInfo(api) {
let ankiConnectVersion = null;
try {
- ankiConnectVersion = await yomitan.api.getAnkiConnectVersion();
+ ankiConnectVersion = await api.getAnkiConnectVersion();
} catch (e) {
// NOP
}
@@ -78,11 +80,13 @@ async function showAnkiConnectInfo() {
ankiVersionUnknownElement.hidden = (ankiConnectVersion !== null);
}
-/** */
-async function showDictionaryInfo() {
+/**
+ * @param {import('../comm/api.js').API} api
+ */
+async function showDictionaryInfo(api) {
let dictionaryInfos;
try {
- dictionaryInfos = await yomitan.api.getDictionaryInfo();
+ dictionaryInfos = await api.getDictionaryInfo();
} catch (e) {
return;
}
@@ -121,11 +125,12 @@ async function main() {
const manifest = chrome.runtime.getManifest();
const language = chrome.i18n.getUILanguage();
- await yomitan.prepare();
+ const application = new Application();
+ await application.prepare();
const {userAgent} = navigator;
const {name, version} = manifest;
- const {browser, platform: {os}} = await yomitan.api.getEnvironmentInfo();
+ const {browser, platform: {os}} = await application.api.getEnvironmentInfo();
/** @type {HTMLLinkElement} */
const thisVersionLink = querySelectorNotNull(document, '#release-notes-this-version-link');
@@ -149,10 +154,10 @@ async function main() {
languageElement.textContent = `${language}`;
userAgentElement.textContent = userAgent;
- showAnkiConnectInfo();
- showDictionaryInfo();
+ showAnkiConnectInfo(application.api);
+ showDictionaryInfo(application.api);
- const settingsController = new SettingsController();
+ const settingsController = new SettingsController(application);
await settingsController.prepare();
const backupController = new BackupController(settingsController, null);
diff --git a/ext/js/pages/permissions-main.js b/ext/js/pages/permissions-main.js
index 38135689..1659bea5 100644
--- a/ext/js/pages/permissions-main.js
+++ b/ext/js/pages/permissions-main.js
@@ -16,11 +16,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import {Application} from '../application.js';
import {log} from '../core/logger.js';
import {promiseTimeout} from '../core/utilities.js';
import {DocumentFocusController} from '../dom/document-focus-controller.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
-import {yomitan} from '../yomitan.js';
import {ExtensionContentController} from './common/extension-content-controller.js';
import {ModalController} from './settings/modal-controller.js';
import {PermissionsOriginController} from './settings/permissions-origin-controller.js';
@@ -30,11 +30,11 @@ import {SettingsController} from './settings/settings-controller.js';
import {SettingsDisplayController} from './settings/settings-display-controller.js';
/**
- * @returns {Promise<void>}
+ * @param {import('../comm/api.js').API} api
*/
-async function setupEnvironmentInfo() {
+async function setupEnvironmentInfo(api) {
const {manifest_version: manifestVersion} = chrome.runtime.getManifest();
- const {browser, platform} = await yomitan.api.getEnvironmentInfo();
+ const {browser, platform} = await api.getEnvironmentInfo();
document.documentElement.dataset.browser = browser;
document.documentElement.dataset.os = platform.os;
document.documentElement.dataset.manifestVersion = `${manifestVersion}`;
@@ -90,6 +90,8 @@ function setupPermissionsToggles() {
/** Entry point. */
async function main() {
try {
+ const application = new Application();
+
const documentFocusController = new DocumentFocusController();
documentFocusController.prepare();
@@ -98,9 +100,9 @@ async function main() {
setupPermissionsToggles();
- await yomitan.prepare();
+ await application.prepare();
- setupEnvironmentInfo();
+ setupEnvironmentInfo(application.api);
/** @type {HTMLInputElement} */
const permissionCheckbox1 = querySelectorNotNull(document, '#permission-checkbox-allow-in-private-windows');
@@ -121,7 +123,7 @@ async function main() {
const modalController = new ModalController();
modalController.prepare();
- const settingsController = new SettingsController();
+ const settingsController = new SettingsController(application);
await settingsController.prepare();
const permissionsToggleController = new PermissionsToggleController(settingsController);
@@ -130,7 +132,7 @@ async function main() {
const permissionsOriginController = new PermissionsOriginController(settingsController);
permissionsOriginController.prepare();
- const persistentStorageController = new PersistentStorageController();
+ const persistentStorageController = new PersistentStorageController(application);
persistentStorageController.prepare();
await promiseTimeout(100);
diff --git a/ext/js/pages/settings/anki-controller.js b/ext/js/pages/settings/anki-controller.js
index 09ab3c03..ae6a71db 100644
--- a/ext/js/pages/settings/anki-controller.js
+++ b/ext/js/pages/settings/anki-controller.js
@@ -26,7 +26,6 @@ import {getRequiredPermissionsForAnkiFieldValue, hasPermissions, setPermissionsG
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {SelectorObserver} from '../../dom/selector-observer.js';
import {ObjectPropertyAccessor} from '../../general/object-property-accessor.js';
-import {yomitan} from '../../yomitan.js';
export class AnkiController {
/**
@@ -510,7 +509,7 @@ export class AnkiController {
let noteId = null;
for (const query of queries) {
- const notes = await yomitan.api.findAnkiNotes(query);
+ const notes = await this._settingsController.application.api.findAnkiNotes(query);
if (notes.length > 0) {
noteId = notes[0];
break;
@@ -521,7 +520,7 @@ export class AnkiController {
throw new Error('Could not find a note to test with');
}
- await yomitan.api.noteView(noteId, mode, false);
+ await this._settingsController.application.api.noteView(noteId, mode, false);
}
/**
diff --git a/ext/js/pages/settings/anki-templates-controller.js b/ext/js/pages/settings/anki-templates-controller.js
index 869c9e16..332102cf 100644
--- a/ext/js/pages/settings/anki-templates-controller.js
+++ b/ext/js/pages/settings/anki-templates-controller.js
@@ -21,7 +21,6 @@ import {toError} from '../../core/to-error.js';
import {AnkiNoteBuilder} from '../../data/anki-note-builder.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {TemplateRendererProxy} from '../../templates/template-renderer-proxy.js';
-import {yomitan} from '../../yomitan.js';
export class AnkiTemplatesController {
/**
@@ -55,12 +54,12 @@ export class AnkiTemplatesController {
/** @type {?import('./modal.js').Modal} */
this._fieldTemplateResetModal = null;
/** @type {AnkiNoteBuilder} */
- this._ankiNoteBuilder = new AnkiNoteBuilder(new TemplateRendererProxy());
+ this._ankiNoteBuilder = new AnkiNoteBuilder(settingsController.application.api, new TemplateRendererProxy());
}
/** */
async prepare() {
- this._defaultFieldTemplates = await yomitan.api.getDefaultAnkiFieldTemplates();
+ this._defaultFieldTemplates = await this._settingsController.application.api.getDefaultAnkiFieldTemplates();
/** @type {HTMLButtonElement} */
const menuButton = querySelectorNotNull(document, '#anki-card-templates-test-field-menu-button');
@@ -205,7 +204,7 @@ export class AnkiTemplatesController {
*/
async _getDictionaryEntry(text, optionsContext) {
if (this._cachedDictionaryEntryText !== text) {
- const {dictionaryEntries} = await yomitan.api.termsFind(text, {}, optionsContext);
+ const {dictionaryEntries} = await this._settingsController.application.api.termsFind(text, {}, optionsContext);
if (dictionaryEntries.length === 0) { return null; }
this._cachedDictionaryEntryValue = dictionaryEntries[0];
diff --git a/ext/js/pages/settings/backup-controller.js b/ext/js/pages/settings/backup-controller.js
index 053cc96b..79733c4d 100644
--- a/ext/js/pages/settings/backup-controller.js
+++ b/ext/js/pages/settings/backup-controller.js
@@ -25,7 +25,6 @@ import {OptionsUtil} from '../../data/options-util.js';
import {getAllPermissions} from '../../data/permissions-util.js';
import {arrayBufferUtf8Decode} from '../../data/sandbox/array-buffer-util.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
import {DictionaryController} from './dictionary-controller.js';
export class BackupController {
@@ -134,8 +133,8 @@ export class BackupController {
*/
async _getSettingsExportData(date) {
const optionsFull = await this._settingsController.getOptionsFull();
- const environment = await yomitan.api.getEnvironmentInfo();
- const fieldTemplatesDefault = await yomitan.api.getDefaultAnkiFieldTemplates();
+ const environment = await this._settingsController.application.api.getEnvironmentInfo();
+ const fieldTemplatesDefault = await this._settingsController.application.api.getDefaultAnkiFieldTemplates();
const permissions = await getAllPermissions();
// Format options
@@ -644,10 +643,10 @@ export class BackupController {
* @param {File} file
*/
async _importDatabase(databaseName, file) {
- await yomitan.api.purgeDatabase();
+ await this._settingsController.application.api.purgeDatabase();
await Dexie.import(file, {progressCallback: this._databaseImportProgressCallback});
- yomitan.api.triggerDatabaseUpdated('dictionary', 'import');
- yomitan.triggerStorageChanged();
+ this._settingsController.application.api.triggerDatabaseUpdated('dictionary', 'import');
+ this._settingsController.application.triggerStorageChanged();
}
/** */
diff --git a/ext/js/pages/settings/collapsible-dictionary-controller.js b/ext/js/pages/settings/collapsible-dictionary-controller.js
index e6930049..5ba61e0c 100644
--- a/ext/js/pages/settings/collapsible-dictionary-controller.js
+++ b/ext/js/pages/settings/collapsible-dictionary-controller.js
@@ -18,7 +18,6 @@
import {EventListenerCollection} from '../../core/event-listener-collection.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
export class CollapsibleDictionaryController {
/**
@@ -45,7 +44,7 @@ export class CollapsibleDictionaryController {
async prepare() {
await this._onDatabaseUpdated();
- yomitan.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
+ this._settingsController.application.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this));
this._settingsController.on('dictionarySettingsReordered', this._onDictionarySettingsReordered.bind(this));
}
diff --git a/ext/js/pages/settings/dictionary-controller.js b/ext/js/pages/settings/dictionary-controller.js
index 10dfdcdc..1d3c1730 100644
--- a/ext/js/pages/settings/dictionary-controller.js
+++ b/ext/js/pages/settings/dictionary-controller.js
@@ -20,7 +20,6 @@ import {EventListenerCollection} from '../../core/event-listener-collection.js';
import {log} from '../../core/logger.js';
import {DictionaryWorker} from '../../dictionary/dictionary-worker.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
class DictionaryEntry {
/**
@@ -437,7 +436,7 @@ export class DictionaryController {
/** @type {HTMLButtonElement} */
const dictionaryMoveButton = querySelectorNotNull(document, '#dictionary-move-button');
- yomitan.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
+ this._settingsController.application.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this));
this._allCheckbox.addEventListener('change', this._onAllCheckboxChange.bind(this), false);
dictionaryDeleteButton.addEventListener('click', this._onDictionaryConfirmDelete.bind(this), false);
@@ -917,7 +916,7 @@ export class DictionaryController {
*/
async _deleteDictionaryInternal(dictionaryTitle, onProgress) {
await new DictionaryWorker().deleteDictionary(dictionaryTitle, onProgress);
- yomitan.api.triggerDatabaseUpdated('dictionary', 'delete');
+ this._settingsController.application.api.triggerDatabaseUpdated('dictionary', 'delete');
}
/**
@@ -947,7 +946,7 @@ export class DictionaryController {
/** */
_triggerStorageChanged() {
- yomitan.triggerStorageChanged();
+ this._settingsController.application.triggerStorageChanged();
}
/** */
diff --git a/ext/js/pages/settings/dictionary-import-controller.js b/ext/js/pages/settings/dictionary-import-controller.js
index 183c0ccd..0484001d 100644
--- a/ext/js/pages/settings/dictionary-import-controller.js
+++ b/ext/js/pages/settings/dictionary-import-controller.js
@@ -21,7 +21,6 @@ import {log} from '../../core/logger.js';
import {toError} from '../../core/to-error.js';
import {DictionaryWorker} from '../../dictionary/dictionary-worker.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
import {DictionaryController} from './dictionary-controller.js';
export class DictionaryImportController {
@@ -120,7 +119,7 @@ export class DictionaryImportController {
this._setModifying(true);
this._hideErrors();
- await yomitan.api.purgeDatabase();
+ await this._settingsController.application.api.purgeDatabase();
const errors = await this._clearDictionarySettings();
if (errors.length > 0) {
@@ -236,7 +235,7 @@ export class DictionaryImportController {
async _importDictionary(file, importDetails, onProgress) {
const archiveContent = await this._readFile(file);
const {result, errors} = await new DictionaryWorker().importDictionary(archiveContent, importDetails, onProgress);
- yomitan.api.triggerDatabaseUpdated('dictionary', 'import');
+ this._settingsController.application.api.triggerDatabaseUpdated('dictionary', 'import');
const errors2 = await this._addDictionarySettings(result.sequenced, result.title);
if (errors.length > 0) {
@@ -399,6 +398,6 @@ export class DictionaryImportController {
/** */
_triggerStorageChanged() {
- yomitan.triggerStorageChanged();
+ this._settingsController.application.triggerStorageChanged();
}
}
diff --git a/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js b/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js
index 61330bb8..61eefffa 100644
--- a/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js
+++ b/ext/js/pages/settings/extension-keyboard-shortcuts-controller.js
@@ -20,7 +20,6 @@ import {EventListenerCollection} from '../../core/event-listener-collection.js';
import {isObject} from '../../core/utilities.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {HotkeyUtil} from '../../input/hotkey-util.js';
-import {yomitan} from '../../yomitan.js';
import {KeyboardMouseInputField} from './keyboard-mouse-input-field.js';
export class ExtensionKeyboardShortcutController {
@@ -63,7 +62,7 @@ export class ExtensionKeyboardShortcutController {
this._clearButton.addEventListener('click', this._onClearClick.bind(this));
}
- const {platform: {os}} = await yomitan.api.getEnvironmentInfo();
+ const {platform: {os}} = await this._settingsController.application.api.getEnvironmentInfo();
this._os = os;
this._hotkeyUtil.os = os;
diff --git a/ext/js/pages/settings/keyboard-shortcuts-controller.js b/ext/js/pages/settings/keyboard-shortcuts-controller.js
index 396b0cc2..9392f768 100644
--- a/ext/js/pages/settings/keyboard-shortcuts-controller.js
+++ b/ext/js/pages/settings/keyboard-shortcuts-controller.js
@@ -20,7 +20,6 @@ import {EventListenerCollection} from '../../core/event-listener-collection.js';
import {DocumentUtil} from '../../dom/document-util.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {ObjectPropertyAccessor} from '../../general/object-property-accessor.js';
-import {yomitan} from '../../yomitan.js';
import {KeyboardMouseInputField} from './keyboard-mouse-input-field.js';
export class KeyboardShortcutController {
@@ -81,7 +80,7 @@ export class KeyboardShortcutController {
/** */
async prepare() {
- const {platform: {os}} = await yomitan.api.getEnvironmentInfo();
+ const {platform: {os}} = await this._settingsController.application.api.getEnvironmentInfo();
this._os = os;
this._addButton.addEventListener('click', this._onAddClick.bind(this));
diff --git a/ext/js/pages/settings/mecab-controller.js b/ext/js/pages/settings/mecab-controller.js
index dec2be68..ba2f6166 100644
--- a/ext/js/pages/settings/mecab-controller.js
+++ b/ext/js/pages/settings/mecab-controller.js
@@ -18,10 +18,14 @@
import {toError} from '../../core/to-error.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
export class MecabController {
- constructor() {
+ /**
+ * @param {import('../../comm/api.js').API} api
+ */
+ constructor(api) {
+ /** @type {import('../../comm/api.js').API} */
+ this._api = api;
/** @type {HTMLButtonElement} */
this._testButton = querySelectorNotNull(document, '#test-mecab-button');
/** @type {HTMLElement} */
@@ -55,7 +59,7 @@ export class MecabController {
/** @type {HTMLButtonElement} */ (this._testButton).disabled = true;
resultsContainer.textContent = '';
resultsContainer.hidden = true;
- await yomitan.api.testMecab();
+ await this._api.testMecab();
this._setStatus('Connection was successful', false);
} catch (e) {
this._setStatus(toError(e).message, true);
diff --git a/ext/js/pages/settings/persistent-storage-controller.js b/ext/js/pages/settings/persistent-storage-controller.js
index baffa969..8b7726dd 100644
--- a/ext/js/pages/settings/persistent-storage-controller.js
+++ b/ext/js/pages/settings/persistent-storage-controller.js
@@ -18,14 +18,23 @@
import {isObject} from '../../core/utilities.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
export class PersistentStorageController {
- constructor() {
+ /**
+ * @param {import('../../application.js').Application} application
+ */
+ constructor(application) {
+ /** @type {import('../../application.js').Application} */
+ this._application = application;
/** @type {HTMLInputElement} */
this._persistentStorageCheckbox = querySelectorNotNull(document, '#storage-persistent-checkbox');
}
+ /** @type {import('../../application.js').Application} */
+ get application() {
+ return this._application;
+ }
+
/** */
async prepare() {
this._persistentStorageCheckbox.addEventListener('change', this._onPersistentStorageCheckboxChange.bind(this), false);
@@ -82,7 +91,7 @@ export class PersistentStorageController {
const node = document.querySelector('#storage-persistent-fail-warning');
if (node !== null) { node.hidden = isStoragePeristent; }
- yomitan.triggerStorageChanged();
+ this._application.triggerStorageChanged();
}
/**
diff --git a/ext/js/pages/settings/popup-preview-frame-main.js b/ext/js/pages/settings/popup-preview-frame-main.js
index e3d7d0ec..fd08bf1d 100644
--- a/ext/js/pages/settings/popup-preview-frame-main.js
+++ b/ext/js/pages/settings/popup-preview-frame-main.js
@@ -17,17 +17,18 @@
*/
import {PopupFactory} from '../../app/popup-factory.js';
+import {Application} from '../../application.js';
import {log} from '../../core/logger.js';
import {HotkeyHandler} from '../../input/hotkey-handler.js';
-import {yomitan} from '../../yomitan.js';
import {PopupPreviewFrame} from './popup-preview-frame.js';
/** Entry point. */
async function main() {
try {
- await yomitan.prepare();
+ const application = new Application();
+ await application.prepare();
- const {tabId, frameId} = await yomitan.api.frameInformationGet();
+ const {tabId, frameId} = await application.api.frameInformationGet();
if (typeof tabId === 'undefined') {
throw new Error('Failed to get tabId');
}
@@ -36,12 +37,12 @@ async function main() {
}
const hotkeyHandler = new HotkeyHandler();
- hotkeyHandler.prepare();
+ hotkeyHandler.prepare(application.crossFrame);
- const popupFactory = new PopupFactory(frameId);
+ const popupFactory = new PopupFactory(application, frameId);
popupFactory.prepare();
- const preview = new PopupPreviewFrame(tabId, frameId, popupFactory, hotkeyHandler);
+ const preview = new PopupPreviewFrame(application, tabId, frameId, popupFactory, hotkeyHandler);
await preview.prepare();
document.documentElement.dataset.loaded = 'true';
diff --git a/ext/js/pages/settings/popup-preview-frame.js b/ext/js/pages/settings/popup-preview-frame.js
index 7a899641..e9cfa541 100644
--- a/ext/js/pages/settings/popup-preview-frame.js
+++ b/ext/js/pages/settings/popup-preview-frame.js
@@ -20,16 +20,18 @@ import * as wanakana from '../../../lib/wanakana.js';
import {Frontend} from '../../app/frontend.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {TextSourceRange} from '../../dom/text-source-range.js';
-import {yomitan} from '../../yomitan.js';
export class PopupPreviewFrame {
/**
+ * @param {import('../../application.js').Application} application
* @param {number} tabId
* @param {number} frameId
* @param {import('../../app/popup-factory.js').PopupFactory} popupFactory
* @param {import('../../input/hotkey-handler.js').HotkeyHandler} hotkeyHandler
*/
- constructor(tabId, frameId, popupFactory, hotkeyHandler) {
+ constructor(application, tabId, frameId, popupFactory, hotkeyHandler) {
+ /** @type {import('../../application.js').Application} */
+ this._application = application;
/** @type {number} */
this._tabId = tabId;
/** @type {number} */
@@ -86,11 +88,12 @@ export class PopupPreviewFrame {
// Overwrite API functions
/** @type {?(optionsContext: import('settings').OptionsContext) => Promise<import('settings').ProfileOptions>} */
- this._apiOptionsGetOld = yomitan.api.optionsGet.bind(yomitan.api);
- yomitan.api.optionsGet = this._apiOptionsGet.bind(this);
+ this._apiOptionsGetOld = this._application.api.optionsGet.bind(this._application.api);
+ this._application.api.optionsGet = this._apiOptionsGet.bind(this);
// Overwrite frontend
this._frontend = new Frontend({
+ application: this._application,
tabId: this._tabId,
frameId: this._frameId,
popupFactory: this._popupFactory,
diff --git a/ext/js/pages/settings/popup-window-controller.js b/ext/js/pages/settings/popup-window-controller.js
index 1b767f77..62879f3b 100644
--- a/ext/js/pages/settings/popup-window-controller.js
+++ b/ext/js/pages/settings/popup-window-controller.js
@@ -17,9 +17,16 @@
*/
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
export class PopupWindowController {
+ /**
+ * @param {import('../../comm/api.js').API} api
+ */
+ constructor(api) {
+ /** @type {import('../../comm/api.js').API} */
+ this._api = api;
+ }
+
/** */
prepare() {
/** @type {HTMLElement} */
@@ -39,6 +46,6 @@ export class PopupWindowController {
/** */
async _testWindowOpen() {
- await yomitan.api.getOrCreateSearchPopup({focus: true});
+ await this._api.getOrCreateSearchPopup({focus: true});
}
}
diff --git a/ext/js/pages/settings/profile-controller.js b/ext/js/pages/settings/profile-controller.js
index 73926a69..c5ccbe7d 100644
--- a/ext/js/pages/settings/profile-controller.js
+++ b/ext/js/pages/settings/profile-controller.js
@@ -19,7 +19,6 @@
import {EventListenerCollection} from '../../core/event-listener-collection.js';
import {clone} from '../../core/utilities.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
import {ProfileConditionsUI} from './profile-conditions-ui.js';
export class ProfileController {
@@ -82,7 +81,7 @@ export class ProfileController {
/** */
async prepare() {
- const {platform: {os}} = await yomitan.api.getEnvironmentInfo();
+ const {platform: {os}} = await this._settingsController.application.api.getEnvironmentInfo();
this._profileConditionsUI.os = os;
this._profileRemoveModal = this._modalController.getModal('profile-remove');
diff --git a/ext/js/pages/settings/scan-inputs-controller.js b/ext/js/pages/settings/scan-inputs-controller.js
index 2dfa3de3..f1547fe4 100644
--- a/ext/js/pages/settings/scan-inputs-controller.js
+++ b/ext/js/pages/settings/scan-inputs-controller.js
@@ -19,7 +19,6 @@
import {EventListenerCollection} from '../../core/event-listener-collection.js';
import {DocumentUtil} from '../../dom/document-util.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
import {KeyboardMouseInputField} from './keyboard-mouse-input-field.js';
export class ScanInputsController {
@@ -43,7 +42,7 @@ export class ScanInputsController {
/** */
async prepare() {
- const {platform: {os}} = await yomitan.api.getEnvironmentInfo();
+ const {platform: {os}} = await this._settingsController.application.api.getEnvironmentInfo();
this._os = os;
this._scanningInputCountNodes = /** @type {NodeListOf<HTMLElement>} */ (document.querySelectorAll('.scanning-input-count'));
diff --git a/ext/js/pages/settings/scan-inputs-simple-controller.js b/ext/js/pages/settings/scan-inputs-simple-controller.js
index e4f34c99..b09a3a76 100644
--- a/ext/js/pages/settings/scan-inputs-simple-controller.js
+++ b/ext/js/pages/settings/scan-inputs-simple-controller.js
@@ -18,7 +18,6 @@
import {querySelectorNotNull} from '../../dom/query-selector.js';
import {HotkeyUtil} from '../../input/hotkey-util.js';
-import {yomitan} from '../../yomitan.js';
import {ScanInputsController} from './scan-inputs-controller.js';
export class ScanInputsSimpleController {
@@ -40,7 +39,7 @@ export class ScanInputsSimpleController {
/** */
async prepare() {
- const {platform: {os}} = await yomitan.api.getEnvironmentInfo();
+ const {platform: {os}} = await this._settingsController.application.api.getEnvironmentInfo();
this._hotkeyUtil.os = os;
this._mainScanModifierKeyInputHasOther = false;
diff --git a/ext/js/pages/settings/secondary-search-dictionary-controller.js b/ext/js/pages/settings/secondary-search-dictionary-controller.js
index 592f5eeb..c708bf65 100644
--- a/ext/js/pages/settings/secondary-search-dictionary-controller.js
+++ b/ext/js/pages/settings/secondary-search-dictionary-controller.js
@@ -18,7 +18,6 @@
import {EventListenerCollection} from '../../core/event-listener-collection.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
export class SecondarySearchDictionaryController {
/**
@@ -41,7 +40,7 @@ export class SecondarySearchDictionaryController {
async prepare() {
await this._onDatabaseUpdated();
- yomitan.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
+ this._settingsController.application.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this));
this._settingsController.on('dictionarySettingsReordered', this._onDictionarySettingsReordered.bind(this));
}
diff --git a/ext/js/pages/settings/settings-controller.js b/ext/js/pages/settings/settings-controller.js
index 49fa9c9e..3f389271 100644
--- a/ext/js/pages/settings/settings-controller.js
+++ b/ext/js/pages/settings/settings-controller.js
@@ -22,14 +22,18 @@ import {generateId, isObject} from '../../core/utilities.js';
import {OptionsUtil} from '../../data/options-util.js';
import {getAllPermissions} from '../../data/permissions-util.js';
import {HtmlTemplateCollection} from '../../dom/html-template-collection.js';
-import {yomitan} from '../../yomitan.js';
/**
* @augments EventDispatcher<import('settings-controller').Events>
*/
export class SettingsController extends EventDispatcher {
- constructor() {
+ /**
+ * @param {import('../../application.js').Application} application
+ */
+ constructor(application) {
super();
+ /** @type {import('../../application.js').Application} */
+ this._application = application;
/** @type {number} */
this._profileIndex = 0;
/** @type {string} */
@@ -43,6 +47,11 @@ export class SettingsController extends EventDispatcher {
this._templates.load(document);
}
+ /** @type {import('../../application.js').Application} */
+ get application() {
+ return this._application;
+ }
+
/** @type {string} */
get source() {
return this._source;
@@ -60,7 +69,7 @@ export class SettingsController extends EventDispatcher {
/** */
async prepare() {
- yomitan.on('optionsUpdated', this._onOptionsUpdated.bind(this));
+ this._application.on('optionsUpdated', this._onOptionsUpdated.bind(this));
if (this._canObservePermissionsChanges()) {
chrome.permissions.onAdded.addListener(this._onPermissionsChanged.bind(this));
chrome.permissions.onRemoved.addListener(this._onPermissionsChanged.bind(this));
@@ -82,14 +91,14 @@ export class SettingsController extends EventDispatcher {
*/
async getOptions() {
const optionsContext = this.getOptionsContext();
- return await yomitan.api.optionsGet(optionsContext);
+ return await this._application.api.optionsGet(optionsContext);
}
/**
* @returns {Promise<import('settings').Options>}
*/
async getOptionsFull() {
- return await yomitan.api.optionsGetFull();
+ return await this._application.api.optionsGetFull();
}
/**
@@ -97,7 +106,7 @@ export class SettingsController extends EventDispatcher {
*/
async setAllSettings(value) {
const profileIndex = value.profileCurrent;
- await yomitan.api.setAllSettings(value, this._source);
+ await this._application.api.setAllSettings(value, this._source);
this._setProfileIndex(profileIndex, true);
}
@@ -171,7 +180,7 @@ export class SettingsController extends EventDispatcher {
* @returns {Promise<import('dictionary-importer').Summary[]>}
*/
async getDictionaryInfo() {
- return await yomitan.api.getDictionaryInfo();
+ return await this._application.api.getDictionaryInfo();
}
/**
@@ -279,7 +288,7 @@ export class SettingsController extends EventDispatcher {
this._modifyOptionsScope(target2);
return target2;
});
- return await yomitan.api.getSettings(targets2);
+ return await this._application.api.getSettings(targets2);
}
/**
@@ -294,7 +303,7 @@ export class SettingsController extends EventDispatcher {
this._modifyOptionsScope(target2);
return target2;
});
- return await yomitan.api.modifySettings(targets2, this._source);
+ return await this._application.api.modifySettings(targets2, this._source);
}
/**
diff --git a/ext/js/pages/settings/settings-main.js b/ext/js/pages/settings/settings-main.js
index 7e458043..c3391173 100644
--- a/ext/js/pages/settings/settings-main.js
+++ b/ext/js/pages/settings/settings-main.js
@@ -16,10 +16,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import {Application} from '../../application.js';
import {log} from '../../core/logger.js';
import {DocumentFocusController} from '../../dom/document-focus-controller.js';
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
import {ExtensionContentController} from '../common/extension-content-controller.js';
import {AnkiController} from './anki-controller.js';
import {AnkiTemplatesController} from './anki-templates-controller.js';
@@ -78,7 +78,8 @@ async function main() {
document.documentElement.dataset.loadingStalled = 'true';
}, 1000);
- await yomitan.prepare();
+ const application = new Application();
+ await application.prepare();
if (prepareTimer !== null) {
clearTimeout(prepareTimer);
@@ -91,10 +92,10 @@ async function main() {
const modalController = new ModalController();
modalController.prepare();
- const settingsController = new SettingsController();
+ const settingsController = new SettingsController(application);
await settingsController.prepare();
- const persistentStorageController = new PersistentStorageController();
+ const persistentStorageController = new PersistentStorageController(application);
persistentStorageController.prepare();
const storageController = new StorageController(persistentStorageController);
@@ -154,10 +155,10 @@ async function main() {
const extensionKeyboardShortcutController = new ExtensionKeyboardShortcutController(settingsController);
extensionKeyboardShortcutController.prepare();
- const popupWindowController = new PopupWindowController();
+ const popupWindowController = new PopupWindowController(application.api);
popupWindowController.prepare();
- const mecabController = new MecabController();
+ const mecabController = new MecabController(application.api);
mecabController.prepare();
const collapsibleDictionaryController = new CollapsibleDictionaryController(settingsController);
diff --git a/ext/js/pages/settings/sort-frequency-dictionary-controller.js b/ext/js/pages/settings/sort-frequency-dictionary-controller.js
index f5b230f0..c8e9918b 100644
--- a/ext/js/pages/settings/sort-frequency-dictionary-controller.js
+++ b/ext/js/pages/settings/sort-frequency-dictionary-controller.js
@@ -17,7 +17,6 @@
*/
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
export class SortFrequencyDictionaryController {
/**
@@ -42,7 +41,7 @@ export class SortFrequencyDictionaryController {
async prepare() {
await this._onDatabaseUpdated();
- yomitan.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
+ this._settingsController.application.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this));
this._sortFrequencyDictionarySelect.addEventListener('change', this._onSortFrequencyDictionarySelectChange.bind(this));
this._sortFrequencyDictionaryOrderSelect.addEventListener('change', this._onSortFrequencyDictionaryOrderSelectChange.bind(this));
@@ -157,7 +156,7 @@ export class SortFrequencyDictionaryController {
const lessCommonTerms = ['行なう', '論じる', '過す', '行方', '人口', '猫', '犬', '滝', '理', '暁'];
const terms = [...moreCommonTerms, ...lessCommonTerms];
- const frequencies = await yomitan.api.getTermFrequencies(
+ const frequencies = await this._settingsController.application.api.getTermFrequencies(
terms.map((term) => ({term, reading: null})),
[dictionary]
);
diff --git a/ext/js/pages/settings/storage-controller.js b/ext/js/pages/settings/storage-controller.js
index 6be1fe24..9a3aa23a 100644
--- a/ext/js/pages/settings/storage-controller.js
+++ b/ext/js/pages/settings/storage-controller.js
@@ -17,7 +17,6 @@
*/
import {querySelectorNotNull} from '../../dom/query-selector.js';
-import {yomitan} from '../../yomitan.js';
export class StorageController {
/**
@@ -61,7 +60,7 @@ export class StorageController {
const storageRefreshButton = querySelectorNotNull(document, '#storage-refresh');
storageRefreshButton.addEventListener('click', this._onStorageRefreshButtonClick.bind(this), false);
- yomitan.on('storageChanged', this._onStorageChanged.bind(this));
+ this._persistentStorageController.application.on('storageChanged', this._onStorageChanged.bind(this));
this._updateStats();
}
diff --git a/ext/js/pages/welcome-main.js b/ext/js/pages/welcome-main.js
index 35472ec2..030d2826 100644
--- a/ext/js/pages/welcome-main.js
+++ b/ext/js/pages/welcome-main.js
@@ -16,10 +16,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+import {Application} from '../application.js';
import {log} from '../core/logger.js';
import {DocumentFocusController} from '../dom/document-focus-controller.js';
import {querySelectorNotNull} from '../dom/query-selector.js';
-import {yomitan} from '../yomitan.js';
import {ExtensionContentController} from './common/extension-content-controller.js';
import {DictionaryController} from './settings/dictionary-controller.js';
import {DictionaryImportController} from './settings/dictionary-import-controller.js';
@@ -31,10 +31,12 @@ import {SettingsController} from './settings/settings-controller.js';
import {SettingsDisplayController} from './settings/settings-display-controller.js';
import {StatusFooter} from './settings/status-footer.js';
-/** */
-async function setupEnvironmentInfo() {
+/**
+ * @param {import('../comm/api.js').API} api
+ */
+async function setupEnvironmentInfo(api) {
const {manifest_version: manifestVersion} = chrome.runtime.getManifest();
- const {browser, platform} = await yomitan.api.getEnvironmentInfo();
+ const {browser, platform} = await api.getEnvironmentInfo();
document.documentElement.dataset.browser = browser;
document.documentElement.dataset.os = platform.os;
document.documentElement.dataset.manifestVersion = `${manifestVersion}`;
@@ -62,9 +64,10 @@ async function main() {
const statusFooter = new StatusFooter(statusFooterElement);
statusFooter.prepare();
- await yomitan.prepare();
+ const application = new Application();
+ await application.prepare();
- setupEnvironmentInfo();
+ setupEnvironmentInfo(application.api);
chrome.storage.session.get({'needsCustomTemplatesWarning': false}).then((result) => {
if (result.needsCustomTemplatesWarning) {
@@ -78,7 +81,7 @@ async function main() {
const modalController = new ModalController();
modalController.prepare();
- const settingsController = new SettingsController();
+ const settingsController = new SettingsController(application);
await settingsController.prepare();
const dictionaryController = new DictionaryController(settingsController, modalController, statusFooter);