From fb3fae8c9b26a9ed83950f4d3ac2997e13914a04 Mon Sep 17 00:00:00 2001 From: aforge Date: Thu, 23 Sep 2021 20:07:21 +0300 Subject: [PATCH] Replace "Forwarded from" with an icon. --- src/lib/formatters.js | 21 ++++++++++++++++++++- src/views/messages-view.jsx | 3 ++- src/views/tinode-web.jsx | 8 +++----- src/widgets/chat-message.jsx | 5 +++-- src/widgets/contact-list.jsx | 3 +++ src/widgets/contact.jsx | 6 +++--- src/widgets/send-message.jsx | 12 +++++++----- 7 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/lib/formatters.js b/src/lib/formatters.js index 89392274..b571cc23 100644 --- a/src/lib/formatters.js +++ b/src/lib/formatters.js @@ -26,7 +26,7 @@ const messages = defineMessages({ id: 'drafty_image', defaultMessage: 'Picture', description: 'Comment for embedded images in drafty preview' - }, + } }); // Size the already scaled image. @@ -393,3 +393,22 @@ export function replyFormatter(style, data, values, key) { values = [React.createElement(LazyImage, attr, null), ' ', attr.alt]; return React.createElement(React.Fragment, {key: key}, values); } + +// Creates a "forward" icon fragment. +export function forwardedDecorator(context) { + return [forward]; +} + +// Returns a fully decorated ready for rendering representation of a drafty object. +export function formatDrafty(content, formatter, context, decorators) { + let tree = Drafty.format(content, formatter, context); + if (decorators) { + if (decorators.before) { + tree = decorators.before(context).concat(tree); + } + if (decorators.after) { + tree = tree.concat(decorators.after(context)); + } + } + return tree; +} diff --git a/src/views/messages-view.jsx b/src/views/messages-view.jsx index d2b7d22d..5b1f2739 100644 --- a/src/views/messages-view.jsx +++ b/src/views/messages-view.jsx @@ -221,6 +221,7 @@ class MessagesView extends React.Component { const preview = nextProps.forwardedMessage.preview; reply = { content: preview, + forwarded: nextProps.forwardedMessage.head.forwarded, seq: null }; } @@ -971,7 +972,6 @@ class MessagesView extends React.Component { userName = user.public.fn; userAvatar = makeImageUrl(user.public.photo); } - //userFrom = thisFrom; chatBoxClass = groupTopic ? 'chat-box group' : 'chat-box'; // Ref for this chat message. @@ -985,6 +985,7 @@ class MessagesView extends React.Component { ); }, this); - const tree = Drafty.format(content, fullFormatter, this.formatterContext); + const tree = formatDrafty(content, fullFormatter, this.formatterContext, + this.props.forwarded ? { before: forwardedDecorator } : null); content = React.createElement(React.Fragment, null, tree); } else if (this.props.deleted) { // Message represents a range of deleted messages. diff --git a/src/widgets/contact-list.jsx b/src/widgets/contact-list.jsx index 86fa95a6..1a456efb 100644 --- a/src/widgets/contact-list.jsx +++ b/src/widgets/contact-list.jsx @@ -77,6 +77,7 @@ class ContactList extends React.Component { const comment = Array.isArray(c.private) ? c.private.join(',') : (c.private ? c.private.comment : null); let preview; + let forwarded; let deliveryStatus; if (!this.props.showMode && c.latestMessage) { const msg = c.latestMessage(true); @@ -85,6 +86,7 @@ class ContactList extends React.Component { preview = typeof msg.content == 'string' ? msg.content.substr(0, MESSAGE_PREVIEW_LENGTH) : Drafty.preview(msg.content, MESSAGE_PREVIEW_LENGTH); + forwarded = msg.head ? msg.head.forwarded : undefined; } } contactNodes.push( @@ -94,6 +96,7 @@ class ContactList extends React.Component { avatar={makeImageUrl(c.public ? c.public.photo : null)} comment={comment} preview={preview} + forwarded={forwarded} received={deliveryStatus} unread={this.props.showUnread ? c.unread : 0} now={c.online && this.props.connected} diff --git a/src/widgets/contact.jsx b/src/widgets/contact.jsx index ea8c733e..d055bb6b 100644 --- a/src/widgets/contact.jsx +++ b/src/widgets/contact.jsx @@ -9,7 +9,7 @@ import UnreadBadge from './unread-badge.jsx'; import { Drafty } from 'tinode-sdk'; -import { previewFormatter } from '../lib/formatters.js'; +import { previewFormatter, formatDrafty, forwardedDecorator } from '../lib/formatters.js'; import { deliveryMarker } from '../lib/utils.js'; class Contact extends React.Component { @@ -72,8 +72,8 @@ class Contact extends React.Component { const subtitle = this.props.preview ? (typeof this.props.preview == 'string' ? this.props.preview : Drafty.isValid(this.props.preview) ? - React.createElement(React.Fragment, null, Drafty.format(this.props.preview, previewFormatter, - {formatMessage: this.props.intl.formatMessage})) : + React.createElement(React.Fragment, null, formatDrafty(this.props.preview, previewFormatter, + {formatMessage: this.props.intl.formatMessage}, this.props.forwarded ? { before: forwardedDecorator } : null)) : <>warning_amber diff --git a/src/widgets/send-message.jsx b/src/widgets/send-message.jsx index 35d84434..5897d249 100644 --- a/src/widgets/send-message.jsx +++ b/src/widgets/send-message.jsx @@ -5,7 +5,7 @@ import { Drafty } from 'tinode-sdk'; import { KEYPRESS_DELAY } from '../config.js'; import { filePasted } from '../lib/blob-helpers.js'; -import { quoteFormatter, replyFormatter } from '../lib/formatters.js'; +import { quoteFormatter, replyFormatter, formatDrafty, forwardedDecorator } from '../lib/formatters.js'; const messages = defineMessages({ messaging_disabled: { @@ -61,10 +61,11 @@ class SendMessage extends React.PureComponent { } this.setState({quote: this.props.replyTo ? - Drafty.format(this.props.replyTo.content, replyFormatter, { + formatDrafty(this.props.replyTo.content, replyFormatter, { formatMessage: this.props.intl.formatMessage.bind(this.props.intl), authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode) - }) : + }, + this.props.replyTo.forwarded ? { before: forwardedDecorator } : null) : null}); } @@ -81,10 +82,11 @@ class SendMessage extends React.PureComponent { if (prevProps.replyTo != this.props.replyTo) { this.setState({quote: this.props.replyTo ? - Drafty.format(this.props.replyTo.content, replyFormatter, { + formatDrafty(this.props.replyTo.content, replyFormatter, { formatMessage: this.props.intl.formatMessage.bind(this.props.intl), authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode) - }) : + }, + this.props.replyTo.forwarded ? { before: forwardedDecorator } : null) : null}); } }