2017-11-21 14:55:50 +00:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
2019-05-20 20:43:50 +00:00
|
|
|
import { KeyboardUtils } from 'react-native-keyboard-input';
|
2017-11-21 14:55:50 +00:00
|
|
|
|
2018-09-11 16:32:52 +00:00
|
|
|
import Message from './Message';
|
2019-04-17 17:01:03 +00:00
|
|
|
import debounce from '../../utils/debounce';
|
2019-06-28 17:02:30 +00:00
|
|
|
import { SYSTEM_MESSAGES, getCustomEmoji, getMessageTranslation } from './utils';
|
2019-05-20 20:43:50 +00:00
|
|
|
import messagesStatus from '../../constants/messagesStatus';
|
2018-01-09 17:12:55 +00:00
|
|
|
|
2018-09-11 16:32:52 +00:00
|
|
|
export default class MessageContainer extends React.Component {
|
2017-11-21 14:55:50 +00:00
|
|
|
static propTypes = {
|
|
|
|
item: PropTypes.object.isRequired,
|
2018-07-10 13:40:32 +00:00
|
|
|
user: PropTypes.shape({
|
|
|
|
id: PropTypes.string.isRequired,
|
|
|
|
username: PropTypes.string.isRequired,
|
|
|
|
token: PropTypes.string.isRequired
|
|
|
|
}),
|
2019-05-20 20:43:50 +00:00
|
|
|
timeFormat: PropTypes.string,
|
2019-04-17 17:01:03 +00:00
|
|
|
customThreadTimeFormat: PropTypes.string,
|
2019-05-22 20:15:35 +00:00
|
|
|
style: PropTypes.any,
|
2018-05-24 20:17:45 +00:00
|
|
|
archived: PropTypes.bool,
|
2018-07-10 13:40:32 +00:00
|
|
|
broadcast: PropTypes.bool,
|
2018-09-11 16:32:52 +00:00
|
|
|
previousItem: PropTypes.object,
|
|
|
|
_updatedAt: PropTypes.instanceOf(Date),
|
|
|
|
baseUrl: PropTypes.string,
|
|
|
|
Message_GroupingPeriod: PropTypes.number,
|
2019-06-10 18:36:31 +00:00
|
|
|
isReadReceiptEnabled: PropTypes.bool,
|
2018-09-11 16:32:52 +00:00
|
|
|
useRealName: PropTypes.bool,
|
2019-05-20 20:43:50 +00:00
|
|
|
useMarkdown: PropTypes.bool,
|
2019-06-28 17:02:30 +00:00
|
|
|
autoTranslateRoom: PropTypes.bool,
|
|
|
|
autoTranslateLanguage: PropTypes.string,
|
2019-04-17 17:01:03 +00:00
|
|
|
status: PropTypes.number,
|
2018-09-11 16:32:52 +00:00
|
|
|
onLongPress: PropTypes.func,
|
|
|
|
onReactionPress: PropTypes.func,
|
2019-04-08 12:35:28 +00:00
|
|
|
onDiscussionPress: PropTypes.func,
|
2019-05-20 20:43:50 +00:00
|
|
|
onThreadPress: PropTypes.func,
|
2018-09-11 16:32:52 +00:00
|
|
|
errorActionsShow: PropTypes.func,
|
|
|
|
replyBroadcast: PropTypes.func,
|
2019-04-17 17:01:03 +00:00
|
|
|
toggleReactionPicker: PropTypes.func,
|
2019-05-20 20:43:50 +00:00
|
|
|
fetchThreadName: PropTypes.func,
|
|
|
|
onOpenFileModal: PropTypes.func,
|
|
|
|
onReactionLongPress: PropTypes.func
|
2018-01-30 19:48:26 +00:00
|
|
|
}
|
|
|
|
|
2018-03-23 16:49:51 +00:00
|
|
|
static defaultProps = {
|
|
|
|
onLongPress: () => {},
|
2018-03-29 17:55:37 +00:00
|
|
|
_updatedAt: new Date(),
|
2018-05-24 20:17:45 +00:00
|
|
|
archived: false,
|
|
|
|
broadcast: false
|
2018-03-23 16:49:51 +00:00
|
|
|
}
|
|
|
|
|
2019-05-20 20:43:50 +00:00
|
|
|
shouldComponentUpdate(nextProps) {
|
2018-09-25 19:28:42 +00:00
|
|
|
const {
|
2019-06-28 17:02:30 +00:00
|
|
|
status, item, _updatedAt, autoTranslateRoom
|
2018-09-25 19:28:42 +00:00
|
|
|
} = this.props;
|
|
|
|
|
|
|
|
if (status !== nextProps.status) {
|
2018-03-02 21:31:44 +00:00
|
|
|
return true;
|
|
|
|
}
|
2019-06-28 17:02:30 +00:00
|
|
|
if (autoTranslateRoom !== nextProps.autoTranslateRoom) {
|
|
|
|
return true;
|
|
|
|
}
|
2019-04-17 17:01:03 +00:00
|
|
|
if (item.tmsg !== nextProps.item.tmsg) {
|
2018-05-24 20:17:45 +00:00
|
|
|
return true;
|
|
|
|
}
|
2019-06-10 18:36:31 +00:00
|
|
|
if (item.unread !== nextProps.item.unread) {
|
|
|
|
return true;
|
|
|
|
}
|
2019-04-17 17:01:03 +00:00
|
|
|
|
|
|
|
return _updatedAt.toISOString() !== nextProps._updatedAt.toISOString();
|
2018-03-02 21:31:44 +00:00
|
|
|
}
|
2017-11-21 14:55:50 +00:00
|
|
|
|
2019-05-20 20:43:50 +00:00
|
|
|
onPress = debounce(() => {
|
|
|
|
const { item } = this.props;
|
|
|
|
KeyboardUtils.dismiss();
|
|
|
|
|
|
|
|
if ((item.tlm || item.tmid)) {
|
|
|
|
this.onThreadPress();
|
|
|
|
}
|
|
|
|
}, 300, true);
|
|
|
|
|
2018-04-24 19:34:03 +00:00
|
|
|
onLongPress = () => {
|
2019-05-20 20:43:50 +00:00
|
|
|
const { archived, onLongPress } = this.props;
|
|
|
|
if (this.isInfo || this.hasError || archived) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (onLongPress) {
|
|
|
|
onLongPress(this.parseMessage());
|
|
|
|
}
|
2017-11-21 14:55:50 +00:00
|
|
|
}
|
|
|
|
|
2018-04-24 19:34:03 +00:00
|
|
|
onErrorPress = () => {
|
2018-09-25 19:28:42 +00:00
|
|
|
const { errorActionsShow } = this.props;
|
2019-05-20 20:43:50 +00:00
|
|
|
if (errorActionsShow) {
|
|
|
|
errorActionsShow(this.parseMessage());
|
|
|
|
}
|
2018-01-30 19:48:26 +00:00
|
|
|
}
|
|
|
|
|
2018-04-24 19:34:03 +00:00
|
|
|
onReactionPress = (emoji) => {
|
2018-09-25 19:28:42 +00:00
|
|
|
const { onReactionPress, item } = this.props;
|
2019-05-20 20:43:50 +00:00
|
|
|
if (onReactionPress) {
|
|
|
|
onReactionPress(emoji, item._id);
|
|
|
|
}
|
2018-01-30 19:48:26 +00:00
|
|
|
}
|
2018-09-11 16:32:52 +00:00
|
|
|
|
|
|
|
onReactionLongPress = () => {
|
2019-05-20 20:43:50 +00:00
|
|
|
const { onReactionLongPress, item } = this.props;
|
|
|
|
if (onReactionLongPress) {
|
|
|
|
onReactionLongPress(item);
|
|
|
|
}
|
2017-12-13 15:00:26 +00:00
|
|
|
}
|
|
|
|
|
2019-04-08 12:35:28 +00:00
|
|
|
onDiscussionPress = () => {
|
|
|
|
const { onDiscussionPress, item } = this.props;
|
2019-05-20 20:43:50 +00:00
|
|
|
if (onDiscussionPress) {
|
|
|
|
onDiscussionPress(item);
|
2019-04-17 17:01:03 +00:00
|
|
|
}
|
2017-12-02 13:19:58 +00:00
|
|
|
}
|
|
|
|
|
2019-05-20 20:43:50 +00:00
|
|
|
onThreadPress = () => {
|
|
|
|
const { onThreadPress, item } = this.props;
|
|
|
|
if (onThreadPress) {
|
|
|
|
onThreadPress(item);
|
|
|
|
}
|
2017-12-13 15:00:26 +00:00
|
|
|
}
|
|
|
|
|
2019-05-20 20:43:50 +00:00
|
|
|
get isHeader() {
|
2018-09-25 19:28:42 +00:00
|
|
|
const {
|
|
|
|
item, previousItem, broadcast, Message_GroupingPeriod
|
|
|
|
} = this.props;
|
2019-07-17 14:06:39 +00:00
|
|
|
if (this.hasError || (previousItem && previousItem.status === messagesStatus.ERROR)) {
|
|
|
|
return true;
|
|
|
|
}
|
2018-04-24 19:34:03 +00:00
|
|
|
if (previousItem && (
|
2018-09-25 19:28:42 +00:00
|
|
|
(previousItem.ts.toDateString() === item.ts.toDateString())
|
|
|
|
&& (previousItem.u.username === item.u.username)
|
|
|
|
&& !(previousItem.groupable === false || item.groupable === false || broadcast === true)
|
|
|
|
&& (item.ts - previousItem.ts < Message_GroupingPeriod * 1000)
|
2019-04-17 17:01:03 +00:00
|
|
|
&& (previousItem.tmid === item.tmid)
|
2018-04-24 19:34:03 +00:00
|
|
|
)) {
|
2018-09-11 16:32:52 +00:00
|
|
|
return false;
|
2018-04-24 19:34:03 +00:00
|
|
|
}
|
2018-09-11 16:32:52 +00:00
|
|
|
return true;
|
2018-04-24 19:34:03 +00:00
|
|
|
}
|
|
|
|
|
2019-05-20 20:43:50 +00:00
|
|
|
get isThreadReply() {
|
2019-05-03 13:33:38 +00:00
|
|
|
const {
|
|
|
|
item, previousItem
|
|
|
|
} = this.props;
|
|
|
|
if (previousItem && item.tmid && (previousItem.tmid !== item.tmid) && (previousItem._id !== item.tmid)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-05-20 20:43:50 +00:00
|
|
|
get isThreadSequential() {
|
2019-05-03 13:33:38 +00:00
|
|
|
const {
|
|
|
|
item, previousItem
|
|
|
|
} = this.props;
|
|
|
|
if (previousItem && item.tmid && ((previousItem.tmid === item.tmid) || (previousItem._id === item.tmid))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-05-20 20:43:50 +00:00
|
|
|
get isInfo() {
|
|
|
|
const { item } = this.props;
|
|
|
|
return SYSTEM_MESSAGES.includes(item.t);
|
|
|
|
}
|
|
|
|
|
|
|
|
get isTemp() {
|
|
|
|
const { item } = this.props;
|
|
|
|
return item.status === messagesStatus.TEMP || item.status === messagesStatus.ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
get hasError() {
|
|
|
|
const { item } = this.props;
|
|
|
|
return item.status === messagesStatus.ERROR;
|
|
|
|
}
|
|
|
|
|
2018-09-25 19:28:42 +00:00
|
|
|
parseMessage = () => {
|
|
|
|
const { item } = this.props;
|
|
|
|
return JSON.parse(JSON.stringify(item));
|
|
|
|
}
|
2017-12-13 15:00:26 +00:00
|
|
|
|
2018-09-11 16:32:52 +00:00
|
|
|
toggleReactionPicker = () => {
|
2018-09-25 19:28:42 +00:00
|
|
|
const { toggleReactionPicker } = this.props;
|
2019-05-20 20:43:50 +00:00
|
|
|
if (toggleReactionPicker) {
|
|
|
|
toggleReactionPicker(this.parseMessage());
|
|
|
|
}
|
2018-01-30 19:48:26 +00:00
|
|
|
}
|
|
|
|
|
2018-09-11 16:32:52 +00:00
|
|
|
replyBroadcast = () => {
|
2018-09-25 19:28:42 +00:00
|
|
|
const { replyBroadcast } = this.props;
|
2019-05-20 20:43:50 +00:00
|
|
|
if (replyBroadcast) {
|
|
|
|
replyBroadcast(this.parseMessage());
|
|
|
|
}
|
2018-05-24 20:17:45 +00:00
|
|
|
}
|
|
|
|
|
2017-11-21 14:55:50 +00:00
|
|
|
render() {
|
2017-11-24 20:44:52 +00:00
|
|
|
const {
|
2019-06-28 17:02:30 +00:00
|
|
|
item, user, style, archived, baseUrl, useRealName, broadcast, fetchThreadName, customThreadTimeFormat, onOpenFileModal, timeFormat, useMarkdown, isReadReceiptEnabled, autoTranslateRoom, autoTranslateLanguage
|
2017-11-24 20:44:52 +00:00
|
|
|
} = this.props;
|
2018-09-11 16:32:52 +00:00
|
|
|
const {
|
2019-06-28 17:02:30 +00:00
|
|
|
_id, msg, ts, attachments, urls, reactions, t, avatar, u, alias, editedBy, role, drid, dcount, dlm, tmid, tcount, tlm, tmsg, mentions, channels, unread, autoTranslate: autoTranslateMessage
|
2018-09-11 16:32:52 +00:00
|
|
|
} = item;
|
2019-05-20 20:43:50 +00:00
|
|
|
|
2019-06-28 17:02:30 +00:00
|
|
|
let message = msg;
|
|
|
|
// "autoTranslateRoom" and "autoTranslateLanguage" are properties from the subscription
|
|
|
|
// "autoTranslateMessage" is a toggle between "View Original" and "Translate" state
|
|
|
|
if (autoTranslateRoom && autoTranslateMessage) {
|
|
|
|
message = getMessageTranslation(item, autoTranslateLanguage) || message;
|
|
|
|
}
|
|
|
|
|
2017-11-21 14:55:50 +00:00
|
|
|
return (
|
2018-09-11 16:32:52 +00:00
|
|
|
<Message
|
2019-04-17 17:01:03 +00:00
|
|
|
id={_id}
|
2019-06-28 17:02:30 +00:00
|
|
|
msg={message}
|
2018-09-11 16:32:52 +00:00
|
|
|
author={u}
|
|
|
|
ts={ts}
|
|
|
|
type={t}
|
|
|
|
attachments={attachments}
|
|
|
|
urls={urls}
|
|
|
|
reactions={reactions}
|
|
|
|
alias={alias}
|
|
|
|
avatar={avatar}
|
|
|
|
user={user}
|
2019-05-20 20:43:50 +00:00
|
|
|
timeFormat={timeFormat}
|
2019-04-17 17:01:03 +00:00
|
|
|
customThreadTimeFormat={customThreadTimeFormat}
|
2018-09-11 16:32:52 +00:00
|
|
|
style={style}
|
|
|
|
archived={archived}
|
|
|
|
broadcast={broadcast}
|
|
|
|
baseUrl={baseUrl}
|
|
|
|
useRealName={useRealName}
|
2019-06-10 18:36:31 +00:00
|
|
|
isReadReceiptEnabled={isReadReceiptEnabled}
|
|
|
|
unread={unread}
|
2018-09-19 14:18:32 +00:00
|
|
|
role={role}
|
2019-04-08 12:35:28 +00:00
|
|
|
drid={drid}
|
|
|
|
dcount={dcount}
|
|
|
|
dlm={dlm}
|
2019-04-17 17:01:03 +00:00
|
|
|
tmid={tmid}
|
|
|
|
tcount={tcount}
|
|
|
|
tlm={tlm}
|
|
|
|
tmsg={tmsg}
|
2019-05-20 20:43:50 +00:00
|
|
|
useMarkdown={useMarkdown}
|
2019-04-17 17:01:03 +00:00
|
|
|
fetchThreadName={fetchThreadName}
|
2019-05-20 20:43:50 +00:00
|
|
|
mentions={mentions}
|
|
|
|
channels={channels}
|
|
|
|
isEdited={editedBy && !!editedBy.username}
|
|
|
|
isHeader={this.isHeader}
|
|
|
|
isThreadReply={this.isThreadReply}
|
|
|
|
isThreadSequential={this.isThreadSequential}
|
|
|
|
isInfo={this.isInfo}
|
|
|
|
isTemp={this.isTemp}
|
|
|
|
hasError={this.hasError}
|
2018-09-11 16:32:52 +00:00
|
|
|
onErrorPress={this.onErrorPress}
|
2019-05-20 20:43:50 +00:00
|
|
|
onPress={this.onPress}
|
2018-04-24 19:34:03 +00:00
|
|
|
onLongPress={this.onLongPress}
|
2018-09-11 16:32:52 +00:00
|
|
|
onReactionLongPress={this.onReactionLongPress}
|
|
|
|
onReactionPress={this.onReactionPress}
|
|
|
|
replyBroadcast={this.replyBroadcast}
|
|
|
|
toggleReactionPicker={this.toggleReactionPicker}
|
2019-04-08 12:35:28 +00:00
|
|
|
onDiscussionPress={this.onDiscussionPress}
|
2019-05-20 20:43:50 +00:00
|
|
|
onOpenFileModal={onOpenFileModal}
|
|
|
|
getCustomEmoji={getCustomEmoji}
|
2018-09-11 16:32:52 +00:00
|
|
|
/>
|
2017-11-21 14:55:50 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|