DEV: Make clipboardCopy util available for import (#15874)
We need this in other places, this commit moves clipboardCopy to the utilities.js lib. Had to remove use of Promise as well because lib/utilities cannot import it, otherwise it will cause a mini racer error.
This commit is contained in:
parent
7850ee318f
commit
c1ad9c3276
|
@ -5,6 +5,7 @@ import Permalink from "admin/models/permalink";
|
||||||
import bootbox from "bootbox";
|
import bootbox from "bootbox";
|
||||||
import discourseDebounce from "discourse-common/lib/debounce";
|
import discourseDebounce from "discourse-common/lib/debounce";
|
||||||
import { observes } from "discourse-common/utils/decorators";
|
import { observes } from "discourse-common/utils/decorators";
|
||||||
|
import { clipboardCopy } from "discourse/lib/utilities";
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
loading: false,
|
loading: false,
|
||||||
|
@ -29,12 +30,7 @@ export default Controller.extend({
|
||||||
|
|
||||||
copyUrl(pl) {
|
copyUrl(pl) {
|
||||||
let linkElement = document.querySelector(`#admin-permalink-${pl.id}`);
|
let linkElement = document.querySelector(`#admin-permalink-${pl.id}`);
|
||||||
let textArea = document.createElement("textarea");
|
clipboardCopy(linkElement.textContent);
|
||||||
textArea.value = linkElement.textContent;
|
|
||||||
document.body.appendChild(textArea);
|
|
||||||
textArea.select();
|
|
||||||
document.execCommand("Copy");
|
|
||||||
textArea.remove();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy(record) {
|
destroy(record) {
|
||||||
|
|
|
@ -1,61 +1,10 @@
|
||||||
import { cancel, later } from "@ember/runloop";
|
import { cancel, later } from "@ember/runloop";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { Promise } from "rsvp";
|
|
||||||
import { guidFor } from "@ember/object/internals";
|
import { guidFor } from "@ember/object/internals";
|
||||||
|
import { clipboardCopy } from "discourse/lib/utilities";
|
||||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||||
|
|
||||||
// http://github.com/feross/clipboard-copy
|
|
||||||
function clipboardCopy(text) {
|
|
||||||
// Use the Async Clipboard API when available.
|
|
||||||
// Requires a secure browsing context (i.e. HTTPS)
|
|
||||||
if (navigator.clipboard) {
|
|
||||||
return navigator.clipboard.writeText(text).catch(function (err) {
|
|
||||||
throw err !== undefined
|
|
||||||
? err
|
|
||||||
: new DOMException("The request is not allowed", "NotAllowedError");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...Otherwise, use document.execCommand() fallback
|
|
||||||
|
|
||||||
// Put the text to copy into a <span>
|
|
||||||
const span = document.createElement("span");
|
|
||||||
span.textContent = text;
|
|
||||||
|
|
||||||
// Preserve consecutive spaces and newlines
|
|
||||||
span.style.whiteSpace = "pre";
|
|
||||||
|
|
||||||
// Add the <span> to the page
|
|
||||||
document.body.appendChild(span);
|
|
||||||
|
|
||||||
// Make a selection object representing the range of text selected by the user
|
|
||||||
const selection = window.getSelection();
|
|
||||||
const range = window.document.createRange();
|
|
||||||
selection.removeAllRanges();
|
|
||||||
range.selectNode(span);
|
|
||||||
selection.addRange(range);
|
|
||||||
|
|
||||||
// Copy text to the clipboard
|
|
||||||
let success = false;
|
|
||||||
try {
|
|
||||||
success = window.document.execCommand("copy");
|
|
||||||
} catch (err) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log("error", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
selection.removeAllRanges();
|
|
||||||
window.document.body.removeChild(span);
|
|
||||||
|
|
||||||
return success
|
|
||||||
? Promise.resolve()
|
|
||||||
: Promise.reject(
|
|
||||||
new DOMException("The request is not allowed", "NotAllowedError")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let _copyCodeblocksClickHandlers = {};
|
let _copyCodeblocksClickHandlers = {};
|
||||||
let _fadeCopyCodeblocksRunners = {};
|
let _fadeCopyCodeblocksRunners = {};
|
||||||
|
|
||||||
|
@ -79,6 +28,25 @@ export default {
|
||||||
_fadeCopyCodeblocksRunners = {};
|
_fadeCopyCodeblocksRunners = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _copyComplete(button) {
|
||||||
|
button.classList.add("copied");
|
||||||
|
const state = button.innerHTML;
|
||||||
|
button.innerHTML = I18n.t("copy_codeblock.copied");
|
||||||
|
|
||||||
|
const commandId = guidFor(button);
|
||||||
|
|
||||||
|
if (_fadeCopyCodeblocksRunners[commandId]) {
|
||||||
|
cancel(_fadeCopyCodeblocksRunners[commandId]);
|
||||||
|
delete _fadeCopyCodeblocksRunners[commandId];
|
||||||
|
}
|
||||||
|
|
||||||
|
_fadeCopyCodeblocksRunners[commandId] = later(() => {
|
||||||
|
button.classList.remove("copied");
|
||||||
|
button.innerHTML = state;
|
||||||
|
delete _fadeCopyCodeblocksRunners[commandId];
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
function _handleClick(event) {
|
function _handleClick(event) {
|
||||||
if (!event.target.classList.contains("copy-cmd")) {
|
if (!event.target.classList.contains("copy-cmd")) {
|
||||||
return;
|
return;
|
||||||
|
@ -96,24 +64,14 @@ export default {
|
||||||
)
|
)
|
||||||
.trim();
|
.trim();
|
||||||
|
|
||||||
clipboardCopy(text).then(() => {
|
const result = clipboardCopy(text);
|
||||||
button.classList.add("copied");
|
if (result.then) {
|
||||||
const state = button.innerHTML;
|
result.then(() => {
|
||||||
button.innerHTML = I18n.t("copy_codeblock.copied");
|
_copyComplete(button);
|
||||||
|
});
|
||||||
const commandId = guidFor(button);
|
} else if (result) {
|
||||||
|
_copyComplete(button);
|
||||||
if (_fadeCopyCodeblocksRunners[commandId]) {
|
}
|
||||||
cancel(_fadeCopyCodeblocksRunners[commandId]);
|
|
||||||
delete _fadeCopyCodeblocksRunners[commandId];
|
|
||||||
}
|
|
||||||
|
|
||||||
_fadeCopyCodeblocksRunners[commandId] = later(() => {
|
|
||||||
button.classList.remove("copied");
|
|
||||||
button.innerHTML = state;
|
|
||||||
delete _fadeCopyCodeblocksRunners[commandId];
|
|
||||||
}, 3000);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -503,5 +503,52 @@ export function translateModKey(string) {
|
||||||
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// http://github.com/feross/clipboard-copy
|
||||||
|
export function clipboardCopy(text) {
|
||||||
|
// Use the Async Clipboard API when available.
|
||||||
|
// Requires a secure browsing context (i.e. HTTPS)
|
||||||
|
if (navigator.clipboard) {
|
||||||
|
return navigator.clipboard.writeText(text).catch(function (err) {
|
||||||
|
throw err !== undefined
|
||||||
|
? err
|
||||||
|
: new DOMException("The request is not allowed", "NotAllowedError");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...Otherwise, use document.execCommand() fallback
|
||||||
|
|
||||||
|
// Put the text to copy into a <span>
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.textContent = text;
|
||||||
|
|
||||||
|
// Preserve consecutive spaces and newlines
|
||||||
|
span.style.whiteSpace = "pre";
|
||||||
|
|
||||||
|
// Add the <span> to the page
|
||||||
|
document.body.appendChild(span);
|
||||||
|
|
||||||
|
// Make a selection object representing the range of text selected by the user
|
||||||
|
const selection = window.getSelection();
|
||||||
|
const range = window.document.createRange();
|
||||||
|
selection.removeAllRanges();
|
||||||
|
range.selectNode(span);
|
||||||
|
selection.addRange(range);
|
||||||
|
|
||||||
|
// Copy text to the clipboard
|
||||||
|
let success = false;
|
||||||
|
try {
|
||||||
|
success = window.document.execCommand("copy");
|
||||||
|
} catch (err) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log("error", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
selection.removeAllRanges();
|
||||||
|
window.document.body.removeChild(span);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
// This prevents a mini racer crash
|
// This prevents a mini racer crash
|
||||||
export default {};
|
export default {};
|
||||||
|
|
Loading…
Reference in New Issue