From a640e943f770a372f0670297ced82b23aaf10068 Mon Sep 17 00:00:00 2001 From: Oliver Hunt Date: Tue, 6 Jun 2017 00:29:14 +0100 Subject: [PATCH] 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); + } } },