From e51fd8ea71b361ef439728ba6985cbc30c057cd0 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 23 Dec 2019 16:13:41 -0500 Subject: Add _isInjectedAndLoaded property --- ext/fg/js/popup.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ext/fg/js/popup.js') diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 7a0c6133..9b3e3944 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -28,6 +28,7 @@ class Popup { this._childrenSupported = true; this._injectPromise = null; this._isInjected = false; + this._isInjectedAndLoaded = false; this._visible = false; this._visibleOverride = null; this._options = null; @@ -114,7 +115,7 @@ class Popup { } clearAutoPlayTimer() { - if (this._isInjected) { + if (this._isInjectedAndLoaded) { this._invokeApi('clearAutoPlayTimer'); } } @@ -215,6 +216,7 @@ 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', { options: this._options, popupInfo: { @@ -307,6 +309,9 @@ class Popup { } _invokeApi(action, params={}) { + if (!this._isInjectedAndLoaded) { + throw new Error('Frame not loaded'); + } this._container.contentWindow.postMessage({action, params}, '*'); } -- cgit v1.2.3 From 22afab2f47bcc1e5e9ac0db35d2f1b168becf76e Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 23 Dec 2019 16:52:05 -0500 Subject: Remove _isInitialized --- ext/fg/js/popup.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'ext/fg/js/popup.js') diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 9b3e3944..12a5c1c2 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -104,7 +104,7 @@ class Popup { } async showContent(elementRect, writingMode, type=null, details=null) { - if (!this._isInitialized()) { return; } + if (this._options === null) { throw new Error('Options not assigned'); } await this._show(elementRect, writingMode); if (type === null) { return; } this._invokeApi('setContent', {type, details}); @@ -236,10 +236,6 @@ class Popup { }); } - _isInitialized() { - return this._options !== null; - } - async _show(elementRect, writingMode) { await this._inject(); -- cgit v1.2.3 From e740965d4f39a34eecf8a211f22eddf56d185fed Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 23 Dec 2019 17:12:09 -0500 Subject: Scale popup based on current page zoom factor --- ext/fg/js/float.js | 11 +++++++++-- ext/fg/js/frontend.js | 20 ++++++++++++++++++++ ext/fg/js/popup-proxy-host.js | 8 +++++++- ext/fg/js/popup-proxy.js | 5 +++++ ext/fg/js/popup.js | 29 ++++++++++++++++++++--------- 5 files changed, 61 insertions(+), 12 deletions(-) (limited to 'ext/fg/js/popup.js') diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index c550579d..8d61d8f6 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -89,7 +89,11 @@ class DisplayFloat extends Display { } } - async initialize(options, popupInfo, url, childrenSupported) { + setContentScale(scale) { + document.body.style.fontSize = `${scale}em`; + } + + async initialize(options, popupInfo, url, childrenSupported, scale) { await super.initialize(options); const {id, depth, parentFrameId} = popupInfo; @@ -99,6 +103,8 @@ class DisplayFloat extends Display { if (childrenSupported) { popupNestedInitialize(id, depth, parentFrameId, url); } + + this.setContentScale(scale); } } @@ -116,7 +122,8 @@ DisplayFloat._messageHandlers = new Map([ ['setContent', (self, {type, details}) => self.setContent(type, details)], ['clearAutoPlayTimer', (self) => self.clearAutoPlayTimer()], ['setCustomCss', (self, {css}) => self.setCustomCss(css)], - ['initialize', (self, {options, popupInfo, url, childrenSupported}) => self.initialize(options, popupInfo, url, childrenSupported)] + ['initialize', (self, {options, popupInfo, url, childrenSupported, scale}) => self.initialize(options, popupInfo, url, childrenSupported, scale)], + ['setContentScale', (self, {scale}) => self.setContentScale(scale)] ]); DisplayFloat.instance = new DisplayFloat(); diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 85f1f373..52e3a5bc 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -34,6 +34,8 @@ class Frontend extends TextScanner { url: popup.url }; + this._pageZoomFactor = 1.0; + this._contentScale = 1.0; this._orphaned = true; this._lastShowPromise = Promise.resolve(); } @@ -41,11 +43,14 @@ class Frontend extends TextScanner { async prepare() { try { await this.updateOptions(); + const {zoomFactor} = await apiGetZoom(); + this.onZoomChanged({newZoomFactor: zoomFactor}); window.addEventListener('resize', this.onResize.bind(this), false); yomichan.on('orphaned', () => this.onOrphaned()); yomichan.on('optionsUpdate', () => this.updateOptions()); + yomichan.on('zoomChanged', (e) => this.onZoomChanged(e)); chrome.runtime.onMessage.addListener(this.onRuntimeMessage.bind(this)); } catch (e) { this.onError(e); @@ -80,6 +85,11 @@ class Frontend extends TextScanner { this._orphaned = true; } + onZoomChanged({newZoomFactor}) { + this._pageZoomFactor = newZoomFactor; + this._updateContentScale(); + } + getMouseEventListeners() { return [ ...super.getMouseEventListeners(), @@ -90,6 +100,7 @@ class Frontend extends TextScanner { async updateOptions() { this.setOptions(await apiOptionsGet(this.getOptionsContext())); await this.popup.setOptions(this.options); + this._updateContentScale(); } async onSearchSource(textSource, cause) { @@ -183,6 +194,15 @@ class Frontend extends TextScanner { ); return this._lastShowPromise; } + + _updateContentScale() { + const contentScale = 1.0 / this._pageZoomFactor; // TODO : Use options + if (contentScale === this._contentScale) { return; } + + this._contentScale = contentScale; + this.popup.setContentScale(this._contentScale); + this.onResize(); + } } Frontend._windowMessageHandlers = new Map([ diff --git a/ext/fg/js/popup-proxy-host.js b/ext/fg/js/popup-proxy-host.js index c4f0c6ff..427172c6 100644 --- a/ext/fg/js/popup-proxy-host.js +++ b/ext/fg/js/popup-proxy-host.js @@ -41,7 +41,8 @@ class PopupProxyHost { ['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)] + ['clearAutoPlayTimer', ({id}) => this._onApiClearAutoPlayTimer(id)], + ['setContentScale', ({id, scale}) => this._onApiSetContentScale(id, scale)] ])); } @@ -97,6 +98,11 @@ class PopupProxyHost { return popup.clearAutoPlayTimer(); } + async _onApiSetContentScale(id, scale) { + const popup = this._getPopup(id); + return popup.setContentScale(scale); + } + // Private functions _createPopupInternal(parentId, depth) { diff --git a/ext/fg/js/popup-proxy.js b/ext/fg/js/popup-proxy.js index ae0cffad..4cacee53 100644 --- a/ext/fg/js/popup-proxy.js +++ b/ext/fg/js/popup-proxy.js @@ -97,6 +97,11 @@ class PopupProxy { this._invokeHostApi('clearAutoPlayTimer', {id: this._id}); } + async setContentScale(scale) { + const id = await this._getPopupId(); + this._invokeHostApi('setContentScale', {id, scale}); + } + // Private _getPopupId() { diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 12a5c1c2..3c774f54 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -33,6 +33,7 @@ class Popup { this._visibleOverride = null; this._options = null; this._stylesheetInjectedViaApi = false; + this._contentScale = 1.0; this._container = document.createElement('iframe'); this._container.className = 'yomichan-float'; @@ -120,6 +121,13 @@ class Popup { } } + setContentScale(scale) { + this._contentScale = scale; + if (this._isInjectedAndLoaded) { + this._invokeApi('setContentScale', {scale}); + } + } + // Popup-only public functions setParent(parent) { @@ -225,7 +233,8 @@ class Popup { parentFrameId }, url: this.url, - childrenSupported: this._childrenSupported + childrenSupported: this._childrenSupported, + scale: this._contentScale }); resolve(); }); @@ -248,12 +257,14 @@ class Popup { Popup._getPositionForVerticalText ); + const scale = this._contentScale; const [x, y, width, height, below] = getPosition( elementRect, - Math.max(containerRect.width, optionsGeneral.popupWidth), - Math.max(containerRect.height, optionsGeneral.popupHeight), + Math.max(containerRect.width, optionsGeneral.popupWidth * scale), + Math.max(containerRect.height, optionsGeneral.popupHeight * scale), document.body.clientWidth, window.innerHeight, + scale, optionsGeneral, writingMode ); @@ -339,8 +350,8 @@ class Popup { } } - static _getPositionForHorizontalText(elementRect, width, height, maxWidth, maxHeight, optionsGeneral) { - let x = elementRect.left + optionsGeneral.popupHorizontalOffset; + static _getPositionForHorizontalText(elementRect, width, height, maxWidth, maxHeight, offsetScale, optionsGeneral) { + let x = elementRect.left + optionsGeneral.popupHorizontalOffset * offsetScale; const overflowX = Math.max(x + width - maxWidth, 0); if (overflowX > 0) { if (x >= overflowX) { @@ -353,7 +364,7 @@ class Popup { const preferBelow = (optionsGeneral.popupHorizontalTextPosition === 'below'); - const verticalOffset = optionsGeneral.popupVerticalOffset; + const verticalOffset = optionsGeneral.popupVerticalOffset * offsetScale; const [y, h, below] = Popup._limitGeometry( elementRect.top - verticalOffset, elementRect.bottom + verticalOffset, @@ -365,10 +376,10 @@ class Popup { return [x, y, width, h, below]; } - static _getPositionForVerticalText(elementRect, width, height, maxWidth, maxHeight, optionsGeneral, writingMode) { + static _getPositionForVerticalText(elementRect, width, height, maxWidth, maxHeight, offsetScale, optionsGeneral, writingMode) { const preferRight = Popup._isVerticalTextPopupOnRight(optionsGeneral.popupVerticalTextPosition, writingMode); - const horizontalOffset = optionsGeneral.popupHorizontalOffset2; - const verticalOffset = optionsGeneral.popupVerticalOffset2; + const horizontalOffset = optionsGeneral.popupHorizontalOffset2 * offsetScale; + const verticalOffset = optionsGeneral.popupVerticalOffset2 * offsetScale; const [x, w] = Popup._limitGeometry( elementRect.left - horizontalOffset, -- cgit v1.2.3 From 4d85a36091c68237c53136a6f78692eaf3a60a37 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 28 Dec 2019 23:22:29 -0500 Subject: Fix popup size changing when zooming --- ext/fg/js/popup.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'ext/fg/js/popup.js') diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 3c774f54..6c98491b 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -34,6 +34,7 @@ class Popup { this._options = null; this._stylesheetInjectedViaApi = false; this._contentScale = 1.0; + this._containerSizeContentScale = null; this._container = document.createElement('iframe'); this._container.className = 'yomichan-float'; @@ -258,10 +259,12 @@ class Popup { ); const scale = this._contentScale; + const scaleRatio = this._containerSizeContentScale === null ? 1.0 : scale / this._containerSizeContentScale; + this._containerSizeContentScale = scale; const [x, y, width, height, below] = getPosition( elementRect, - Math.max(containerRect.width, optionsGeneral.popupWidth * scale), - Math.max(containerRect.height, optionsGeneral.popupHeight * scale), + Math.max(containerRect.width * scaleRatio, optionsGeneral.popupWidth * scale), + Math.max(containerRect.height * scaleRatio, optionsGeneral.popupHeight * scale), document.body.clientWidth, window.innerHeight, scale, -- cgit v1.2.3 From d59f2022b9582a9a310c8a93eb3b4e0bbab097a5 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 11 Jan 2020 14:21:10 -0500 Subject: Allow viewport to be used for constraining popup position --- ext/fg/js/popup.js | 114 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 39 deletions(-) (limited to 'ext/fg/js/popup.js') diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 6c98491b..710d95cd 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -258,6 +258,7 @@ class Popup { Popup._getPositionForVerticalText ); + const viewport = Popup._getViewport(optionsGeneral.popupScaleRelativeToVisualViewport); const scale = this._contentScale; const scaleRatio = this._containerSizeContentScale === null ? 1.0 : scale / this._containerSizeContentScale; this._containerSizeContentScale = scale; @@ -265,8 +266,7 @@ class Popup { elementRect, Math.max(containerRect.width * scaleRatio, optionsGeneral.popupWidth * scale), Math.max(containerRect.height * scaleRatio, optionsGeneral.popupHeight * scale), - document.body.clientWidth, - window.innerHeight, + viewport, scale, optionsGeneral, writingMode @@ -353,49 +353,49 @@ class Popup { } } - static _getPositionForHorizontalText(elementRect, width, height, maxWidth, maxHeight, offsetScale, optionsGeneral) { - let x = elementRect.left + optionsGeneral.popupHorizontalOffset * offsetScale; - const overflowX = Math.max(x + width - maxWidth, 0); - if (overflowX > 0) { - if (x >= overflowX) { - x -= overflowX; - } else { - width = maxWidth; - x = 0; - } - } - + static _getPositionForHorizontalText(elementRect, width, height, viewport, offsetScale, optionsGeneral) { const preferBelow = (optionsGeneral.popupHorizontalTextPosition === 'below'); - + const horizontalOffset = optionsGeneral.popupHorizontalOffset * offsetScale; const verticalOffset = optionsGeneral.popupVerticalOffset * offsetScale; - const [y, h, below] = Popup._limitGeometry( + + const [x, w] = Popup._getConstrainedPosition( + elementRect.right - horizontalOffset, + elementRect.left + horizontalOffset, + width, + viewport.left, + viewport.right, + true + ); + const [y, h, below] = Popup._getConstrainedPositionBinary( elementRect.top - verticalOffset, elementRect.bottom + verticalOffset, height, - maxHeight, + viewport.top, + viewport.bottom, preferBelow ); - - return [x, y, width, h, below]; + return [x, y, w, h, below]; } - static _getPositionForVerticalText(elementRect, width, height, maxWidth, maxHeight, offsetScale, optionsGeneral, writingMode) { + static _getPositionForVerticalText(elementRect, width, height, viewport, offsetScale, optionsGeneral, writingMode) { const preferRight = Popup._isVerticalTextPopupOnRight(optionsGeneral.popupVerticalTextPosition, writingMode); const horizontalOffset = optionsGeneral.popupHorizontalOffset2 * offsetScale; const verticalOffset = optionsGeneral.popupVerticalOffset2 * offsetScale; - const [x, w] = Popup._limitGeometry( + const [x, w] = Popup._getConstrainedPositionBinary( elementRect.left - horizontalOffset, elementRect.right + horizontalOffset, width, - maxWidth, + viewport.left, + viewport.right, preferRight ); - const [y, h, below] = Popup._limitGeometry( + const [y, h, below] = Popup._getConstrainedPosition( elementRect.bottom - verticalOffset, elementRect.top + verticalOffset, height, - maxHeight, + viewport.top, + viewport.bottom, true ); return [x, y, w, h, below]; @@ -424,23 +424,36 @@ class Popup { } } - static _limitGeometry(positionBefore, positionAfter, size, limit, preferAfter) { - let after = preferAfter; - let position = 0; - const overflowBefore = Math.max(0, size - positionBefore); - const overflowAfter = Math.max(0, positionAfter + size - limit); + static _getConstrainedPosition(positionBefore, positionAfter, size, minLimit, maxLimit, after) { + size = Math.min(size, maxLimit - minLimit); + + let position; + if (after) { + position = Math.max(minLimit, positionAfter); + position = position - Math.max(0, (position + size) - maxLimit); + } else { + position = Math.min(maxLimit, positionBefore) - size; + position = position + Math.max(0, minLimit - position); + } + + return [position, size, after]; + } + + static _getConstrainedPositionBinary(positionBefore, positionAfter, size, minLimit, maxLimit, after) { + const overflowBefore = minLimit - (positionBefore - size); + const overflowAfter = (positionAfter + size) - maxLimit; + if (overflowAfter > 0 || overflowBefore > 0) { - if (overflowAfter < overflowBefore) { - size = Math.max(0, size - overflowAfter); - position = positionAfter; - after = true; - } else { - size = Math.max(0, size - overflowBefore); - position = Math.max(0, positionBefore - size); - after = false; - } + after = (overflowAfter < overflowBefore); + } + + let position; + if (after) { + size -= Math.max(0, overflowAfter); + position = Math.max(minLimit, positionAfter); } else { - position = preferAfter ? positionAfter : positionBefore - size; + size -= Math.max(0, overflowBefore); + position = Math.min(maxLimit, positionBefore) - size; } return [position, size, after]; @@ -479,6 +492,29 @@ class Popup { // NOP } } + + static _getViewport(useVisualViewport) { + if (useVisualViewport) { + const visualViewport = window.visualViewport; + if (visualViewport !== null && typeof visualViewport === 'object') { + const left = visualViewport.offsetLeft; + const top = visualViewport.offsetTop; + return { + left, + top, + right: left + visualViewport.width, + bottom: top + visualViewport.height + }; + } + } + + return { + left: 0, + top: 0, + right: document.body.clientWidth, + bottom: window.innerHeight + }; + } } Popup.outerStylesheet = null; -- cgit v1.2.3 From 74d9b0e857bc8fc086a6ffaf4178c2372779ecd3 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 11 Jan 2020 14:45:40 -0500 Subject: Update full-width popup to stay on screen --- ext/fg/css/client.css | 7 ------- ext/fg/js/popup.js | 12 ++++++++++-- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'ext/fg/js/popup.js') diff --git a/ext/fg/css/client.css b/ext/fg/css/client.css index b9c59da7..5720d8ac 100644 --- a/ext/fg/css/client.css +++ b/ext/fg/css/client.css @@ -39,21 +39,14 @@ iframe.yomichan-float[data-yomichan-theme=auto][data-yomichan-site-color=dark] { iframe.yomichan-float.yomichan-float-full-width { border-left: none; border-right: none; - left: 0 !important; - right: 0 !important; - width: 100% !important; box-sizing: border-box; resize: none; } iframe.yomichan-float.yomichan-float-full-width:not(.yomichan-float-above) { border-bottom: none; - top: auto !important; - bottom: 0 !important; } iframe.yomichan-float.yomichan-float-full-width.yomichan-float-above { border-top: none; - top: 0 !important; - bottom: auto !important; } diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index 710d95cd..ef1334bd 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -262,7 +262,7 @@ class Popup { const scale = this._contentScale; const scaleRatio = this._containerSizeContentScale === null ? 1.0 : scale / this._containerSizeContentScale; this._containerSizeContentScale = scale; - const [x, y, width, height, below] = getPosition( + let [x, y, width, height, below] = getPosition( elementRect, Math.max(containerRect.width * scaleRatio, optionsGeneral.popupWidth * scale), Math.max(containerRect.height * scaleRatio, optionsGeneral.popupHeight * scale), @@ -272,8 +272,16 @@ class Popup { writingMode ); - container.classList.toggle('yomichan-float-full-width', optionsGeneral.popupDisplayMode === 'full-width'); + const fullWidth = (optionsGeneral.popupDisplayMode === 'full-width'); + container.classList.toggle('yomichan-float-full-width', fullWidth); container.classList.toggle('yomichan-float-above', !below); + + if (optionsGeneral.popupDisplayMode === 'full-width') { + x = viewport.left; + y = below ? viewport.bottom - height : viewport.top; + width = viewport.right - viewport.left; + } + container.style.left = `${x}px`; container.style.top = `${y}px`; container.style.width = `${width}px`; -- cgit v1.2.3 From 04727a8cd7dc29a02595690389979ec1070bbded Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 18 Jan 2020 13:13:12 -0500 Subject: Fix viewport issues when popupScaleRelativeToVisualViewport is disabled --- ext/fg/js/popup.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'ext/fg/js/popup.js') diff --git a/ext/fg/js/popup.js b/ext/fg/js/popup.js index ef1334bd..e7dae93e 100644 --- a/ext/fg/js/popup.js +++ b/ext/fg/js/popup.js @@ -502,16 +502,26 @@ class Popup { } static _getViewport(useVisualViewport) { - if (useVisualViewport) { - const visualViewport = window.visualViewport; - if (visualViewport !== null && typeof visualViewport === 'object') { - const left = visualViewport.offsetLeft; - const top = visualViewport.offsetTop; + const visualViewport = window.visualViewport; + if (visualViewport !== null && typeof visualViewport === 'object') { + const left = visualViewport.offsetLeft; + const top = visualViewport.offsetTop; + const width = visualViewport.width; + const height = visualViewport.height; + if (useVisualViewport) { return { left, top, - right: left + visualViewport.width, - bottom: top + visualViewport.height + right: left + width, + bottom: top + height + }; + } else { + const scale = visualViewport.scale; + return { + left: 0, + top: 0, + right: Math.max(left + width, width * scale), + bottom: Math.max(top + height, height * scale) }; } } -- cgit v1.2.3