Merge branch 'next' into features

This commit is contained in:
aforge
2021-09-17 09:18:58 +03:00
30 changed files with 1679 additions and 1718 deletions
+15 -5
View File
@@ -7,6 +7,7 @@ import Attachment from './attachment.jsx';
import LetterTile from './letter-tile.jsx';
import ReceivedMarker from './received-marker.jsx'
import { fullFormatter, quoteFormatter } from '../lib/formatters.js';
import { sanitizeImageUrl, sanitizeUrl } from '../lib/utils.js';
class BaseChatMessage extends React.PureComponent {
@@ -25,8 +26,17 @@ class BaseChatMessage extends React.PureComponent {
this.handleFormButtonClick = this.handleFormButtonClick.bind(this);
this.handleContextClick = this.handleContextClick.bind(this);
this.handleCancelUpload = this.handleCancelUpload.bind(this);
this.handleQuoteClick = this.handleQuoteClick.bind(this);
this.formatterContext = {
getFormatter: (tp) => { return tp == 'QQ' ? quoteFormatter : null; },
formatMessage: props.intl.formatMessage.bind(props.intl),
viewportWidth: props.viewportWidth,
authorizeURL: props.tinode.authorizeURL.bind(props.tinode),
onImagePreview: this.handleImagePreview,
onFormButtonClick: this.handleFormButtonClick,
onQuoteClick: this.handleQuoteClick
};
}
handleImagePreview(e) {
@@ -99,7 +109,7 @@ class BaseChatMessage extends React.PureComponent {
let content = this.props.content;
const attachments = [];
if (this.props.mimeType == Drafty.getContentType() && Drafty.isValid(content)) {
Drafty.attachments(content, function(att, i) {
Drafty.attachments(content, (att, i) => {
if (att.mime == 'application/json') {
// Don't show json objects as attachments.
// They are not meant for users.
@@ -117,7 +127,7 @@ class BaseChatMessage extends React.PureComponent {
onError={this.props.onError}
key={i} />);
}, this);
const tree = Drafty.format(content, this.props.formatter, this);
const tree = Drafty.format(content, fullFormatter, this.formatterContext);
content = React.createElement(React.Fragment, null, tree);
} else if (this.props.deleted) {
// Message represents a range of deleted messages.
@@ -126,9 +136,9 @@ class BaseChatMessage extends React.PureComponent {
defaultMessage="content deleted" description="Shown when messages are deleted" />
</i></>
} else if (typeof content != 'string') {
content = <><i className="material-icons gray">error_outline</i> <i className="gray">
content = <><i className="material-icons gray">warning_amber</i> <i className="gray">
<FormattedMessage id="invalid_content"
defaultMessage="invalid content" description="Shown when message is unreadable" /></i></>
defaultMessage="invalid content" description="Shown when the message is unreadable" /></i></>
}
return (
+6 -82
View File
@@ -1,6 +1,6 @@
// A single topic or user.
import React from 'react';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import { FormattedMessage, injectIntl } from 'react-intl';
import ContactBadges from './contact-badges.jsx';
import LetterTile from './letter-tile.jsx';
@@ -9,26 +9,9 @@ import UnreadBadge from './unread-badge.jsx';
import { Drafty } from 'tinode-sdk';
import { previewFormatter } from '../lib/formatters.js';
import { deliveryMarker } from '../lib/utils.js';
const messages = defineMessages({
drafty_image: {
id: 'drafty_image',
defaultMessage: 'Picture',
description: 'Comment for embedded images in drafty preview'
},
drafty_form: {
id: 'drafty_form',
defaultMessage: 'Form: ',
description: 'Comment for form in drafty preview'
},
drafty_attachment: {
id: 'drafty_attachment',
defaultMessage: 'Attachment',
description: 'Comment for attachment in drafty preview'
},
});
class Contact extends React.Component {
constructor(props) {
super(props);
@@ -89,10 +72,11 @@ 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, draftyFormatter, this)) :
<><i className="material-icons gray">error_outline</i> <i className="gray">
React.createElement(React.Fragment, null, Drafty.format(this.props.preview, previewFormatter,
{formatMessage: this.props.intl.formatMessage})) :
<><i className="material-icons gray">warning_amber</i> <i className="gray">
<FormattedMessage id="invalid_content"
defaultMessage="invalid content" description="Shown when message is unreadable" /></i>
defaultMessage="invalid content" description="Shown when the message is unreadable" /></i>
</>
) :
this.props.comment;
@@ -134,64 +118,4 @@ class Contact extends React.Component {
}
};
// Converts Drafty object into a one-line preview.
function draftyFormatter(style, data, values, key) {
let el = Drafty.tagName(style);
const attr = { key: key };
if (el) {
const { formatMessage } = this.props.intl;
switch (style) {
case 'BR':
// Replace new line with a space.
el = React.Fragment;
values = [' '];
break;
case 'HL':
// Make highlight less prominent in preview.
attr.className = 'highlight preview';
break;
case 'LN':
case 'MN':
// Disable links in previews.
el = 'span';
break;
case 'IM':
// Replace image with '[icon] Image'.
el = React.Fragment;
values = [<i key="im" className="material-icons">photo</i>, formatMessage(messages.drafty_image)];
break;
case 'BN':
el = 'span';
attr.className = 'flat-button faux';
break;
case 'FM':
el = React.Fragment;
values = [<i key="fm" className="material-icons">dashboard</i>,
formatMessage(messages.drafty_form)].concat(' ', values || []);
break;
case 'RW':
el = React.Fragment;
break;
case 'EX':
if (data && data.mime == 'application/json') {
// Ignore JSON attachments: they are form response payloads.
return null;
}
el = React.Fragment;
values = [<i key="ex" className="material-icons">attachment</i>, formatMessage(messages.drafty_attachment)];
break;
default:
if (el == '_UNKN') {
el = React.Fragment;
values = [<i key="unkn" className="material-icons">extension</i>, ' '].concat(values || []);
}
break;
}
return React.createElement(el, attr, values);
} else {
return values;
}
};
export default injectIntl(Contact);
+1 -1
View File
@@ -428,7 +428,7 @@ class ContextMenu extends React.Component {
}
replyToMessage(params, errorHandler) {
params.pickReply({ seq: params.seq, content: params.content });
params.pickReply(params.seq, params.content, errorHandler);
}
render() {
-1
View File
@@ -47,7 +47,6 @@ export default class DocPreview extends React.PureComponent {
noInput={true}
tinode={this.props.tinode}
replyTo={this.props.replyTo}
formatter={this.props.formatter}
onCancelReply={this.props.onCancelReply}
onSendMessage={this.handleSendDoc}
onError={this.props.onError} />
-1
View File
@@ -75,7 +75,6 @@ export default class ImagePreview extends React.PureComponent {
acceptBlank={true}
tinode={this.props.tinode}
replyTo={this.props.replyTo}
formatter={this.props.formatter}
onCancelReply={this.props.onCancelReply}
onSendMessage={this.handleSendImage}
onError={this.props.onError} />
+8 -5
View File
@@ -5,6 +5,7 @@ import { Drafty } from 'tinode-sdk';
import { KEYPRESS_DELAY } from '../config.js';
import { filePasted } from '../lib/blob-helpers.js';
import { quoteFormatter } from '../lib/formatters.js';
const messages = defineMessages({
messaging_disabled: {
@@ -153,17 +154,19 @@ class SendMessage extends React.PureComponent {
}
render() {
const {formatMessage} = this.props.intl;
const { formatMessage } = this.props.intl;
const prompt = this.props.disabled ?
formatMessage(messages.messaging_disabled) :
(this.props.messagePrompt ?
formatMessage(messages[this.props.messagePrompt]) :
formatMessage(messages.type_new_message));
let quote = null;
if (this.props.replyTo) {
quote = Drafty.format(this.props.replyTo.content, this.props.formatter, this);
}
const quote = this.props.replyTo ?
Drafty.format(this.props.replyTo.content, quoteFormatter, {
formatMessage: formatMessage.bind(this.props.intl),
authorizeURL: this.props.tinode.authorizeURL.bind(this.props.tinode)
}) :
null;
return (
<div id="send-message-wrapper">