Replace "Forwarded from" with an icon.
This commit is contained in:
+20
-1
@@ -26,7 +26,7 @@ const messages = defineMessages({
|
|||||||
id: 'drafty_image',
|
id: 'drafty_image',
|
||||||
defaultMessage: 'Picture',
|
defaultMessage: 'Picture',
|
||||||
description: 'Comment for embedded images in drafty preview'
|
description: 'Comment for embedded images in drafty preview'
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Size the already scaled image.
|
// Size the already scaled image.
|
||||||
@@ -393,3 +393,22 @@ export function replyFormatter(style, data, values, key) {
|
|||||||
values = [React.createElement(LazyImage, attr, null), ' ', attr.alt];
|
values = [React.createElement(LazyImage, attr, null), ' ', attr.alt];
|
||||||
return React.createElement(React.Fragment, {key: key}, values);
|
return React.createElement(React.Fragment, {key: key}, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Creates a "forward" icon fragment.
|
||||||
|
export function forwardedDecorator(context) {
|
||||||
|
return [<i key="fwd" className="material-icons">forward</i>];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ class MessagesView extends React.Component {
|
|||||||
const preview = nextProps.forwardedMessage.preview;
|
const preview = nextProps.forwardedMessage.preview;
|
||||||
reply = {
|
reply = {
|
||||||
content: preview,
|
content: preview,
|
||||||
|
forwarded: nextProps.forwardedMessage.head.forwarded,
|
||||||
seq: null
|
seq: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -971,7 +972,6 @@ class MessagesView extends React.Component {
|
|||||||
userName = user.public.fn;
|
userName = user.public.fn;
|
||||||
userAvatar = makeImageUrl(user.public.photo);
|
userAvatar = makeImageUrl(user.public.photo);
|
||||||
}
|
}
|
||||||
//userFrom = thisFrom;
|
|
||||||
chatBoxClass = groupTopic ? 'chat-box group' : 'chat-box';
|
chatBoxClass = groupTopic ? 'chat-box group' : 'chat-box';
|
||||||
|
|
||||||
// Ref for this chat message.
|
// Ref for this chat message.
|
||||||
@@ -985,6 +985,7 @@ class MessagesView extends React.Component {
|
|||||||
<ChatMessage
|
<ChatMessage
|
||||||
tinode={this.props.tinode}
|
tinode={this.props.tinode}
|
||||||
content={msg.content}
|
content={msg.content}
|
||||||
|
forwarded={msg.head ? msg.head.forwarded : null}
|
||||||
deleted={msg.hi}
|
deleted={msg.hi}
|
||||||
mimeType={msg.head ? msg.head.mime : null}
|
mimeType={msg.head ? msg.head.mime : null}
|
||||||
timestamp={msg.ts}
|
timestamp={msg.ts}
|
||||||
|
|||||||
@@ -1450,7 +1450,7 @@ class TinodeWeb extends React.Component {
|
|||||||
// If the Find panel is active, close it.
|
// If the Find panel is active, close it.
|
||||||
this.handleSidepanelCancel();
|
this.handleSidepanelCancel();
|
||||||
}
|
}
|
||||||
const header = "Forwarded from " + params.userName;
|
const header = params.userName;
|
||||||
const content = typeof params.content == 'string' ? Tinode.Drafty.init(params.content) : params.content;
|
const content = typeof params.content == 'string' ? Tinode.Drafty.init(params.content) : params.content;
|
||||||
const preview = Tinode.Drafty.preview(content, 30);
|
const preview = Tinode.Drafty.preview(content, 30);
|
||||||
const msg = Tinode.Drafty.append(
|
const msg = Tinode.Drafty.append(
|
||||||
@@ -1459,9 +1459,7 @@ class TinodeWeb extends React.Component {
|
|||||||
content);
|
content);
|
||||||
const msgPreview = Tinode.Drafty.quote(header, params.userFrom, preview);
|
const msgPreview = Tinode.Drafty.quote(header, params.userFrom, preview);
|
||||||
const head = {
|
const head = {
|
||||||
// TODO: decide what parameters to store.
|
forwarded: params.topicName + ':' + params.seq
|
||||||
fwdFrom: params.topicName,
|
|
||||||
authorUid: params.userFrom
|
|
||||||
};
|
};
|
||||||
this.setState({
|
this.setState({
|
||||||
forwardMenuVisible: true,
|
forwardMenuVisible: true,
|
||||||
@@ -1760,7 +1758,7 @@ class TinodeWeb extends React.Component {
|
|||||||
applicationVisible={this.state.applicationVisible}
|
applicationVisible={this.state.applicationVisible}
|
||||||
|
|
||||||
// Show the forwareded message if the user has selected a topic to forward this message to.
|
// Show the forwareded message if the user has selected a topic to forward this message to.
|
||||||
forwardedMessage={this.state.forwardMessage && this.stateTopicSelected != this.state.forwardMessage.head.fwdFrom ? this.state.forwardMessage : null}
|
forwardedMessage={this.state.forwardMessage && !this.state.forwardMessage.head.forwarded.startsWith(this.stateTopicSelected) ? this.state.forwardMessage : null}
|
||||||
onCancelForwardMessage={this.handleHideForwardMenu}
|
onCancelForwardMessage={this.handleHideForwardMenu}
|
||||||
|
|
||||||
errorText={this.state.errorText}
|
errorText={this.state.errorText}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import Attachment from './attachment.jsx';
|
|||||||
import LetterTile from './letter-tile.jsx';
|
import LetterTile from './letter-tile.jsx';
|
||||||
import ReceivedMarker from './received-marker.jsx'
|
import ReceivedMarker from './received-marker.jsx'
|
||||||
|
|
||||||
import { fullFormatter, quoteFormatter } from '../lib/formatters.js';
|
import { fullFormatter, quoteFormatter, formatDrafty, forwardedDecorator } from '../lib/formatters.js';
|
||||||
import { sanitizeImageUrl, sanitizeUrl } from '../lib/utils.js';
|
import { sanitizeImageUrl, sanitizeUrl } from '../lib/utils.js';
|
||||||
|
|
||||||
class BaseChatMessage extends React.PureComponent {
|
class BaseChatMessage extends React.PureComponent {
|
||||||
@@ -129,7 +129,8 @@ class BaseChatMessage extends React.PureComponent {
|
|||||||
onError={this.props.onError}
|
onError={this.props.onError}
|
||||||
key={i} />);
|
key={i} />);
|
||||||
}, this);
|
}, 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);
|
content = React.createElement(React.Fragment, null, tree);
|
||||||
} else if (this.props.deleted) {
|
} else if (this.props.deleted) {
|
||||||
// Message represents a range of deleted messages.
|
// Message represents a range of deleted messages.
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ class ContactList extends React.Component {
|
|||||||
const comment = Array.isArray(c.private) ?
|
const comment = Array.isArray(c.private) ?
|
||||||
c.private.join(',') : (c.private ? c.private.comment : null);
|
c.private.join(',') : (c.private ? c.private.comment : null);
|
||||||
let preview;
|
let preview;
|
||||||
|
let forwarded;
|
||||||
let deliveryStatus;
|
let deliveryStatus;
|
||||||
if (!this.props.showMode && c.latestMessage) {
|
if (!this.props.showMode && c.latestMessage) {
|
||||||
const msg = c.latestMessage(true);
|
const msg = c.latestMessage(true);
|
||||||
@@ -85,6 +86,7 @@ class ContactList extends React.Component {
|
|||||||
preview = typeof msg.content == 'string' ?
|
preview = typeof msg.content == 'string' ?
|
||||||
msg.content.substr(0, MESSAGE_PREVIEW_LENGTH) :
|
msg.content.substr(0, MESSAGE_PREVIEW_LENGTH) :
|
||||||
Drafty.preview(msg.content, MESSAGE_PREVIEW_LENGTH);
|
Drafty.preview(msg.content, MESSAGE_PREVIEW_LENGTH);
|
||||||
|
forwarded = msg.head ? msg.head.forwarded : undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
contactNodes.push(
|
contactNodes.push(
|
||||||
@@ -94,6 +96,7 @@ class ContactList extends React.Component {
|
|||||||
avatar={makeImageUrl(c.public ? c.public.photo : null)}
|
avatar={makeImageUrl(c.public ? c.public.photo : null)}
|
||||||
comment={comment}
|
comment={comment}
|
||||||
preview={preview}
|
preview={preview}
|
||||||
|
forwarded={forwarded}
|
||||||
received={deliveryStatus}
|
received={deliveryStatus}
|
||||||
unread={this.props.showUnread ? c.unread : 0}
|
unread={this.props.showUnread ? c.unread : 0}
|
||||||
now={c.online && this.props.connected}
|
now={c.online && this.props.connected}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import UnreadBadge from './unread-badge.jsx';
|
|||||||
|
|
||||||
import { Drafty } from 'tinode-sdk';
|
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';
|
import { deliveryMarker } from '../lib/utils.js';
|
||||||
|
|
||||||
class Contact extends React.Component {
|
class Contact extends React.Component {
|
||||||
@@ -72,8 +72,8 @@ class Contact extends React.Component {
|
|||||||
const subtitle = this.props.preview ?
|
const subtitle = this.props.preview ?
|
||||||
(typeof this.props.preview == 'string' ? this.props.preview :
|
(typeof this.props.preview == 'string' ? this.props.preview :
|
||||||
Drafty.isValid(this.props.preview) ?
|
Drafty.isValid(this.props.preview) ?
|
||||||
React.createElement(React.Fragment, null, Drafty.format(this.props.preview, previewFormatter,
|
React.createElement(React.Fragment, null, formatDrafty(this.props.preview, previewFormatter,
|
||||||
{formatMessage: this.props.intl.formatMessage})) :
|
{formatMessage: this.props.intl.formatMessage}, this.props.forwarded ? { before: forwardedDecorator } : null)) :
|
||||||
<><i className="material-icons gray">warning_amber</i> <i className="gray">
|
<><i className="material-icons gray">warning_amber</i> <i className="gray">
|
||||||
<FormattedMessage id="invalid_content"
|
<FormattedMessage id="invalid_content"
|
||||||
defaultMessage="invalid content" description="Shown when the message is unreadable" /></i>
|
defaultMessage="invalid content" description="Shown when the message is unreadable" /></i>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Drafty } from 'tinode-sdk';
|
|||||||
|
|
||||||
import { KEYPRESS_DELAY } from '../config.js';
|
import { KEYPRESS_DELAY } from '../config.js';
|
||||||
import { filePasted } from '../lib/blob-helpers.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({
|
const messages = defineMessages({
|
||||||
messaging_disabled: {
|
messaging_disabled: {
|
||||||
@@ -61,10 +61,11 @@ class SendMessage extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setState({quote: 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),
|
formatMessage: this.props.intl.formatMessage.bind(this.props.intl),
|
||||||
authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode)
|
authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode)
|
||||||
}) :
|
},
|
||||||
|
this.props.replyTo.forwarded ? { before: forwardedDecorator } : null) :
|
||||||
null});
|
null});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,10 +82,11 @@ class SendMessage extends React.PureComponent {
|
|||||||
|
|
||||||
if (prevProps.replyTo != this.props.replyTo) {
|
if (prevProps.replyTo != this.props.replyTo) {
|
||||||
this.setState({quote: 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),
|
formatMessage: this.props.intl.formatMessage.bind(this.props.intl),
|
||||||
authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode)
|
authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode)
|
||||||
}) :
|
},
|
||||||
|
this.props.replyTo.forwarded ? { before: forwardedDecorator } : null) :
|
||||||
null});
|
null});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user