From d8f4512439bc844e5df75050afb67aef0d578f72 Mon Sep 17 00:00:00 2001 From: Sorunome Date: Wed, 22 May 2019 20:41:27 +0200 Subject: [PATCH] add basic spoiler support --- res/css/views/rooms/_EventTile.scss | 27 +++++++++++++++++ src/HtmlUtils.js | 2 +- src/components/views/elements/Spoiler.js | 32 ++++++++++++++++++++ src/components/views/messages/TextualBody.js | 30 ++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/components/views/elements/Spoiler.js diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 72881231f8..dd078d7f30 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -280,6 +280,33 @@ limitations under the License. overflow-y: hidden; } +/* Spoiler stuff */ +.mx_EventTile_spoiler { + cursor: pointer; +} + +.mx_EventTile_spoiler_reason { + color: $event-timestamp-color; + font-size: 11px; +} + +.mx_EventTile_spoiler_content { + background-color: black; +} + +.mx_EventTile_spoiler_content > span { + visibility: hidden; +} + + +.mx_EventTile_spoiler.visible > .mx_EventTile_spoiler_content { + background-color: initial; +} + +.mx_EventTile_spoiler.visible > .mx_EventTile_spoiler_content > span { + visibility: visible; +} + /* End to end encryption stuff */ .mx_EventTile:hover .mx_EventTile_e2eIcon { opacity: 1; diff --git a/src/HtmlUtils.js b/src/HtmlUtils.js index d06c31682d..626b228357 100644 --- a/src/HtmlUtils.js +++ b/src/HtmlUtils.js @@ -250,7 +250,7 @@ const sanitizeHtmlParams = { allowedAttributes: { // custom ones first: font: ['color', 'data-mx-bg-color', 'data-mx-color', 'style'], // custom to matrix - span: ['data-mx-bg-color', 'data-mx-color', 'style'], // custom to matrix + span: ['data-mx-bg-color', 'data-mx-color', 'data-mx-spoiler', 'style'], // custom to matrix a: ['href', 'name', 'target', 'rel'], // remote target: custom to matrix img: ['src', 'width', 'height', 'alt', 'title'], ol: ['start'], diff --git a/src/components/views/elements/Spoiler.js b/src/components/views/elements/Spoiler.js new file mode 100644 index 0000000000..e1e0febbab --- /dev/null +++ b/src/components/views/elements/Spoiler.js @@ -0,0 +1,32 @@ +'use strict'; + +import React from 'react'; + +module.exports = React.createClass({ + displayName: 'Spoiler', + + getInitialState() { + return { + visible: false, + }; + }, + + toggleVisible() { + this.setState({ visible: !this.state.visible }); + }, + + render: function() { + const reason = this.props.reason ? ( + {"(" + this.props.reason + ")"} + ) : null; + return ( + + { reason } +   + + + + + ); + } +}) diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 1fc16d6a53..e6d67b034d 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -96,6 +96,8 @@ module.exports = React.createClass({ }, _applyFormatting() { + this.activateSpoilers(this.refs.content.children); + // pillifyLinks BEFORE linkifyElement because plain room/user URLs in the composer // are still sent as plaintext URLs. If these are ever pillified in the composer, // we should be pillify them here by doing the linkifying BEFORE the pillifying. @@ -184,6 +186,34 @@ module.exports = React.createClass({ } }, + activateSpoilers: function(nodes) { + let node = nodes[0]; + while (node) { + if (node.tagName === "SPAN" && typeof node.getAttribute("data-mx-spoiler") === "string") { + const spoilerContainer = document.createElement('span'); + + const reason = node.getAttribute("data-mx-spoiler"); + const Spoiler = sdk.getComponent('elements.Spoiler'); + node.removeAttribute("data-mx-spoiler"); // we don't want to recurse + const spoiler = ; + + ReactDOM.render(spoiler, spoilerContainer); + node.parentNode.replaceChild(spoilerContainer, node); + + node = spoilerContainer; + } + + if (node.childNodes && node.childNodes.length) { + this.activateSpoilers(node.childNodes); + } + + node = node.nextSibling; + } + }, + pillifyLinks: function(nodes) { const shouldShowPillAvatar = SettingsStore.getValue("Pill.shouldShowPillAvatar"); let node = nodes[0];