// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import { Text, View, } from 'react-native'; import FormattedText from 'app/components/formatted_text'; import FormattedTime from 'app/components/formatted_time'; import FormattedDate from 'app/components/formatted_date'; import ReplyIcon from 'app/components/reply_icon'; import Tag, {BotTag, GuestTag} from 'app/components/tag'; import TouchableWithFeedback from 'app/components/touchable_with_feedback'; import {emptyFunction} from 'app/utils/general'; import {t} from 'app/utils/i18n'; import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; export default class PostHeader extends PureComponent { static propTypes = { commentCount: PropTypes.number, commentedOnDisplayName: PropTypes.string, createAt: PropTypes.number.isRequired, displayName: PropTypes.string, enablePostUsernameOverride: PropTypes.bool, fromWebHook: PropTypes.bool, isPendingOrFailedPost: PropTypes.bool, isSearchResult: PropTypes.bool, isSystemMessage: PropTypes.bool, fromAutoResponder: PropTypes.bool, militaryTime: PropTypes.bool, onPress: PropTypes.func, onUsernamePress: PropTypes.func, overrideUsername: PropTypes.string, renderReplies: PropTypes.bool, shouldRenderReplyButton: PropTypes.bool, showFullDate: PropTypes.bool, theme: PropTypes.object.isRequired, username: PropTypes.string, isBot: PropTypes.bool, isGuest: PropTypes.bool, userTimezone: PropTypes.string, enableTimezone: PropTypes.bool, previousPostExists: PropTypes.bool, post: PropTypes.object, beforePrevPostUserId: PropTypes.string, isLandscape: PropTypes.bool.isRequired, }; static defaultProps = { commentCount: 0, onPress: emptyFunction, onUsernamePress: emptyFunction, }; handleUsernamePress = () => { if (this.props.username) { this.props.onUsernamePress(this.props.username); } }; renderCommentedOnMessage = () => { const { beforePrevPostUserId, commentedOnDisplayName, post, previousPostExists, renderReplies, theme, } = this.props; if (!renderReplies || !commentedOnDisplayName || (!previousPostExists && post.user_id === beforePrevPostUserId)) { return null; } const style = getStyleSheet(theme); const displayName = commentedOnDisplayName; let name; if (displayName) { name = displayName; } else { name = ( ); } let apostrophe; if (displayName && displayName.slice(-1) === 's') { apostrophe = '\''; } else { apostrophe = '\'s'; } return ( ); }; calcNameWidth = () => { const { fromWebHook, fromAutoResponder, renderReplies, shouldRenderReplyButton, commentedOnDisplayName, commentCount, isBot, isLandscape, theme, } = this.props; const style = getStyleSheet(theme); const showReply = shouldRenderReplyButton || (!commentedOnDisplayName && commentCount > 0 && renderReplies); const reduceWidth = showReply && (isBot || fromAutoResponder || fromWebHook); if (reduceWidth && isLandscape) { return style.displayNameContainerLandscapeBotReplyWidth; } else if (isLandscape) { return style.displayNameContainerLandscape; } else if (reduceWidth) { return style.displayNameContainerBotReplyWidth; } return null; } renderDisplayName = () => { const { displayName, enablePostUsernameOverride, fromWebHook, isSystemMessage, fromAutoResponder, overrideUsername, theme, } = this.props; const style = getStyleSheet(theme); const displayNameWidth = this.calcNameWidth(); const displayNameStyle = [style.displayNameContainer, displayNameWidth]; if (fromAutoResponder || fromWebHook) { let name = displayName; if (overrideUsername && enablePostUsernameOverride) { name = overrideUsername; } return ( {name} ); } else if (isSystemMessage) { return ( ); } else if (displayName) { return ( {displayName} ); } return ( ); }; renderReply = () => { const { commentCount, commentedOnDisplayName, isSearchResult, onPress, renderReplies, shouldRenderReplyButton, theme, } = this.props; const style = getStyleSheet(theme); const showReply = shouldRenderReplyButton || (!commentedOnDisplayName && commentCount > 0 && renderReplies); if (!showReply) { return null; } return ( {!isSearchResult && {commentCount} } ); }; renderTag = () => { const {fromAutoResponder, fromWebHook, isBot, isSystemMessage, isGuest, theme} = this.props; const style = getStyleSheet(theme); if (fromWebHook || isBot) { return ( ); } else if (isSystemMessage) { return null; } else if (isGuest) { return ( ); } else if (fromAutoResponder) { return ( ); } return null; }; render() { const { createAt, isPendingOrFailedPost, userTimezone, militaryTime, showFullDate, theme, } = this.props; const style = getStyleSheet(theme); let dateComponent; if (showFullDate) { dateComponent = ( ); } else { dateComponent = ( ); } return ( {this.renderDisplayName()} {this.renderTag()} {dateComponent} {this.renderReply()} {this.renderCommentedOnMessage(style)} ); } } const getStyleSheet = makeStyleSheetFromTheme((theme) => { return { container: { flex: 1, marginTop: 10, }, pendingPost: { opacity: 0.5, }, tag: { marginLeft: 0, marginRight: 5, marginBottom: 5, }, wrapper: { flex: 1, flexDirection: 'row', }, displayNameContainer: { maxWidth: '60%', marginRight: 5, marginBottom: 3, }, displayName: { color: theme.centerChannelColor, fontSize: 15, fontWeight: '600', flexGrow: 1, paddingVertical: 2, }, time: { color: theme.centerChannelColor, fontSize: 12, marginTop: 5, opacity: 0.5, flex: 1, }, replyWrapper: { flex: 1, justifyContent: 'flex-end', }, replyIconContainer: { flexDirection: 'row', alignItems: 'flex-start', justifyContent: 'flex-end', minWidth: 40, paddingTop: 2, paddingBottom: 10, flex: 1, }, replyText: { fontSize: 12, marginLeft: 2, marginTop: 2, color: theme.linkColor, }, commentedOn: { color: changeOpacity(theme.centerChannelColor, 0.65), marginBottom: 3, lineHeight: 21, }, displayNameContainerBotReplyWidth: { maxWidth: '50%', }, displayNameContainerLandscape: { maxWidth: '80%', }, displayNameContainerLandscapeBotReplyWidth: { maxWidth: '70%', }, }; });