diff options
Diffstat (limited to 'ext/fg/js/popup.js')
-rw-r--r-- | ext/fg/js/popup.js | 109 |
1 files changed, 71 insertions, 38 deletions
diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 0b142dda..de05f9f5 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -28,8 +28,6 @@ class Popup { this._child = null; this._childrenSupported = true; this._injectPromise = null; - this._isInjected = false; - this._isInjectedAndLoaded = false; this._visible = false; this._visibleOverride = null; this._options = null; @@ -41,19 +39,28 @@ class Popup { this._container.className = 'yomichan-float'; this._container.addEventListener('mousedown', (e) => e.stopPropagation()); this._container.addEventListener('scroll', (e) => e.stopPropagation()); - this._container.setAttribute('src', chrome.runtime.getURL('/fg/float.html')); this._container.style.width = '0px'; this._container.style.height = '0px'; + this._fullscreenEventListeners = new EventListenerCollection(); + this._updateVisibility(); } // Public properties + get id() { + return this._id; + } + get parent() { return this._parent; } + get child() { + return this._child; + } + get depth() { return this._depth; } @@ -118,16 +125,12 @@ class Popup { } clearAutoPlayTimer() { - if (this._isInjectedAndLoaded) { - this._invokeApi('clearAutoPlayTimer'); - } + this._invokeApi('clearAutoPlayTimer'); } setContentScale(scale) { this._contentScale = scale; - if (this._isInjectedAndLoaded) { - this._invokeApi('setContentScale', {scale}); - } + this._invokeApi('setContentScale', {scale}); } // Popup-only public functions @@ -147,7 +150,7 @@ class Popup { } isVisibleSync() { - return this._isInjected && (this._visibleOverride !== null ? this._visibleOverride : this._visible); + return (this._visibleOverride !== null ? this._visibleOverride : this._visible); } updateTheme() { @@ -226,8 +229,10 @@ class Popup { return new Promise((resolve) => { const parentFrameId = (typeof this._frameId === 'number' ? this._frameId : null); this._container.addEventListener('load', () => { - this._isInjectedAndLoaded = true; - this._invokeApi('initialize', { + const uniqueId = yomichan.generateId(32); + Popup._listenForDisplayPrepareCompleted(uniqueId, resolve); + + this._invokeApi('prepare', { options: this._options, popupInfo: { id: this._id, @@ -236,17 +241,47 @@ class Popup { }, url: this.url, childrenSupported: this._childrenSupported, - scale: this._contentScale + scale: this._contentScale, + uniqueId }); - resolve(); }); - this._observeFullscreen(); + this._observeFullscreen(true); this._onFullscreenChanged(); this.setCustomOuterCss(this._options.general.customPopupOuterCss, false); - this._isInjected = true; + this._container.setAttribute('src', chrome.runtime.getURL('/fg/float.html')); }); } + _observeFullscreen(observe) { + if (!observe) { + this._fullscreenEventListeners.removeAllEventListeners(); + return; + } + + if (this._fullscreenEventListeners.size > 0) { + // Already observing + return; + } + + const fullscreenEvents = [ + 'fullscreenchange', + 'MSFullscreenChange', + 'mozfullscreenchange', + 'webkitfullscreenchange' + ]; + const onFullscreenChanged = () => this._onFullscreenChanged(); + for (const eventName of fullscreenEvents) { + this._fullscreenEventListeners.addEventListener(document, eventName, onFullscreenChanged, false); + } + } + + _onFullscreenChanged() { + const parent = (Popup._getFullscreenElement() || document.body || null); + if (parent !== null && this._container.parentNode !== parent) { + parent.appendChild(this._container); + } + } + async _show(elementRect, writingMode) { await this._inject(); @@ -328,38 +363,36 @@ class Popup { } _invokeApi(action, params={}) { - if (!this._isInjectedAndLoaded) { - throw new Error('Frame not loaded'); - } - this._container.contentWindow.postMessage({action, params}, '*'); - } - - _observeFullscreen() { - const fullscreenEvents = [ - 'fullscreenchange', - 'MSFullscreenChange', - 'mozfullscreenchange', - 'webkitfullscreenchange' - ]; - for (const eventName of fullscreenEvents) { - document.addEventListener(eventName, () => this._onFullscreenChanged(), false); + if (this._container.contentWindow) { + this._container.contentWindow.postMessage({action, params}, '*'); } } - _getFullscreenElement() { + static _getFullscreenElement() { return ( document.fullscreenElement || document.msFullscreenElement || document.mozFullScreenElement || - document.webkitFullscreenElement + document.webkitFullscreenElement || + null ); } - _onFullscreenChanged() { - const parent = (this._getFullscreenElement() || document.body || null); - if (parent !== null && this._container.parentNode !== parent) { - parent.appendChild(this._container); - } + static _listenForDisplayPrepareCompleted(uniqueId, resolve) { + const runtimeMessageCallback = ({action, params}, sender, callback) => { + if ( + action === 'popupPrepareCompleted' && + typeof params === 'object' && + params !== null && + params.uniqueId === uniqueId + ) { + chrome.runtime.onMessage.removeListener(runtimeMessageCallback); + callback(); + resolve(); + return false; + } + }; + chrome.runtime.onMessage.addListener(runtimeMessageCallback); } static _getPositionForHorizontalText(elementRect, width, height, viewport, offsetScale, optionsGeneral) { |