// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import PostAttachmentList from './post_attachment_list.jsx'; import PostAttachmentOpenGraph from './post_attachment_opengraph'; import PostImage from './post_image.jsx'; import YoutubeVideo from 'components/youtube_video'; import Constants from 'utils/constants.jsx'; import * as Utils from 'utils/utils.jsx'; import React from 'react'; import PropTypes from 'prop-types'; export default class PostBodyAdditionalContent extends React.PureComponent { static propTypes = { /** * The post to render the content of */ post: PropTypes.object.isRequired, /** * The post's message */ message: PropTypes.element.isRequired, /** * Set to collapse image and video previews */ previewCollapsed: PropTypes.string } static defaultProps = { previewCollapsed: '' } constructor(props) { super(props); this.getSlackAttachment = this.getSlackAttachment.bind(this); this.generateToggleableEmbed = this.generateToggleableEmbed.bind(this); this.generateStaticEmbed = this.generateStaticEmbed.bind(this); this.toggleEmbedVisibility = this.toggleEmbedVisibility.bind(this); this.isLinkToggleable = this.isLinkToggleable.bind(this); this.handleLinkLoadError = this.handleLinkLoadError.bind(this); this.handleLinkLoaded = this.handleLinkLoaded.bind(this); this.state = { embedVisible: props.previewCollapsed.startsWith('false'), link: Utils.extractFirstLink(props.post.message), linkLoadError: false, linkLoaded: false }; } componentWillReceiveProps(nextProps) { this.setState({ embedVisible: nextProps.previewCollapsed.startsWith('false'), link: Utils.extractFirstLink(nextProps.post.message) }); } toggleEmbedVisibility() { this.setState({embedVisible: !this.state.embedVisible}); } getSlackAttachment() { let attachments = []; if (this.props.post.props && this.props.post.props.attachments) { attachments = this.props.post.props.attachments; } return ( ); } isLinkImage(link) { const regex = /.+\/(.+\.(?:jpg|gif|bmp|png|jpeg))(?:\?.*)?$/i; const match = link.match(regex); if (match && match[1]) { return true; } return false; } isLinkToggleable() { const link = this.state.link; if (!link) { return false; } if (YoutubeVideo.isYoutubeLink(link)) { return true; } if (this.isLinkImage(link)) { return true; } return false; } handleLinkLoadError() { this.setState({ linkLoadError: true }); } handleLinkLoaded() { this.setState({ linkLoaded: true }); } generateToggleableEmbed() { const link = this.state.link; if (!link) { return null; } if (YoutubeVideo.isYoutubeLink(link)) { return ( ); } if (this.isLinkImage(link)) { return ( ); } return null; } generateStaticEmbed() { if (this.props.post.props && this.props.post.props.attachments) { return this.getSlackAttachment(); } const link = Utils.extractFirstLink(this.props.post.message); if (link && Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMBED_PREVIEW)) { return ( ); } return null; } render() { if (this.isLinkToggleable() && !this.state.linkLoadError) { // if message has only one line and starts with a link place toggle in this only line // else - place it in new line between message and embed const prependToggle = (/^\s*https?:\/\/.*$/).test(this.props.post.message); const toggle = ( ); const message = (
{this.props.message}
); const contents = [message]; if (this.state.linkLoaded) { if (prependToggle) { contents.unshift(toggle); } else { contents.push(toggle); } } if (this.state.embedVisible) { contents.push(
{this.generateToggleableEmbed()}
); } return (
{contents}
); } const staticEmbed = this.generateStaticEmbed(); if (staticEmbed) { return (
{this.props.message} {staticEmbed}
); } return this.props.message; } }