From a640e943f770a372f0670297ced82b23aaf10068 Mon Sep 17 00:00:00 2001 From: Oliver Hunt Date: Tue, 6 Jun 2017 00:29:14 +0100 Subject: [PATCH 1/2] Added button that copies code to clipboard Signed-off-by: Oliver Hunt --- src/HtmlUtils.js | 13 ++++++++++ src/components/views/messages/TextualBody.js | 27 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index 4acb314c2f..e597d011b9 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -345,6 +345,7 @@ export function bodyToHtml(content, highlights, opts) { } safeBody = sanitizeHtml(body, sanitizeHtmlParams); safeBody = unicodeToImage(safeBody); + safeBody = addCodeCopyButton(safeBody); } finally { delete sanitizeHtmlParams.textFilter; @@ -363,6 +364,18 @@ export function bodyToHtml(content, highlights, opts) { return ; } +function addCodeCopyButton(safeBody) { + var el = document.createElement("div"); + el.innerHTML = safeBody; + var codeBlocks = Array.from(el.getElementsByTagName("pre")); + codeBlocks.forEach(p => { + var button = document.createElement("span"); + button.className = "mx_EventTile_copyButton"; + p.appendChild(button); + }); + return el.innerHTML; +} + export function emojifyText(text) { return { __html: unicodeToImage(escape(text)), diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 3df09fc444..fe4a66b55f 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -62,6 +62,19 @@ module.exports = React.createClass({ }; }, + copyToClipboard: function(text) { + const textArea = document.createElement("textarea"); + textArea.value = text; + document.body.appendChild(textArea); + textArea.select(); + try { + const successful = document.execCommand('copy'); + } catch (err) { + console.log('Unable to copy'); + } + document.body.removeChild(textArea); + }, + componentDidMount: function() { this._unmounted = false; @@ -80,6 +93,20 @@ module.exports = React.createClass({ } }, 10); } + const buttons = ReactDOM.findDOMNode(this).getElementsByClassName("mx_EventTile_copyButton"); + if (buttons.length > 0) { + // Do this asynchronously: parsing code takes time and we don't + // need to block the DOM update on it. + setTimeout(() => { + if (this._unmounted) return; + for (let i = 0; i < buttons.length; i++) { + buttons[i].onclick = (e) => { + const copyCode = buttons[i].parentNode.getElementsByTagName("code")[0]; + this.copyToClipboard(copyCode.textContent); + }; + } + }, 10); + } } }, From dd6171a39ebced55fd154bd8856bbc126ed111d8 Mon Sep 17 00:00:00 2001 From: Oliver Hunt Date: Tue, 6 Jun 2017 12:29:23 +0100 Subject: [PATCH 2/2] Review changes Signed-off-by: Oliver Hunt --- src/HtmlUtils.js | 6 +++--- src/components/views/messages/TextualBody.js | 17 ++++++----------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index e597d011b9..59717b0459 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -365,11 +365,11 @@ export function bodyToHtml(content, highlights, opts) { } function addCodeCopyButton(safeBody) { - var el = document.createElement("div"); + const el = document.createElement("div"); el.innerHTML = safeBody; - var codeBlocks = Array.from(el.getElementsByTagName("pre")); + const codeBlocks = Array.from(el.getElementsByTagName("pre")); codeBlocks.forEach(p => { - var button = document.createElement("span"); + const button = document.createElement("span"); button.className = "mx_EventTile_copyButton"; p.appendChild(button); }); diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index fe4a66b55f..8265ed5010 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -95,17 +95,12 @@ module.exports = React.createClass({ } const buttons = ReactDOM.findDOMNode(this).getElementsByClassName("mx_EventTile_copyButton"); if (buttons.length > 0) { - // Do this asynchronously: parsing code takes time and we don't - // need to block the DOM update on it. - setTimeout(() => { - if (this._unmounted) return; - for (let i = 0; i < buttons.length; i++) { - buttons[i].onclick = (e) => { - const copyCode = buttons[i].parentNode.getElementsByTagName("code")[0]; - this.copyToClipboard(copyCode.textContent); - }; - } - }, 10); + for (let i = 0; i < buttons.length; i++) { + buttons[i].onclick = (e) => { + const copyCode = buttons[i].parentNode.getElementsByTagName("code")[0]; + this.copyToClipboard(copyCode.textContent); + }; + } } } },