diff --git a/app/components/post_body_additional_content/index.js b/app/components/post_body_additional_content/index.js
index 019775ba4..b2ab09265 100644
--- a/app/components/post_body_additional_content/index.js
+++ b/app/components/post_body_additional_content/index.js
@@ -7,7 +7,7 @@ import {bindActionCreators} from 'redux';
import {getRedirectLocation} from 'mattermost-redux/actions/general';
import {Preferences} from 'mattermost-redux/constants';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
-import {getOpenGraphMetadataForUrl} from 'mattermost-redux/selectors/entities/posts';
+import {getOpenGraphMetadataForUrl, getExpandedLink} from 'mattermost-redux/selectors/entities/posts';
import {getBool, getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {ViewTypes} from 'app/constants';
@@ -46,6 +46,10 @@ function makeMapStateToProps() {
return function mapStateToProps(state, ownProps) {
const config = getConfig(state);
const link = getFirstLink(ownProps.message);
+ let expandedLink;
+ if (link) {
+ expandedLink = getExpandedLink(state, link);
+ }
// Link previews used to be an advanced settings until server version 4.4 when it was changed to be a display setting.
// We are checking both here until we bump the server requirement for the mobile apps.
@@ -64,6 +68,7 @@ function makeMapStateToProps() {
...getDimensions(state),
googleDeveloperKey: config.GoogleDeveloperKey,
link,
+ expandedLink,
openGraphData,
showLinkPreviews: previewsEnabled && config.EnableLinkPreviews === 'true' && !removeLinkPreview,
theme: getTheme(state),
diff --git a/app/components/post_body_additional_content/post_body_additional_content.js b/app/components/post_body_additional_content/post_body_additional_content.js
index 9cf156791..1108de8e7 100644
--- a/app/components/post_body_additional_content/post_body_additional_content.js
+++ b/app/components/post_body_additional_content/post_body_additional_content.js
@@ -38,23 +38,24 @@ export default class PostBodyAdditionalContent extends PureComponent {
actions: PropTypes.shape({
getRedirectLocation: PropTypes.func.isRequired,
}).isRequired,
- baseTextStyle: CustomPropTypes.Style,
- blockStyles: PropTypes.object,
- googleDeveloperKey: PropTypes.string,
+ link: PropTypes.string.isRequired,
+ message: PropTypes.string.isRequired,
deviceHeight: PropTypes.number.isRequired,
deviceWidth: PropTypes.number.isRequired,
- metadata: PropTypes.object,
- isReplyPost: PropTypes.bool,
- link: PropTypes.string,
- message: PropTypes.string.isRequired,
- onHashtagPress: PropTypes.func,
- onPermalinkPress: PropTypes.func,
- openGraphData: PropTypes.object,
postId: PropTypes.string.isRequired,
postProps: PropTypes.object.isRequired,
showLinkPreviews: PropTypes.bool.isRequired,
- textStyles: PropTypes.object,
theme: PropTypes.object.isRequired,
+ baseTextStyle: CustomPropTypes.Style,
+ blockStyles: PropTypes.object,
+ googleDeveloperKey: PropTypes.string,
+ metadata: PropTypes.object,
+ isReplyPost: PropTypes.bool,
+ onHashtagPress: PropTypes.func,
+ onPermalinkPress: PropTypes.func,
+ openGraphData: PropTypes.object,
+ textStyles: PropTypes.object,
+ expandedLink: PropTypes.string,
};
static contextTypes = {
@@ -79,7 +80,6 @@ export default class PostBodyAdditionalContent extends PureComponent {
this.state = {
linkLoadError: false,
linkLoaded: false,
- shortenedLink: null,
...dimensions,
};
@@ -89,12 +89,12 @@ export default class PostBodyAdditionalContent extends PureComponent {
componentDidMount() {
this.mounted = true;
- this.load(this.props);
+ this.load();
}
componentDidUpdate(prevProps) {
if (prevProps.link !== this.props.link) {
- this.load(this.props);
+ this.load(true);
}
}
@@ -116,33 +116,30 @@ export default class PostBodyAdditionalContent extends PureComponent {
return false;
};
- load = async (props) => {
- const {link} = props;
+ getImageUrl = (link) => {
+ let imageUrl;
+
+ if (this.isImage()) {
+ imageUrl = link;
+ } else if (isYoutubeLink(link)) {
+ const videoId = getYouTubeVideoId(link);
+ imageUrl = `https://i.ytimg.com/vi/${videoId}/hqdefault.jpg`;
+ }
+
+ return imageUrl;
+ }
+
+ load = (linkChanged = false) => {
+ const {link, expandedLink, actions} = this.props;
+
if (link) {
- let imageUrl;
- if (this.isImage()) {
- imageUrl = link;
- } else if (isYoutubeLink(link)) {
- const videoId = getYouTubeVideoId(link);
- imageUrl = `https://i.ytimg.com/vi/${videoId}/hqdefault.jpg`;
- } else {
- const {data} = await this.props.actions.getRedirectLocation(link);
+ let imageUrl = this.getImageUrl(link);
- let shortenedLink;
- if (data && data.location) {
- shortenedLink = data.location;
- }
-
- if (shortenedLink) {
- if (this.isImage(shortenedLink)) {
- imageUrl = shortenedLink;
- } else if (isYoutubeLink(shortenedLink)) {
- const videoId = getYouTubeVideoId(shortenedLink);
- imageUrl = `https://i.ytimg.com/vi/${videoId}/hqdefault.jpg`;
- }
- if (this.mounted) {
- this.setState({shortenedLink});
- }
+ if (!imageUrl) {
+ if (!expandedLink || linkChanged) {
+ actions.getRedirectLocation(link);
+ } else {
+ imageUrl = this.getImageUrl(expandedLink);
}
}
@@ -215,9 +212,9 @@ export default class PostBodyAdditionalContent extends PureComponent {
generateToggleableEmbed = (isImage, isYouTube) => {
let {link} = this.props;
- const {shortenedLink} = this.state;
- if (shortenedLink) {
- link = shortenedLink;
+ const {expandedLink} = this.props;
+ if (expandedLink) {
+ link = expandedLink;
}
const {width, height, uri} = this.state;
@@ -407,10 +404,10 @@ export default class PostBodyAdditionalContent extends PureComponent {
};
handlePreviewImage = (imageRef) => {
- const {shortenedLink} = this.state;
let {link} = this.props;
- if (shortenedLink) {
- link = shortenedLink;
+ const {expandedLink} = this.props;
+ if (expandedLink) {
+ link = expandedLink;
}
const {
originalHeight,
@@ -485,10 +482,10 @@ export default class PostBodyAdditionalContent extends PureComponent {
render() {
let {link} = this.props;
- const {openGraphData, postProps} = this.props;
- const {linkLoadError, shortenedLink} = this.state;
- if (shortenedLink) {
- link = shortenedLink;
+ const {openGraphData, postProps, expandedLink} = this.props;
+ const {linkLoadError} = this.state;
+ if (expandedLink) {
+ link = expandedLink;
}
const {attachments} = postProps;
diff --git a/app/components/post_body_additional_content/post_body_additional_content.test.js b/app/components/post_body_additional_content/post_body_additional_content.test.js
new file mode 100644
index 000000000..64bc6d3b0
--- /dev/null
+++ b/app/components/post_body_additional_content/post_body_additional_content.test.js
@@ -0,0 +1,52 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+
+import {Preferences} from 'mattermost-redux/constants';
+
+import {shallowWithIntl} from 'test/intl-test-helper';
+
+import PostBodyAdditionalContent from './post_body_additional_content.js';
+
+describe('PostBodyAdditionalContent', () => {
+ const baseProps = {
+ actions: {
+ getRedirectLocation: jest.fn(),
+ },
+ link: 'http://short.ened/123',
+ deviceHeight: 100,
+ deviceWidth: 100,
+ message: 'message',
+ postId: 'post-id',
+ postProps: {},
+ showLinkPreviews: false,
+ theme: Preferences.THEMES.default,
+ };
+
+ test('should call getRedirectLocation only if expandedLink has not been set', () => {
+ const wrapper = shallowWithIntl();
+ const instance = wrapper.instance();
+
+ expect(baseProps.actions.getRedirectLocation).toHaveBeenCalledTimes(1);
+
+ wrapper.setProps({expandedLink: 'http://expanded.com/123'});
+ instance.load();
+ expect(baseProps.actions.getRedirectLocation).toHaveBeenCalledTimes(1);
+ });
+
+ test('should call getRedirectLocation if expandedLink is set but link changed', () => {
+ const props = {
+ ...baseProps,
+ expandedLink: 'http://expanded.com/123',
+ };
+ const wrapper = shallowWithIntl();
+ const instance = wrapper.instance();
+
+ expect(baseProps.actions.getRedirectLocation).toHaveBeenCalledTimes(0);
+
+ wrapper.setProps({link: `${baseProps.link}/456`});
+ instance.load();
+ expect(baseProps.actions.getRedirectLocation).toHaveBeenCalledTimes(1);
+ });
+});