Skip to content

Commit

Permalink
Application refactor (#591)
Browse files Browse the repository at this point in the history
* Rename Yomitan class to Application, change initialization style

* Rename file

* Update init

* Update config

* Remove dead code
  • Loading branch information
toasted-nutbread authored Feb 1, 2024
1 parent 2356223 commit dfd42ba
Show file tree
Hide file tree
Showing 60 changed files with 396 additions and 274 deletions.
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -658,9 +658,8 @@
},
{
"files": [
"ext/js/core.js",
"ext/js/core/extension-error.js",
"ext/js/yomitan.js",
"ext/js/application.js",
"ext/js/accessibility/accessibility-controller.js",
"ext/js/background/backend.js",
"ext/js/background/offscreen.js",
Expand Down
14 changes: 8 additions & 6 deletions ext/js/app/content-script-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -54,7 +56,7 @@ async function main() {
});
await frontend.prepare();

yomitan.ready();
application.ready();
} catch (e) {
log.error(e);
}
Expand Down
35 changes: 19 additions & 16 deletions ext/js/app/frontend.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
Expand All @@ -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} */
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)
Expand All @@ -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)],
Expand Down Expand Up @@ -230,7 +233,7 @@ export class Frontend {
try {
await this._updateOptionsInternal();
} catch (e) {
if (!yomitan.webExtension.unloaded) {
if (!this._application.webExtension.unloaded) {
throw e;
}
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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}});
});
}

Expand Down Expand Up @@ -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
}
Expand Down
15 changes: 10 additions & 5 deletions ext/js/app/popup-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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}[]>} */
Expand All @@ -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)],
Expand Down Expand Up @@ -119,6 +121,7 @@ export class PopupFactory {
id = generateId(16);
}
const popup = new PopupWindow({
application: this._application,
id,
depth,
frameId: this._frameId
Expand All @@ -131,6 +134,7 @@ export class PopupFactory {
id = generateId(16);
}
const popup = new Popup({
application: this._application,
id,
depth,
frameId: this._frameId,
Expand All @@ -152,14 +156,15 @@ 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,
childrenSupported
}));
id = info.id;
const popup = new PopupProxy({
application: this._application,
id,
depth: info.depth,
frameId: info.frameId,
Expand Down
8 changes: 5 additions & 3 deletions ext/js/app/popup-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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} */
Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -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;
}
}
Expand Down
16 changes: 9 additions & 7 deletions ext/js/app/popup-window.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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} */
Expand Down Expand Up @@ -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));
}

/**
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}
}
Expand All @@ -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',
Expand Down
Loading

0 comments on commit dfd42ba

Please sign in to comment.