Skip to content

Commit

Permalink
Add special logic to get clipboard API to work on Safari
Browse files Browse the repository at this point in the history
  • Loading branch information
juanjoDiaz committed Dec 11, 2022
1 parent 9ac0e75 commit 02c8427
Showing 1 changed file with 49 additions and 9 deletions.
58 changes: 49 additions & 9 deletions core/clipboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,24 @@
* Licensed under MPL 2.0 or any later version (see LICENSE.txt)
*/

import * as Log from "./util/logging.js";
import { isSafari } from "./util/browser.js";

export default class Clipboard {
constructor(target) {
this._target = target;

// Safari only allows interacting with the clipboard during a user interaction
// So we keep data in a fake clipboard and then sync it
this.isSafari = isSafari();
if (this.isSafari) {
this.fakeClipboard = [];
}

this._eventHandlers = {
'copy': this._handleCopy.bind(this),
'focus': this._handleFocus.bind(this)
'focus': this._handleFocus.bind(this),
'syncFromFakeClipboard': this._syncFromFakeClipboard.bind(this)
};

// ===== EVENT HANDLERS =====
Expand All @@ -32,14 +43,18 @@ export default class Clipboard {

if (navigator.clipboard.writeText) {
try {
if (this.isSafari) {
this.fakeClipboard.push(e.clipboardData.getData('text/plain'));
return;
}
await navigator.clipboard.writeText(e.clipboardData.getData('text/plain'));
} catch (e) {
/* Do nothing */
} catch (err) {
Log.Warn(`Couldn't write to clipboard. ${err.message}`);
}
}
}

async _handleFocus() {
async _handleFocus(e) {
try {
if (navigator.permissions && navigator.permissions.query) {
const permission = await navigator.permissions.query({ name: "clipboard-read", allowWithoutGesture: false });
Expand All @@ -53,9 +68,20 @@ export default class Clipboard {
try {
const data = await navigator.clipboard.readText();
this.onpaste(data);
} catch (e) {
/* Do nothing */
return;
} catch (err) {
Log.Warn(`Couldn't read from clipboard. ${err.message}`);
}
}
}

async _syncFromFakeClipboard() {
if (navigator.clipboard.writeText) {
while (this.fakeClipboard.length) {
try {
await navigator.clipboard.writeText(this.fakeClipboard.shift());
} catch (err) {
Log.Warn(`Couldn't write to clipboard. ${err.message}`);
}
}
}
}
Expand All @@ -65,13 +91,27 @@ export default class Clipboard {
grab() {
if (!Clipboard.isSupported) return;
this._target.addEventListener('copy', this._eventHandlers.copy);
this._target.addEventListener('focus', this._eventHandlers.focus);
if (this.isSafari) {
this._target.addEventListener('pointerdown', this._eventHandlers.focus);
// For some reason pointerup doen´t trigger on safari
this._target.addEventListener('mouseup', this._eventHandlers._syncFromFakeClipboard);
this._target.addEventListener('keyup', this._eventHandlers._syncFromFakeClipboard);
} else {
this._target.addEventListener('focus', this._eventHandlers.focus);
}
}

ungrab() {
if (!Clipboard.isSupported) return;
this._target.removeEventListener('copy', this._eventHandlers.copy);
this._target.removeEventListener('focus', this._eventHandlers.focus);
if (this.isSafari) {
this._target.removeEventListener('pointerdown', this._eventHandlers.focus);
// For some reason pointerup doen´t trigger on safari
this._target.removeEventListener('mouseup', this._eventHandlers._syncFromFakeClipboard);
this._target.removeEventListener('keyup', this._eventHandlers._syncFromFakeClipboard);
} else {
this._target.removeEventListener('focus', this._eventHandlers.focus);
}
}
}

Expand Down

0 comments on commit 02c8427

Please sign in to comment.