diff options
Diffstat (limited to 'ext/fg/js/frontend.js')
-rw-r--r-- | ext/fg/js/frontend.js | 94 |
1 files changed, 74 insertions, 20 deletions
diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 034d9075..2286bf19 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,23 +43,30 @@ class Frontend extends TextScanner { async prepare() { try { await this.updateOptions(); + const {zoomFactor} = await apiGetZoom(); + this._pageZoomFactor = zoomFactor; + + window.addEventListener('resize', this.onResize.bind(this), false); + + const visualViewport = window.visualViewport; + if (visualViewport !== null && typeof visualViewport === 'object') { + window.visualViewport.addEventListener('scroll', this.onVisualViewportScroll.bind(this)); + window.visualViewport.addEventListener('resize', this.onVisualViewportResize.bind(this)); + } 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)); + + this._updateContentScale(); } catch (e) { this.onError(e); } } - async onResize() { - const textSource = this.textSourceCurrent; - if (textSource !== null && await this.popup.isVisible()) { - this._lastShowPromise = this.popup.showContent( - textSource.getRect(), - textSource.getWritingMode() - ); - } + onResize() { + this._updatePopupPosition(); } onWindowMessage(e) { @@ -81,18 +90,30 @@ class Frontend extends TextScanner { this._orphaned = true; } + onZoomChanged({newZoomFactor}) { + this._pageZoomFactor = newZoomFactor; + this._updateContentScale(); + } + + onVisualViewportScroll() { + this._updatePopupPosition(); + } + + onVisualViewportResize() { + this._updateContentScale(); + } + getMouseEventListeners() { return [ ...super.getMouseEventListeners(), - [window, 'message', this.onWindowMessage.bind(this)], - [window, 'resize', this.onResize.bind(this)] + [window, 'message', this.onWindowMessage.bind(this)] ]; } async updateOptions() { - this.options = await apiOptionsGet(this.getOptionsContext()); + this.setOptions(await apiOptionsGet(this.getOptionsContext())); await this.popup.setOptions(this.options); - this.setEnabled(this.options.general.enable); + this._updateContentScale(); } async onSearchSource(textSource, cause) { @@ -112,11 +133,7 @@ class Frontend extends TextScanner { } catch (e) { if (this._orphaned) { if (textSource !== null && this.options.scanning.modifier !== 'none') { - this._lastShowPromise = this.popup.showContent( - textSource.getRect(), - textSource.getWritingMode(), - 'orphaned' - ); + this._showPopupContent(textSource, 'orphaned'); } } else { this.onError(e); @@ -133,9 +150,8 @@ class Frontend extends TextScanner { showContent(textSource, focus, definitions, type) { const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); const url = window.location.href; - this._lastShowPromise = this.popup.showContent( - textSource.getRect(), - textSource.getWritingMode(), + this._showPopupContent( + textSource, type, {definitions, context: {sentence, url, focus, disableHistory: true}} ); @@ -181,6 +197,44 @@ class Frontend extends TextScanner { this.optionsContext.url = this.popup.url; return this.optionsContext; } + + _showPopupContent(textSource, type=null, details=null) { + this._lastShowPromise = this.popup.showContent( + textSource.getRect(), + textSource.getWritingMode(), + type, + details + ); + return this._lastShowPromise; + } + + _updateContentScale() { + const {popupScalingFactor, popupScaleRelativeToPageZoom, popupScaleRelativeToVisualViewport} = this.options.general; + let contentScale = popupScalingFactor; + if (popupScaleRelativeToPageZoom) { + contentScale /= this._pageZoomFactor; + } + if (popupScaleRelativeToVisualViewport) { + contentScale /= Frontend._getVisualViewportScale(); + } + if (contentScale === this._contentScale) { return; } + + this._contentScale = contentScale; + this.popup.setContentScale(this._contentScale); + this._updatePopupPosition(); + } + + async _updatePopupPosition() { + const textSource = this.getCurrentTextSource(); + if (textSource !== null && await this.popup.isVisible()) { + this._showPopupContent(textSource); + } + } + + static _getVisualViewportScale() { + const visualViewport = window.visualViewport; + return visualViewport !== null && typeof visualViewport === 'object' ? visualViewport.scale : 1.0; + } } Frontend._windowMessageHandlers = new Map([ |