diff options
Diffstat (limited to 'ext/fg/js/popup-proxy-host.js')
-rw-r--r-- | ext/fg/js/popup-proxy-host.js | 161 |
1 files changed, 81 insertions, 80 deletions
diff --git a/ext/fg/js/popup-proxy-host.js b/ext/fg/js/popup-proxy-host.js index b2f18b97..c4f0c6ff 100644 --- a/ext/fg/js/popup-proxy-host.js +++ b/ext/fg/js/popup-proxy-host.js @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Alex Yatskov <alex@foosoft.net> + * Copyright (C) 2019-2020 Alex Yatskov <alex@foosoft.net> * Author: Alex Yatskov <alex@foosoft.net> * * This program is free software: you can redistribute it and/or modify @@ -13,126 +13,127 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. + * along with this program. If not, see <https://www.gnu.org/licenses/>. */ class PopupProxyHost { constructor() { - this.popups = {}; - this.nextId = 0; - this.apiReceiver = null; - this.frameIdPromise = null; + this._popups = new Map(); + this._nextId = 0; + this._apiReceiver = null; + this._frameIdPromise = null; } - static create() { - const popupProxyHost = new PopupProxyHost(); - popupProxyHost.prepare(); - return popupProxyHost; - } + // Public functions async prepare() { - this.frameIdPromise = apiFrameInformationGet(); - const {frameId} = await this.frameIdPromise; + this._frameIdPromise = apiFrameInformationGet(); + const {frameId} = await this._frameIdPromise; if (typeof frameId !== 'number') { return; } - this.apiReceiver = new FrontendApiReceiver(`popup-proxy-host#${frameId}`, { - createNestedPopup: ({parentId}) => this.createNestedPopup(parentId), - setOptions: ({id, options}) => this.setOptions(id, options), - hide: ({id, changeFocus}) => this.hide(id, changeFocus), - isVisibleAsync: ({id}) => this.isVisibleAsync(id), - setVisibleOverride: ({id, visible}) => this.setVisibleOverride(id, visible), - containsPoint: ({id, x, y}) => this.containsPoint(id, x, y), - showContent: ({id, elementRect, writingMode, type, details}) => this.showContent(id, elementRect, writingMode, type, details), - setCustomCss: ({id, css}) => this.setCustomCss(id, css), - clearAutoPlayTimer: ({id}) => this.clearAutoPlayTimer(id) - }); + this._apiReceiver = new FrontendApiReceiver(`popup-proxy-host#${frameId}`, new Map([ + ['createNestedPopup', ({parentId}) => this._onApiCreateNestedPopup(parentId)], + ['setOptions', ({id, options}) => this._onApiSetOptions(id, options)], + ['hide', ({id, changeFocus}) => this._onApiHide(id, changeFocus)], + ['isVisible', ({id}) => this._onApiIsVisibleAsync(id)], + ['setVisibleOverride', ({id, visible}) => this._onApiSetVisibleOverride(id, visible)], + ['containsPoint', ({id, x, y}) => this._onApiContainsPoint(id, x, y)], + ['showContent', ({id, elementRect, writingMode, type, details}) => this._onApiShowContent(id, elementRect, writingMode, type, details)], + ['setCustomCss', ({id, css}) => this._onApiSetCustomCss(id, css)], + ['clearAutoPlayTimer', ({id}) => this._onApiClearAutoPlayTimer(id)] + ])); } createPopup(parentId, depth) { - const parent = (typeof parentId === 'string' && hasOwn(this.popups, parentId) ? this.popups[parentId] : null); - const id = `${this.nextId}`; - if (parent !== null) { - depth = parent.depth + 1; - } - ++this.nextId; - const popup = new Popup(id, depth, this.frameIdPromise); - if (parent !== null) { - popup.parent = parent; - parent.child = popup; - } - this.popups[id] = popup; - return popup; - } - - async createNestedPopup(parentId) { - return this.createPopup(parentId, 0).id; + return this._createPopupInternal(parentId, depth).popup; } - getPopup(id) { - if (!hasOwn(this.popups, id)) { - throw new Error('Invalid popup ID'); - } - - return this.popups[id]; - } + // Message handlers - jsonRectToDOMRect(popup, jsonRect) { - let x = jsonRect.x; - let y = jsonRect.y; - if (popup.parent !== null) { - const popupRect = popup.parent.container.getBoundingClientRect(); - x += popupRect.x; - y += popupRect.y; - } - return new DOMRect(x, y, jsonRect.width, jsonRect.height); + async _onApiCreateNestedPopup(parentId) { + return this._createPopupInternal(parentId, 0).id; } - async setOptions(id, options) { - const popup = this.getPopup(id); + async _onApiSetOptions(id, options) { + const popup = this._getPopup(id); return await popup.setOptions(options); } - async hide(id, changeFocus) { - const popup = this.getPopup(id); + async _onApiHide(id, changeFocus) { + const popup = this._getPopup(id); return popup.hide(changeFocus); } - async isVisibleAsync(id) { - const popup = this.getPopup(id); - return await popup.isVisibleAsync(); + async _onApiIsVisibleAsync(id) { + const popup = this._getPopup(id); + return await popup.isVisible(); } - async setVisibleOverride(id, visible) { - const popup = this.getPopup(id); + async _onApiSetVisibleOverride(id, visible) { + const popup = this._getPopup(id); return await popup.setVisibleOverride(visible); } - async containsPoint(id, x, y) { - const popup = this.getPopup(id); + async _onApiContainsPoint(id, x, y) { + const popup = this._getPopup(id); return await popup.containsPoint(x, y); } - async showContent(id, elementRect, writingMode, type, details) { - const popup = this.getPopup(id); - elementRect = this.jsonRectToDOMRect(popup, elementRect); - if (!PopupProxyHost.popupCanShow(popup)) { return Promise.resolve(false); } + async _onApiShowContent(id, elementRect, writingMode, type, details) { + const popup = this._getPopup(id); + elementRect = PopupProxyHost._convertJsonRectToDOMRect(popup, elementRect); + if (!PopupProxyHost._popupCanShow(popup)) { return; } return await popup.showContent(elementRect, writingMode, type, details); } - async setCustomCss(id, css) { - const popup = this.getPopup(id); + async _onApiSetCustomCss(id, css) { + const popup = this._getPopup(id); return popup.setCustomCss(css); } - async clearAutoPlayTimer(id) { - const popup = this.getPopup(id); + async _onApiClearAutoPlayTimer(id) { + const popup = this._getPopup(id); return popup.clearAutoPlayTimer(); } - static popupCanShow(popup) { - return popup.parent === null || popup.parent.isVisible(); + // Private functions + + _createPopupInternal(parentId, depth) { + const parent = (typeof parentId === 'string' && this._popups.has(parentId) ? this._popups.get(parentId) : null); + const id = `${this._nextId}`; + if (parent !== null) { + depth = parent.depth + 1; + } + ++this._nextId; + const popup = new Popup(id, depth, this._frameIdPromise); + if (parent !== null) { + popup.setParent(parent); + } + this._popups.set(id, popup); + return {popup, id}; } -} -PopupProxyHost.instance = PopupProxyHost.create(); + _getPopup(id) { + const popup = this._popups.get(id); + if (typeof popup === 'undefined') { + throw new Error('Invalid popup ID'); + } + return popup; + } + + static _convertJsonRectToDOMRect(popup, jsonRect) { + let x = jsonRect.x; + let y = jsonRect.y; + if (popup.parent !== null) { + const popupRect = popup.parent.getContainerRect(); + x += popupRect.x; + y += popupRect.y; + } + return new DOMRect(x, y, jsonRect.width, jsonRect.height); + } + + static _popupCanShow(popup) { + return popup.parent === null || popup.parent.isVisibleSync(); + } +} |