From d5865db457ef6f96aa32662a8219fdf73478ae20 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 15 Aug 2020 17:27:03 -0400 Subject: [PATCH] Popup API refactor (#732) * Simplify how parent/child are set * Remove unused public frameId property * Change use of getFrame * Simplify parent access * Use property for the container * Remove isProxy * Public function API parity * Public property API parity --- ext/fg/js/frontend.js | 9 +++++-- ext/fg/js/popup-factory.js | 52 ++++++++++++++++++++++++++++---------- ext/fg/js/popup-proxy.js | 44 +++++++++++++++++++++++++++++--- ext/fg/js/popup.js | 50 +++++++++++------------------------- 4 files changed, 100 insertions(+), 55 deletions(-) diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 0c18fb2a..88038cd9 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -347,7 +347,13 @@ class Frontend { } _ignoreElements() { - return this._popup === null || this._popup.isProxy() ? [] : [this._popup.getContainer()]; + if (this._popup !== null) { + const container = this._popup.container; + if (container !== null) { + return [container]; + } + } + return []; } async _ignorePoint(x, y) { @@ -526,7 +532,6 @@ class Frontend { _broadcastRootPopupInformation() { if ( this._popup !== null && - !this._popup.isProxy() && this._depth === 0 && this._frameId === 0 ) { diff --git a/ext/fg/js/popup-factory.js b/ext/fg/js/popup-factory.js index 1dc7d61e..7d6f9846 100644 --- a/ext/fg/js/popup-factory.js +++ b/ext/fg/js/popup-factory.js @@ -30,16 +30,19 @@ class PopupFactory { prepare() { api.crossFrame.registerHandlers([ - ['getOrCreatePopup', {async: false, handler: this._onApiGetOrCreatePopup.bind(this)}], - ['setOptionsContext', {async: true, handler: this._onApiSetOptionsContext.bind(this)}], - ['hide', {async: false, handler: this._onApiHide.bind(this)}], - ['isVisible', {async: true, handler: this._onApiIsVisibleAsync.bind(this)}], - ['setVisibleOverride', {async: true, handler: this._onApiSetVisibleOverride.bind(this)}], - ['containsPoint', {async: true, handler: this._onApiContainsPoint.bind(this)}], - ['showContent', {async: true, handler: this._onApiShowContent.bind(this)}], - ['setCustomCss', {async: false, handler: this._onApiSetCustomCss.bind(this)}], - ['clearAutoPlayTimer', {async: false, handler: this._onApiClearAutoPlayTimer.bind(this)}], - ['setContentScale', {async: false, handler: this._onApiSetContentScale.bind(this)}] + ['getOrCreatePopup', {async: false, handler: this._onApiGetOrCreatePopup.bind(this)}], + ['setOptionsContext', {async: true, handler: this._onApiSetOptionsContext.bind(this)}], + ['hide', {async: false, handler: this._onApiHide.bind(this)}], + ['isVisible', {async: true, handler: this._onApiIsVisibleAsync.bind(this)}], + ['setVisibleOverride', {async: true, handler: this._onApiSetVisibleOverride.bind(this)}], + ['containsPoint', {async: true, handler: this._onApiContainsPoint.bind(this)}], + ['showContent', {async: true, handler: this._onApiShowContent.bind(this)}], + ['setCustomCss', {async: false, handler: this._onApiSetCustomCss.bind(this)}], + ['clearAutoPlayTimer', {async: false, handler: this._onApiClearAutoPlayTimer.bind(this)}], + ['setContentScale', {async: false, handler: this._onApiSetContentScale.bind(this)}], + ['updateTheme', {async: false, handler: this._onApiUpdateTheme.bind(this)}], + ['setCustomOuterCss', {async: false, handler: this._onApiSetCustomOuterCss.bind(this)}], + ['setChildrenSupported', {async: false, handler: this._onApiSetChildrenSupported.bind(this)}] ]); } @@ -82,7 +85,11 @@ class PopupFactory { } const popup = new Popup(id, depth, this._frameId, ownerFrameId); if (parent !== null) { - popup.setParent(parent); + if (parent.child !== null) { + throw new Error('Parent popup already has a child'); + } + popup.parent = parent; + parent.child = popup; } this._popups.set(id, popup); popup.prepare(); @@ -151,6 +158,21 @@ class PopupFactory { return popup.setContentScale(scale); } + _onApiUpdateTheme({id}) { + const popup = this._getPopup(id); + return popup.updateTheme(); + } + + _onApiSetCustomOuterCss({id, css, useWebExtensionApi}) { + const popup = this._getPopup(id); + return popup.setCustomOuterCss(css, useWebExtensionApi); + } + + _onApiSetChildrenSupported({id, value}) { + const popup = this._getPopup(id); + return popup.setChildrenSupported(value); + } + // Private functions _getPopup(id) { @@ -167,8 +189,9 @@ class PopupFactory { } _convertPopupPointToRootPagePoint(popup, x, y) { - if (popup.parent !== null) { - const popupRect = popup.parent.getFrameRect(); + const parent = popup.parent; + if (parent !== null) { + const popupRect = parent.getFrameRect(); x += popupRect.x; y += popupRect.y; } @@ -176,6 +199,7 @@ class PopupFactory { } _popupCanShow(popup) { - return popup.parent === null || popup.parent.isVisibleSync(); + const parent = popup.parent; + return parent === null || parent.isVisibleSync(); } } diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index b4438f80..28f6b276 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -45,10 +45,30 @@ class PopupProxy extends EventDispatcher { return null; } + set parent(value) { + throw new Error('Not supported on PopupProxy'); + } + + get child() { + return null; + } + + set child(value) { + throw new Error('Not supported on PopupProxy'); + } + get depth() { return this._depth; } + get frameContentWindow() { + return null; + } + + get container() { + return null; + } + // Public functions async prepare() { @@ -56,10 +76,6 @@ class PopupProxy extends EventDispatcher { this._id = id; } - isProxy() { - return true; - } - setOptionsContext(optionsContext, source) { return this._invokeSafe('setOptionsContext', {id: this._id, optionsContext, source}); } @@ -109,6 +125,26 @@ class PopupProxy extends EventDispatcher { return this._invokeSafe('setContentScale', {id: this._id, scale}); } + isVisibleSync() { + throw new Error('Not supported on PopupProxy'); + } + + updateTheme() { + return this._invokeSafe('updateTheme', {id: this._id}); + } + + async setCustomOuterCss(css, useWebExtensionApi) { + return this._invokeSafe('updateTheme', {id: this._id, css, useWebExtensionApi}); + } + + setChildrenSupported(value) { + return this._invokeSafe('updateTheme', {id: this._id, value}); + } + + getFrameRect() { + return new DOMRect(0, 0, 0, 0); + } + // Private _invoke(action, params={}) { diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 8ea1afd0..bdffd424 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -64,16 +64,28 @@ class Popup { return this._parent; } + set parent(value) { + this._parent = value; + } + get child() { return this._child; } + set child(value) { + this._child = value; + } + get depth() { return this._depth; } - get frameId() { - return this._frameId; + get frameContentWindow() { + return this._frame.contentWindow; + } + + get container() { + return this._container; } // Public functions @@ -86,10 +98,6 @@ class Popup { yomichan.on('extensionUnloaded', this._onExtensionUnloaded.bind(this)); } - isProxy() { - return false; - } - async setOptionsContext(optionsContext, source) { this._optionsContext = optionsContext; this._previousOptionsContextSource = source; @@ -163,26 +171,6 @@ class Popup { this._invokeSafe('setContentScale', {scale}); } - // Popup-only public functions - - setParent(parent) { - if (parent === null) { - throw new Error('Cannot set popup parent to null'); - } - if (this._parent !== null) { - throw new Error('Popup already has a parent'); - } - parent.setChild(this); - this._parent = parent; - } - - setChild(popup) { - if (this._child !== null) { - throw new Error('Popup already has a child'); - } - this._child = popup; - } - isVisibleSync() { return (this._visibleOverride !== null ? this._visibleOverride : this._visible); } @@ -205,18 +193,10 @@ class Popup { this._childrenSupported = value; } - getFrame() { - return this._frame; - } - getFrameRect() { return this._frame.getBoundingClientRect(); } - getContainer() { - return this._container; - } - // Private functions _inject() { @@ -418,7 +398,7 @@ class Popup { _focusParent() { if (this._parent !== null) { // Chrome doesn't like focusing iframe without contentWindow. - const contentWindow = this._parent.getFrame().contentWindow; + const contentWindow = this._parent.frameContentWindow; if (contentWindow !== null) { contentWindow.focus(); }