// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import { Platform, TouchableHighlight, TouchableOpacity, View } from 'react-native'; import {injectIntl, intlShape} from 'react-intl'; import Icon from 'react-native-vector-icons/Ionicons'; import FileAttachmentList from 'app/components/file_attachment_list'; import FormattedText from 'app/components/formatted_text'; import Markdown from 'app/components/markdown'; import OptionsContext from 'app/components/options_context'; import PostBodyAdditionalContent from 'app/components/post_body_additional_content'; import {emptyFunction} from 'app/utils/general'; import {getMarkdownTextStyles, getMarkdownBlockStyles} from 'app/utils/markdown'; import {makeStyleSheetFromTheme} from 'app/utils/theme'; import Reactions from 'app/components/reactions'; class PostBody extends PureComponent { static propTypes = { actions: PropTypes.shape({ flagPost: PropTypes.func.isRequired, unflagPost: PropTypes.func.isRequired }).isRequired, canDelete: PropTypes.bool, canEdit: PropTypes.bool, fileIds: PropTypes.array, hasBeenDeleted: PropTypes.bool, hasReactions: PropTypes.bool, intl: intlShape.isRequired, isFailed: PropTypes.bool, isFlagged: PropTypes.bool, isPending: PropTypes.bool, isPostEphemeral: PropTypes.bool, isSearchResult: PropTypes.bool, isSystemMessage: PropTypes.bool, message: PropTypes.string, navigator: PropTypes.object.isRequired, onAddReaction: PropTypes.func, onFailedPostPress: PropTypes.func, onPostDelete: PropTypes.func, onPostEdit: PropTypes.func, onPress: PropTypes.func, postId: PropTypes.string.isRequired, postProps: PropTypes.object, renderReplyBar: PropTypes.func, theme: PropTypes.object, toggleSelected: PropTypes.func }; static defaultProps = { fileIds: [], onAddReaction: emptyFunction, onFailedPostPress: emptyFunction, onPostDelete: emptyFunction, onPostEdit: emptyFunction, onPress: emptyFunction, renderReplyBar: emptyFunction, toggleSelected: emptyFunction }; handleHideUnderlay = () => { this.props.toggleSelected(false); }; handleShowUnderlay = () => { this.props.toggleSelected(true); }; hideOptionsContext = () => { if (Platform.OS === 'ios' && this.refs.options) { this.refs.options.hide(); } }; flagPost = () => { const {actions, postId} = this.props; actions.flagPost(postId); }; unflagPost = () => { const {actions, postId} = this.props; actions.unflagPost(postId); }; showOptionsContext = () => { if (this.refs.options) { this.refs.options.show(); } }; renderFileAttachments() { const { fileIds, isFailed, navigator, onPress, postId, toggleSelected } = this.props; let attachments; if (fileIds.length > 0) { attachments = ( ); } return attachments; } render() { const { canDelete, canEdit, hasBeenDeleted, hasReactions, isFailed, isFlagged, isPending, isPostEphemeral, isSearchResult, isSystemMessage, intl, message, navigator, onFailedPostPress, onPostDelete, onPostEdit, onPress, postId, postProps, renderReplyBar, theme, toggleSelected } = this.props; const {formatMessage} = intl; const actions = []; const style = getStyleSheet(theme); const blockStyles = getMarkdownBlockStyles(theme); const textStyles = getMarkdownTextStyles(theme); const messageStyle = isSystemMessage ? [style.message, style.systemMessage] : style.message; const isPendingOrFailedPost = isPending || isFailed; // we should check for the user roles and permissions if (!isPendingOrFailedPost && !isSearchResult && !isSystemMessage && !isPostEphemeral) { if (isFlagged) { actions.push({ text: formatMessage({id: 'post_info.mobile.unflag', defaultMessage: 'Unflag'}), onPress: this.unflagPost }); } else { actions.push({ text: formatMessage({id: 'post_info.mobile.flag', defaultMessage: 'Flag'}), onPress: this.flagPost }); } if (canEdit) { actions.push({text: formatMessage({id: 'post_info.edit', defaultMessage: 'Edit'}), onPress: onPostEdit}); } if (canDelete && !hasBeenDeleted) { actions.push({text: formatMessage({id: 'post_info.del', defaultMessage: 'Delete'}), onPress: onPostDelete}); } actions.push({ text: formatMessage({id: 'mobile.post_info.add_reaction', defaultMessage: 'Add Reaction'}), onPress: this.props.onAddReaction }); } let body; let messageComponent; if (hasBeenDeleted) { messageComponent = ( ); body = ({messageComponent}); } else if (message.length) { messageComponent = ( ); } if (!hasBeenDeleted) { if (isSearchResult) { body = ( {messageComponent} {this.renderFileAttachments()} ); } else { body = ( {messageComponent} {this.renderFileAttachments()} {hasReactions && } ); } } return ( {renderReplyBar()} {body} {isFailed && } ); } } const getStyleSheet = makeStyleSheetFromTheme((theme) => { return { message: { color: theme.centerChannelColor, fontSize: 15, lineHeight: 20 }, messageContainerWithReplyBar: { flexDirection: 'row', flex: 1 }, pendingPost: { opacity: 0.5 }, systemMessage: { opacity: 0.6 } }; }); export default injectIntl(PostBody);