diff --git a/css/converse.css b/css/converse.css index fcba2a396..e124fee8d 100644 --- a/css/converse.css +++ b/css/converse.css @@ -1617,6 +1617,8 @@ margin-top: 1em; } #converse-embedded-chat .chatbox .chat-body .chat-image, #conversejs .chatbox .chat-body .chat-image { + height: auto; + width: auto; max-height: 24em; max-width: 100%; } #converse-embedded-chat .chatbox .chat-body .chat-action, @@ -1679,6 +1681,9 @@ line-height: 1.3em; height: 206px; height: calc(100% - 96px); } + #converse-embedded-chat .chatbox .chat-content .toggle-spoiler:before, + #conversejs .chatbox .chat-content .toggle-spoiler:before { + padding-right: 0.25em; } #converse-embedded-chat .chatbox .chat-content-sendbutton, #conversejs .chatbox .chat-content-sendbutton { height: calc(100% - 128px); } diff --git a/css/inverse.css b/css/inverse.css index 70ab24a5d..eab910965 100644 --- a/css/inverse.css +++ b/css/inverse.css @@ -1682,6 +1682,8 @@ body { margin-top: 1em; } #converse-embedded-chat .chatbox .chat-body .chat-image, #conversejs .chatbox .chat-body .chat-image { + height: auto; + width: auto; max-height: 24em; max-width: 100%; } #converse-embedded-chat .chatbox .chat-body .chat-action, @@ -1744,6 +1746,9 @@ body { line-height: 1.3em; height: 206px; height: calc(100% - 100px); } + #converse-embedded-chat .chatbox .chat-content .toggle-spoiler:before, + #conversejs .chatbox .chat-content .toggle-spoiler:before { + padding-right: 0.25em; } #converse-embedded-chat .chatbox .chat-content-sendbutton, #conversejs .chatbox .chat-content-sendbutton { height: calc(100% - 132px); } diff --git a/sass/_chatbox.scss b/sass/_chatbox.scss index a2dcf364e..433060c0c 100644 --- a/sass/_chatbox.scss +++ b/sass/_chatbox.scss @@ -217,6 +217,11 @@ line-height: 1.3em; height: 206px; height: calc(100% - #{$toolbar-height + $chat-textarea-height +1px}); + + .toggle-spoiler:before { + padding-right: 0.25em; + whitespace: nowrap; + } } .chat-content-sendbutton { height: calc(100% - #{$toolbar-height + $chat-textarea-height + $send-button-height + 2*$send-button-margin}); diff --git a/src/config.js b/src/config.js index c84a86806..ec626cd75 100644 --- a/src/config.js +++ b/src/config.js @@ -85,7 +85,6 @@ require.config({ "converse-rosterview": "src/converse-rosterview", "converse-singleton": "src/converse-singleton", "converse-vcard": "src/converse-vcard", - "converse-spoilers": "src/converse-spoilers", // Off-the-record-encryption // "bigint": "node_modules/otr/build/dep/bigint", diff --git a/src/converse-chatview.js b/src/converse-chatview.js index 0eb5d11a7..538e61aa9 100644 --- a/src/converse-chatview.js +++ b/src/converse-chatview.js @@ -23,6 +23,7 @@ "tpl!new_day", "tpl!spinner", "tpl!spoiler_button", + "tpl!spoiler_message", "tpl!toolbar" ], factory); }(this, function ( @@ -41,6 +42,7 @@ tpl_new_day, tpl_spinner, tpl_spoiler_button, + tpl_spoiler_message, tpl_toolbar ) { "use strict"; @@ -361,7 +363,7 @@ 'click .toggle-clear': 'clearMessages', 'click .toggle-smiley ul.emoji-picker li': 'insertEmoji', 'click .toggle-smiley': 'toggleEmojiMenu', - 'click .toggle-spoiler-display': 'toggleSpoilerMessage', + 'click .toggle-spoiler': 'toggleSpoilerMessage', 'keypress .chat-textarea': 'keyPressed' }, @@ -610,14 +612,18 @@ } }, - getExtraMessageTemplateAttributes () { + getExtraMessageTemplateAttributes (attrs) { /* Provides a hook for sending more attributes to the * message template. * * Parameters: * (Object) attrs: An object containing message attributes. */ - return {}; + if (attrs.is_spoiler) { + return {'label_show': __('Show spoiler')}; + } else { + return {} + } }, getExtraMessageClasses (attrs) { @@ -632,46 +638,11 @@ /* Render a "spoiler" message, as defined in XEP-0382 * * Parameters: + * (HTMLElement) msg: The chat message DOM element * (Object) attrs: An object containing the message attributes. */ - console.log('Spoiler in attrs \n'); - const button = document.createElement("button"); - const container = document.createElement("div"); - const content = document.createElement( "div" ); - const hint = document.createElement("div"); - const contentHidden = document.createElement("div"); - const messageContent = msg.querySelector(".chat-msg-content"); - - hint.appendChild(document.createTextNode(attrs.spoiler_hint)); - - for (var i = 0; i < messageContent.childNodes.length; i++){ - contentHidden.append(messageContent.childNodes[i]); - } - contentHidden.classList.add("hidden"); - // contentHidden.addHyperlinks(); - // contentHidden.addEmoticons(_converse.visible_toolbar_buttons.emoticons); - - container.style.backgroundColor = "Lavender"; - container.style.textAlign = "center"; - - //Spoiler's content - content.classList.add("spoiler-content"); - content.appendChild(hint); - content.appendChild(contentHidden); - //Spoiler's button - button.classList.add("toggle-spoiler-display"); - button.classList.add("icon-eye"); - button.setAttribute("type", "button"); - button.appendChild(document.createTextNode(__('Show '))); - button.style.width = "100%"; - button.setAttribute("closed", "true"); - - container.appendChild(button); - container.appendChild(content); - - messageContent.textContent = ""; - messageContent.append(document.createElement("br")); - messageContent.append(container); + const hint = msg.querySelector('.spoiler-hint'); + hint.appendChild(document.createTextNode(attrs.spoiler_hint || '')); }, renderMessage (attrs) { @@ -697,6 +668,8 @@ } else { username = attrs.fullname; } + } else if (attrs.is_spoiler) { + template = tpl_spoiler_message; } else { template = tpl_message; username = attrs.sender === 'me' && __('me') || fullname; @@ -714,13 +687,13 @@ }) )); if (_converse.show_message_load_animation) { - window.setTimeout(_.partial(u.removeClass, 'onload', msg), 2000); + window.setTimeout( + _.partial(u.removeClass, 'onload', msg), 2000); } const msg_content = msg.querySelector('.chat-msg-content'); msg_content.innerHTML = u.addEmoji( _converse, emojione, u.addHyperlinks(xss.filterXSS(text, {'whiteList': {}})) ); - if (attrs.is_spoiler) { this.renderSpoilerMessage(msg, attrs) } @@ -846,11 +819,9 @@ }).c('body').t(message.get('message')).up() .c(_converse.ACTIVE, {'xmlns': Strophe.NS.CHATSTATES}).up(); - if (this.message_form_view.model.get('sending_spoiler')) { - const has_hint = this.el.querySelector('.spoiler-hint').value.length > 0; - if (has_hint) { - const hint = document.querySelector('.spoiler-hint').value; - stanza.c('spoiler', {'xmlns': Strophe.NS.SPOILER }, hint); + if (message.get('is_spoiler')) { + if (message.get('spoiler_hint')) { + stanza.c('spoiler', {'xmlns': Strophe.NS.SPOILER }, message.get('spoiler_hint')); } else { stanza.c('spoiler', {'xmlns': Strophe.NS.SPOILER }); } @@ -882,12 +853,14 @@ } }, - onMessageSubmitted (text) { + onMessageSubmitted (text, spoiler_hint) { /* This method gets called once the user has typed a message * and then pressed enter in a chat box. * * Parameters: - * (string) text - The chat message text. + * (String) text - The chat message text. + * (String) spoiler_hint - A hint in case the message + * text is a spoiler message. See XEP-0382 */ if (!_converse.connection.authenticated) { return this.showHelpMessages( @@ -911,12 +884,12 @@ return; } } - const attrs = this.getOutgoingMessageAttributes(text) + const attrs = this.getOutgoingMessageAttributes(text, spoiler_hint) const message = this.model.messages.create(attrs); this.sendMessage(message); }, - getOutgoingMessageAttributes (text) { + getOutgoingMessageAttributes (text, spoiler_hint) { /* Overridable method which returns the attributes to be * passed to Backbone.Message's constructor. */ @@ -930,8 +903,7 @@ 'is_spoiler': is_spoiler }; if (is_spoiler) { - const spoiler = this.el.querySelector('.spoiler-hint') - attrs.spoiler_hint = spoiler.textContent.length > 0 ? spoiler.textContent : __('Spoiler'); + attrs.spoiler_hint = spoiler_hint; } return attrs; }, @@ -988,10 +960,17 @@ ev.preventDefault(); const textarea = this.el.querySelector('.chat-textarea'), message = textarea.value; + + let spoiler_hint; + if (this.model.get('sending_spoiler')) { + const hint_el = this.el.querySelector('form.sendXMPPMessage input.spoiler-hint'); + spoiler_hint = hint_el.value; + hint_el.value = ''; + } textarea.value = ''; textarea.focus(); if (message !== '') { - this.onMessageSubmitted(message); + this.onMessageSubmitted(message, spoiler_hint); _converse.emit('messageSend', message); } this.setChatState(_converse.ACTIVE); @@ -1036,6 +1015,7 @@ this.insertIntoTextArea(target.getAttribute('data-emoji')); }, + toggleEmojiMenu (ev) { if (u.hasClass('insert-emoji', ev.target)) { return; @@ -1067,6 +1047,27 @@ }); }, + toggleSpoilerMessage (ev) { + if (ev && ev.preventDefault) { + ev.preventDefault(); + } + const toggle_el = ev.target; + u.slideToggleElement( + toggle_el.parentElement.querySelector('.spoiler') + ); + if (toggle_el.getAttribute("data-toggle-state") == "closed") { + toggle_el.textContent = __('Hide spoiler'); + toggle_el.classList.remove("icon-eye"); + toggle_el.classList.add("icon-eye-blocked"); + toggle_el.setAttribute("data-toggle-state", "open"); + } else { + toggle_el.textContent = __('Show spoiler'); + toggle_el.classList.remove("icon-eye-blocked"); + toggle_el.classList.add("icon-eye"); + toggle_el.setAttribute("data-toggle-state", "closed"); + } + }, + onChatStatusChanged (item) { const chat_status = item.get('chat_status'); let fullname = item.get('fullname'); diff --git a/src/converse-spoilers.js b/src/converse-spoilers.js deleted file mode 100644 index 9ad92ec07..000000000 --- a/src/converse-spoilers.js +++ /dev/null @@ -1,83 +0,0 @@ -(function (root, factory) { - define([ - "converse-core", - "converse-chatview" - ], factory); -}(this, function (converse) { - - // The following line registers your plugin. - converse.plugins.add("converse-spoilers", { - /* Optional dependencies are other plugins which might be - * overridden or relied upon, and therefore need to be loaded before - * this plugin. They are called "optional" because they might not be - * available, in which case any overrides applicable to them will be - * ignored. - * - * It's possible however to make optional dependencies non-optional. - * If the setting "strict_plugin_dependencies" is set to true, - * an error will be raised if the plugin is not found. - * - * NB: These plugins need to have already been loaded via require.js. - */ - dependencies: ["converse-chatview"], - - overrides: { - // Overrides mentioned here will be picked up by converse.js's - // plugin architecture they will replace existing methods on the - // relevant objects or classes. - // - // New functions which don't exist yet can also be added. - - 'ChatBoxView': { - - toggleSpoilerMessage (event) { - const { _converse } = this.__super__, - { __ } = _converse; - - const button = event.target; - const textarea = button.nextElementSibling; - const hint = textarea.children[0]; - const contentHidden = textarea.children[1]; - const container = button.parentElement; - - if (button.getAttribute("closed") == "true") { - //Show spoiler's content - button.classList.remove("icon-eye"); - button.classList.add("toggle-spoiler-display"); - button.classList.add("icon-eye-blocked"); - button.setAttribute("closed", "false"); - button.textContent = __('Hide '); - container.style.backgroundColor="#D5FFD2"; - - hint.classList.add("hidden"); - contentHidden.classList.remove("hidden"); - } else { //Hide spoiler's content - button.classList.remove("icon-eye-blocked"); - button.classList.add("icon-eye"); - button.setAttribute("closed", "true"); - button.textContent = __('Show '); - container.style.backgroundColor="Lavender"; - hint.classList.remove("hidden"); - contentHidden.classList.add("hidden"); - } - }, - - 'renderMessage': function (attrs) { - /* Renders a chat message based on the passed in attributes. - * - * Parameters: - * (Object) attrs: An object containing the message attributes. - * - * Returns: - * The DOM element representing the message. - */ - const { _converse } = this.__super__, - { __ } = _converse, - msg = this.__super__.renderMessage.apply(this, arguments); - - return msg; - } - } - } - }); -})); diff --git a/src/converse.js b/src/converse.js index 8928b6e9a..031cad98a 100644 --- a/src/converse.js +++ b/src/converse.js @@ -21,8 +21,7 @@ if (typeof define !== 'undefined') { "converse-minimize", // Allows chat boxes to be minimized "converse-dragresize", // Allows chat boxes to be resized by dragging them "converse-headline", // Support for headline messages - "converse-fullscreen", - "converse-spoilers" + "converse-fullscreen" /* END: Removable components */ ], function (converse) { return converse; diff --git a/src/templates/spoiler_message.html b/src/templates/spoiler_message.html new file mode 100644 index 000000000..a452e8e11 --- /dev/null +++ b/src/templates/spoiler_message.html @@ -0,0 +1,6 @@ +
+ {{{o.time}}} {{{o.username}}}:  +
+ {{{o.label_show}}} + +