diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/fg/js/float.js | 44 | ||||
| -rw-r--r-- | ext/fg/js/frontend.js | 6 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 12 | 
3 files changed, 54 insertions, 8 deletions
| diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index 3b752df5..9f58439f 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -29,6 +29,8 @@ class DisplayFloat extends Display {          this._windowMessageHandlers = new Map([              ['extensionUnloaded', {async: false, handler: this._onMessageExtensionUnloaded.bind(this)}]          ]); +        this._browser = null; +        this._copyTextarea = null;          this.registerActions([              ['copyHostSelection', () => this._copySelection()] @@ -43,6 +45,9 @@ class DisplayFloat extends Display {      async prepare() {          await super.prepare(); +        const {browser} = await api.getEnvironmentInfo(); +        this._browser = browser; +          this.registerDirectMessageHandlers([              ['configure',       {async: true,  handler: this._onMessageConfigure.bind(this)}],              ['setContentScale', {async: false, handler: this._onMessageSetContentScale.bind(this)}] @@ -150,10 +155,47 @@ class DisplayFloat extends Display {      _copySelection() {          if (window.getSelection().toString()) { return false; } -        this._invokeOwner('copySelection'); +        this._copyHostSelection();          return true;      } +    async _copyHostSelection() { +        switch (this._browser) { +            case 'firefox': +            case 'firefox-mobile': +                { +                    let text; +                    try { +                        text = await this._invokeOwner('getSelectionText'); +                    } catch (e) { +                        break; +                    } +                    this._copyText(text); +                } +                break; +            default: +                this._invokeOwner('copySelection'); +                break; +        } +    } + +    _copyText(text) { +        const parent = document.body; +        if (parent === null) { return; } + +        let textarea = this._copyTextarea; +        if (textarea === null) { +            textarea = document.createElement('textarea'); +            this._copyTextarea = textarea; +        } + +        textarea.value = text; +        parent.appendChild(textarea); +        textarea.select(); +        document.execCommand('copy'); +        parent.removeChild(textarea); +    } +      _setContentScale(scale) {          const body = document.body;          if (body === null) { return; } diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 82a56f1e..2ee9b4a1 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -115,6 +115,7 @@ class Frontend {              ['getUrl',                  {async: false, handler: this._onApiGetUrl.bind(this)}],              ['closePopup',              {async: false, handler: this._onApiClosePopup.bind(this)}],              ['copySelection',           {async: false, handler: this._onApiCopySelection.bind(this)}], +            ['getSelectionText',        {async: false, handler: this._onApiGetSelectionText.bind(this)}],              ['getPopupInfo',            {async: false, handler: this._onApiGetPopupInfo.bind(this)}],              ['getDocumentInformation',  {async: false, handler: this._onApiGetDocumentInformation.bind(this)}]          ]); @@ -168,9 +169,14 @@ class Frontend {      }      _onApiCopySelection() { +        // This will not work on Firefox if a popup has focus, which is usually the case when this function is called.          document.execCommand('copy');      } +    _onApiGetSelectionText() { +        return document.getSelection().toString(); +    } +      _onApiGetPopupInfo() {          return {              popupId: (this._popup !== null ? this._popup.id : null) diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index c0102379..f79ba303 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -466,7 +466,7 @@ class Display extends EventDispatcher {              this._closePopups();              this._setEventListenersActive(false); -            let asigned = false; +            let assigned = false;              const eventArgs = {type, urlSearchParams, token};              this._historyHasChanged = true;              this._contentType = type; @@ -476,7 +476,7 @@ class Display extends EventDispatcher {                  case 'kanji':                      {                          const isTerms = (type === 'terms'); -                        asigned = await this._setContentTermsOrKanji(token, isTerms, urlSearchParams, eventArgs); +                        assigned = await this._setContentTermsOrKanji(token, isTerms, urlSearchParams, eventArgs);                      }                      break;                  case 'unloaded': @@ -485,14 +485,14 @@ class Display extends EventDispatcher {                          eventArgs.content = content;                          this.trigger('contentUpdating', eventArgs);                          this._setContentExtensionUnloaded(); -                        asigned = true; +                        assigned = true;                      }                      break;              }              const stale = (this._setContentToken !== token);              if (!stale) { -                if (!asigned) { +                if (!assigned) {                      type = 'clear';                      this._contentType = type;                      const {content} = this._history; @@ -910,9 +910,7 @@ class Display extends EventDispatcher {              container.appendChild(entry);          } -        if (typeof focusEntry === 'number') { -            this._focusEntry(focusEntry, false); -        } +        this._focusEntry(typeof focusEntry === 'number' ? focusEntry : 0, false);          if (typeof scrollX === 'number' || typeof scrollY === 'number') {              let {x, y} = this._windowScroll;              if (typeof scrollX === 'number') { x = scrollX; } |