// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import UserProfile from './user_profile.jsx'; import FileAttachmentListContainer from './file_attachment_list_container.jsx'; import PendingPostOptions from 'components/post_view/components/pending_post_options.jsx'; import PostMessageContainer from 'components/post_view/components/post_message_container.jsx'; import ProfilePicture from 'components/profile_picture.jsx'; import ReactionListContainer from 'components/post_view/components/reaction_list_container.jsx'; import RhsDropdown from 'components/rhs_dropdown.jsx'; import * as GlobalActions from 'actions/global_actions.jsx'; import {flagPost, unflagPost, pinPost, unpinPost, addReaction} from 'actions/post_actions.jsx'; import TeamStore from 'stores/team_store.jsx'; import * as Utils from 'utils/utils.jsx'; import * as PostUtils from 'utils/post_utils.jsx'; import Constants from 'utils/constants.jsx'; import DelayedAction from 'utils/delayed_action.jsx'; import {Tooltip, OverlayTrigger, Overlay} from 'react-bootstrap'; import {FormattedMessage} from 'react-intl'; import EmojiPicker from 'components/emoji_picker/emoji_picker.jsx'; import ReactDOM from 'react-dom'; import loadingGif from 'images/load.gif'; import React from 'react'; import {Link} from 'react-router/es6'; export default class RhsComment extends React.Component { constructor(props) { super(props); this.handlePermalink = this.handlePermalink.bind(this); this.removePost = this.removePost.bind(this); this.flagPost = this.flagPost.bind(this); this.unflagPost = this.unflagPost.bind(this); this.pinPost = this.pinPost.bind(this); this.unpinPost = this.unpinPost.bind(this); this.reactEmojiClick = this.reactEmojiClick.bind(this); this.emojiPickerClick = this.emojiPickerClick.bind(this); this.canEdit = false; this.canDelete = false; this.editDisableAction = new DelayedAction(this.handleEditDisable); this.state = { currentTeamDisplayName: TeamStore.getCurrent().name, width: '', height: '', showReactEmojiPicker: false, reactPickerOffset: 15 }; } componentDidMount() { window.addEventListener('resize', () => { Utils.updateWindowDimensions(this); }); } componentWillUnmount() { window.removeEventListener('resize', () => { Utils.updateWindowDimensions(this); }); } handlePermalink(e) { e.preventDefault(); GlobalActions.showGetPostLinkModal(this.props.post); } handleEditDisable() { this.canEdit = false; } removePost() { GlobalActions.emitRemovePost(this.props.post); } createRemovePostButton() { return ( {'×'} ); } shouldComponentUpdate(nextProps, nextState) { if (nextProps.status !== this.props.status) { return true; } if (nextProps.isBusy !== this.props.isBusy) { return true; } if (nextProps.compactDisplay !== this.props.compactDisplay) { return true; } if (nextProps.useMilitaryTime !== this.props.useMilitaryTime) { return true; } if (nextProps.isFlagged !== this.props.isFlagged) { return true; } if (!Utils.areObjectsEqual(nextProps.post, this.props.post)) { return true; } if (!Utils.areObjectsEqual(nextProps.currentUser, this.props.currentUser)) { return true; } if (this.state.showReactEmojiPicker !== nextState.showReactEmojiPicker) { return true; } return false; } flagPost(e) { e.preventDefault(); flagPost(this.props.post.id); } unflagPost(e) { e.preventDefault(); unflagPost(this.props.post.id); } pinPost(e) { e.preventDefault(); pinPost(this.props.post.channel_id, this.props.post.id); } unpinPost(e) { e.preventDefault(); unpinPost(this.props.post.channel_id, this.props.post.id); } createDropdown() { const post = this.props.post; if (post.state === Constants.POST_FAILED || post.state === Constants.POST_LOADING) { return ''; } this.canDelete = PostUtils.canDeletePost(post); this.canEdit = PostUtils.canEditPost(post, this.editDisableAction); var dropdownContents = []; if (Utils.isMobile()) { if (this.props.isFlagged) { dropdownContents.push(
  • ); } else { dropdownContents.push(
  • ); } } dropdownContents.push(
  • ); if (post.is_pinned) { dropdownContents.push(
  • ); } else { dropdownContents.push(
  • ); } if (this.canDelete) { dropdownContents.push(
  • { e.preventDefault(); GlobalActions.showDeletePostModal(post, 0); }} >
  • ); } if (this.canEdit) { dropdownContents.push(
  • ); } if (dropdownContents.length === 0) { return ''; } return ( ); } timeTag(post, timeOptions) { return ( ); } renderTimeTag(post, timeOptions) { return Utils.isMobile() ? this.timeTag(post, timeOptions) : ( {this.timeTag(post, timeOptions)} ); } emojiPickerClick() { // set default offset let reactOffset = 15; const reactSelectorHeight = 360; const reactionIconY = ReactDOM.findDOMNode(this).getBoundingClientRect().top; const rhsMinHeight = 700; const spaceAvail = rhsMinHeight - reactionIconY; if (spaceAvail < reactSelectorHeight) { reactOffset = (spaceAvail - reactSelectorHeight); } this.setState({showReactEmojiPicker: !this.state.showReactEmojiPicker, reactPickerOffset: reactOffset}); } reactEmojiClick(emoji) { this.setState({showReactEmojiPicker: false}); const emojiName = emoji.name || emoji.aliases[0]; addReaction(this.props.post.channel_id, this.props.post.id, emojiName); } render() { const post = this.props.post; const flagIcon = Constants.FLAG_ICON_SVG; const mattermostLogo = Constants.MATTERMOST_ICON_SVG; const isSystemMessage = PostUtils.isSystemMessage(post); let canReact = false; if (post.state !== Constants.POST_FAILED && post.state !== Constants.POST_LOADING && !Utils.isPostEphemeral(post) && Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMOJI_PICKER_PREVIEW)) { canReact = true; } var currentUserCss = ''; if (this.props.currentUser.id === post.user_id) { currentUserCss = 'current--user'; } var timestamp = this.props.currentUser.last_picture_update; let status = this.props.status; if (post.props && post.props.from_webhook === 'true') { status = null; } let botIndicator; let userProfile = ( ); if (post.props && post.props.from_webhook) { if (post.props.override_username && global.window.mm_config.EnablePostUsernameOverride === 'true') { userProfile = ( ); } else { userProfile = ( ); } botIndicator =
  • {'BOT'}
  • ; } else if (PostUtils.isSystemMessage(post)) { userProfile = ( } overwriteImage={Constants.SYSTEM_MESSAGE_PROFILE_IMAGE} disablePopover={true} /> ); } let loading; let postClass = ''; if (post.state === Constants.POST_FAILED) { postClass += ' post-fail'; loading = ; } else if (post.state === Constants.POST_LOADING) { postClass += ' post-waiting'; loading = ( ); } if (PostUtils.isEdited(this.props.post)) { postClass += ' post--edited'; } let systemMessageClass = ''; if (isSystemMessage) { systemMessageClass = 'post--system'; } let profilePic = ( ); if (post.props && post.props.from_webhook) { profilePic = ( ); } if (PostUtils.isSystemMessage(post)) { profilePic = ( ); } let compactClass = ''; if (this.props.compactDisplay) { compactClass = 'post--compact'; if (post.props && post.props.from_webhook) { profilePic = ( ); } else { profilePic = ( ); } } const profilePicContainer = (
    {profilePic}
    ); let fileAttachment = null; if (post.file_ids && post.file_ids.length > 0) { fileAttachment = ( ); } let flag; let flagFunc; let flagVisible = ''; let flagTooltip = ( ); if (this.props.isFlagged) { flagVisible = 'visible'; flag = ( ); flagFunc = this.unflagPost; flagTooltip = ( ); } else { flag = ( ); flagFunc = this.flagPost; } let flagTrigger; if (!Utils.isPostEphemeral(post)) { flagTrigger = ( {flag} ); } let react; let reactOverlay; if (canReact) { react = ( ); reactOverlay = ( this.setState({showReactEmojiPicker: false})} target={() => ReactDOM.findDOMNode(this.refs['rhs_reacticon_' + post.id])} > ); } let options; if (Utils.isPostEphemeral(post)) { options = (
  • {this.createRemovePostButton()}
  • ); } else if (!PostUtils.isSystemMessage(post)) { options = (
  • {reactOverlay} {this.createDropdown()} {react}
  • ); } let pinnedBadge; if (post.is_pinned) { pinnedBadge = ( ); } const timeOptions = { hour: '2-digit', minute: '2-digit', hour12: !this.props.useMilitaryTime }; return (
    {profilePicContainer}
    • {userProfile}
    • {botIndicator}
    • {this.renderTimeTag(post, timeOptions)} {pinnedBadge} {flagTrigger}
    • {options}
    {loading}
    {fileAttachment}
    ); } } RhsComment.propTypes = { post: React.PropTypes.object, user: React.PropTypes.object.isRequired, currentUser: React.PropTypes.object.isRequired, compactDisplay: React.PropTypes.bool, useMilitaryTime: React.PropTypes.bool.isRequired, isFlagged: React.PropTypes.bool, status: React.PropTypes.string, isBusy: React.PropTypes.bool };