summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/fg/js/float.js44
-rw-r--r--ext/fg/js/frontend.js6
-rw-r--r--ext/mixed/js/display.js12
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; }