diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx
index 506b38ce64..70cf86748a 100644
--- a/web/react/components/post_body.jsx
+++ b/web/react/components/post_body.jsx
@@ -6,13 +6,9 @@ import UserStore from '../stores/user_store.jsx';
import * as Utils from '../utils/utils.jsx';
import * as Emoji from '../utils/emoticons.jsx';
import Constants from '../utils/constants.jsx';
-const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES;
import * as TextFormatting from '../utils/text_formatting.jsx';
import twemoji from 'twemoji';
import PostBodyAdditionalContent from './post_body_additional_content.jsx';
-import YoutubeVideo from './youtube_video.jsx';
-
-import providers from './providers.json';
import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
@@ -31,19 +27,7 @@ class PostBody extends React.Component {
constructor(props) {
super(props);
- this.isImgLoading = false;
-
this.parseEmojis = this.parseEmojis.bind(this);
- this.createEmbed = this.createEmbed.bind(this);
- this.createImageEmbed = this.createImageEmbed.bind(this);
- this.loadImg = this.loadImg.bind(this);
-
- const linkData = Utils.extractLinks(this.props.post.message);
-
- this.state = {
- links: linkData,
- post: this.props.post
- };
}
getAllChildNodes(nodeIn) {
@@ -69,120 +53,10 @@ class PostBody extends React.Component {
});
}
- componentWillMount() {
- if (this.props.post.filenames.length === 0 && this.state.links && this.state.links.length > 0) {
- this.embed = this.createEmbed(this.state.links[0]);
- }
- }
-
componentDidMount() {
this.parseEmojis();
}
- componentDidUpdate() {
- this.parseEmojis();
- }
-
- componentWillReceiveProps(nextProps) {
- const linkData = Utils.extractLinks(nextProps.post.message);
- if (this.props.post.filenames.length === 0 && this.state.links && this.state.links.length > 0) {
- this.embed = this.createEmbed(linkData[0]);
- }
- this.setState({
- links: linkData
- });
- }
-
- createEmbed(link) {
- const post = this.state.post;
-
- if (!link) {
- if (post.type === 'oEmbed') {
- post.props.oEmbedLink = '';
- post.type = '';
- }
- return null;
- }
-
- const trimmedLink = link.trim();
-
- if (Utils.isFeatureEnabled(PreReleaseFeatures.EMBED_PREVIEW)) {
- const provider = this.getOembedProvider(trimmedLink);
- if (provider != null) {
- post.props.oEmbedLink = trimmedLink;
- post.type = 'oEmbed';
- this.setState({post, provider});
- return '';
- }
- }
-
- if (YoutubeVideo.isYoutubeLink(link)) {
- return (
-
- );
- }
-
- for (let i = 0; i < Constants.IMAGE_TYPES.length; i++) {
- const imageType = Constants.IMAGE_TYPES[i];
- const suffix = link.substring(link.length - (imageType.length + 1));
- if (suffix === '.' + imageType || suffix === '=' + imageType) {
- return this.createImageEmbed(link, this.state.imgLoaded);
- }
- }
-
- return null;
- }
-
- getOembedProvider(link) {
- for (let i = 0; i < providers.length; i++) {
- for (let j = 0; j < providers[i].patterns.length; j++) {
- if (link.match(providers[i].patterns[j])) {
- return providers[i];
- }
- }
- }
- return null;
- }
-
- loadImg(src) {
- if (this.isImgLoading) {
- return;
- }
-
- this.isImgLoading = true;
-
- const img = new Image();
- img.onload = (
- () => {
- this.embed = this.createImageEmbed(src, true);
- this.setState({imgLoaded: true});
- }
- );
- img.src = src;
- }
-
- createImageEmbed(link, isLoaded) {
- if (!isLoaded) {
- this.loadImg(link);
- return (
-
- );
- }
-
- return (
-
- );
- }
-
render() {
const {formatMessage} = this.props.intl;
const post = this.props.post;
@@ -295,6 +169,7 @@ class PostBody extends React.Component {
}
let message;
+ let additionalContent = null;
if (this.props.post.state === Constants.POST_DELETED) {
message = (
);
+
+ additionalContent = (
+
+ );
}
return (
@@ -323,12 +202,8 @@ class PostBody extends React.Component {
{loading}
{message}
-
{fileAttachmentHolder}
- {this.embed}
+ {additionalContent}
);
diff --git a/web/react/components/post_body_additional_content.jsx b/web/react/components/post_body_additional_content.jsx
index 4871eea4fa..a76c59fb37 100644
--- a/web/react/components/post_body_additional_content.jsx
+++ b/web/react/components/post_body_additional_content.jsx
@@ -3,72 +3,103 @@
import PostAttachmentList from './post_attachment_list.jsx';
import PostAttachmentOEmbed from './post_attachment_oembed.jsx';
+import PostImage from './post_image.jsx';
+import YoutubeVideo from './youtube_video.jsx';
+
+import Constants from '../utils/constants.jsx';
+import OEmbedProviders from './providers.json';
+import * as Utils from '../utils/utils.jsx';
export default class PostBodyAdditionalContent extends React.Component {
constructor(props) {
super(props);
this.getSlackAttachment = this.getSlackAttachment.bind(this);
- this.getOembedAttachment = this.getOembedAttachment.bind(this);
- this.getComponent = this.getComponent.bind(this);
+ this.getOEmbedProvider = this.getOEmbedProvider.bind(this);
}
- componentWillMount() {
- this.setState({type: this.props.post.type, shouldRender: Boolean(this.props.post.type)});
+ shouldComponentUpdate(nextProps) {
+ if (!Utils.areObjectsEqual(nextProps.post, this.props.post)) {
+ return true;
+ }
+
+ return false;
}
getSlackAttachment() {
- const attachments = this.props.post.props && this.props.post.props.attachments || [];
+ let attachments = [];
+ if (this.props.post.props && this.props.post.props.attachments) {
+ attachments = this.props.post.props.attachments;
+ }
+
return (
);
}
- getOembedAttachment() {
- const link = this.props.post.props && this.props.post.props.oEmbedLink || '';
- return (
-
- );
- }
-
- getComponent() {
- switch (this.props.post.type) {
- case 'slack_attachment':
- return this.getSlackAttachment();
- case 'oEmbed':
- return this.getOembedAttachment();
- default:
- return '';
- }
- }
-
- render() {
- let content = [];
-
- if (this.props.post.type) {
- const component = this.getComponent();
-
- if (component) {
- content = component;
+ getOEmbedProvider(link) {
+ for (let i = 0; i < OEmbedProviders.length; i++) {
+ for (let j = 0; j < OEmbedProviders[i].patterns.length; j++) {
+ if (link.match(OEmbedProviders[i].patterns[j])) {
+ return OEmbedProviders[i];
+ }
}
}
- return (
-
- {content}
-
- );
+ return null;
+ }
+
+ render() {
+ if (this.props.post.type === 'slack_attachment') {
+ return this.getSlackAttachment();
+ }
+
+ const link = Utils.extractLinks(this.props.post.message)[0];
+ if (!link) {
+ return null;
+ }
+
+ if (Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMBED_PREVIEW)) {
+ const provider = this.getOEmbedProvider(link);
+
+ if (provider) {
+ return (
+
+ );
+ }
+ }
+
+ if (YoutubeVideo.isYoutubeLink(link)) {
+ return (
+
+ );
+ }
+
+ for (let i = 0; i < Constants.IMAGE_TYPES.length; i++) {
+ const imageType = Constants.IMAGE_TYPES[i];
+ const suffix = link.substring(link.length - (imageType.length + 1));
+ if (suffix === '.' + imageType || suffix === '=' + imageType) {
+ return (
+
+ );
+ }
+ }
+
+ return null;
}
}
PostBodyAdditionalContent.propTypes = {
- post: React.PropTypes.object.isRequired,
- provider: React.PropTypes.object
+ post: React.PropTypes.object.isRequired
};
diff --git a/web/react/components/post_image.jsx b/web/react/components/post_image.jsx
new file mode 100644
index 0000000000..da4a25794a
--- /dev/null
+++ b/web/react/components/post_image.jsx
@@ -0,0 +1,81 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+export default class PostImageEmbed extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.handleLoadComplete = this.handleLoadComplete.bind(this);
+ this.handleLoadError = this.handleLoadError.bind(this);
+
+ this.state = {
+ loaded: false,
+ errored: false
+ };
+ }
+
+ componentWillMount() {
+ this.loadImg(this.props.link);
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.link !== this.props.link) {
+ this.setState({
+ loaded: false,
+ errored: false
+ });
+ }
+ }
+
+ componentDidUpdate(prevProps) {
+ if (!this.state.loaded && prevProps.link !== this.props.link) {
+ this.loadImg(this.props.link);
+ }
+ }
+
+ loadImg(src) {
+ const img = new Image();
+ img.onload = this.handleLoadComplete;
+ img.onerror = this.handleLoadError;
+ img.src = src;
+ }
+
+ handleLoadComplete() {
+ this.setState({
+ loaded: true
+ });
+ }
+
+ handleLoadError() {
+ this.setState({
+ errored: true,
+ loaded: true
+ });
+ }
+
+ render() {
+ if (this.state.errored) {
+ return null;
+ }
+
+ if (!this.state.loaded) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+ }
+}
+
+PostImageEmbed.propTypes = {
+ link: React.PropTypes.string.isRequired
+};