From 9f88923656bb11409c943fbe5e08005aa92ccaa0 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Tue, 2 Jul 2019 12:28:13 -0400 Subject: [PATCH] Place the new message indicator at the top of the screen (#2943) * Place the new message indicator at the top of the screen * Add unit tests for channel postVisibility reducer --- .../post_attachment_opengraph.js | 14 +++ .../post_body_additional_content.js | 5 +- app/components/post_list/post_list.js | 12 +- app/reducers/views/channel.js | 6 +- app/reducers/views/channel.test.js | 112 ++++++++++++++++++ 5 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 app/reducers/views/channel.test.js diff --git a/app/components/post_attachment_opengraph/post_attachment_opengraph.js b/app/components/post_attachment_opengraph/post_attachment_opengraph.js index d74293ea7..a495f159c 100644 --- a/app/components/post_attachment_opengraph/post_attachment_opengraph.js +++ b/app/components/post_attachment_opengraph/post_attachment_opengraph.js @@ -89,6 +89,7 @@ export default class PostAttachmentOpenGraph extends PureComponent { const bestImage = getNearestPoint(bestDimensions, data.images, 'width', 'height'); const imageUrl = bestImage.secure_url || bestImage.url; + let ogImage; if (imagesMetadata && imagesMetadata[imageUrl]) { ogImage = imagesMetadata[imageUrl]; @@ -98,6 +99,12 @@ export default class PostAttachmentOpenGraph extends PureComponent { ogImage = data.images.find((i) => i.url === imageUrl || i.secure_url === imageUrl); } + // Fallback when the ogImage does not have dimensions but there is a metaImage defined + const metaImages = imagesMetadata ? Object.values(imagesMetadata) : null; + if ((!ogImage?.width || !ogImage?.height) && metaImages?.length) { + ogImage = metaImages[0]; + } + let dimensions = bestDimensions; if (ogImage?.width && ogImage?.height) { dimensions = calculateDimensions(ogImage.height, ogImage.width, this.getViewPostWidth()); @@ -139,9 +146,16 @@ export default class PostAttachmentOpenGraph extends PureComponent { ogImage = openGraphData.images.find((i) => i.url === openGraphImageUrl || i.secure_url === openGraphImageUrl); } + // Fallback when the ogImage does not have dimensions but there is a metaImage defined + const metaImages = imagesMetadata ? Object.values(imagesMetadata) : null; + if ((!ogImage?.width || !ogImage?.height) && metaImages?.length) { + ogImage = metaImages[0]; + } + if (ogImage?.width && ogImage?.height) { this.setImageSize(imageUrl, ogImage.width, ogImage.height); } else { + // if we get to this point there can be a scroll pop Image.getSize(imageUrl, (width, height) => { this.setImageSize(imageUrl, width, height); }, () => null); 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 9d957b074..5358c7695 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 @@ -182,11 +182,12 @@ export default class PostBodyAdditionalContent extends PureComponent { }; generateStaticEmbed = (isYouTube, isImage) => { - if (isYouTube || isImage) { + const {isReplyPost, link, metadata, navigator, openGraphData, showLinkPreviews, theme} = this.props; + + if (isYouTube || (isImage && !openGraphData)) { return null; } - const {isReplyPost, link, metadata, navigator, openGraphData, showLinkPreviews, theme} = this.props; const attachments = this.getMessageAttachment(); if (attachments) { return attachments; diff --git a/app/components/post_list/post_list.js b/app/components/post_list/post_list.js index ddbae2381..8634cf44e 100644 --- a/app/components/post_list/post_list.js +++ b/app/components/post_list/post_list.js @@ -294,11 +294,13 @@ export default class PostList extends PureComponent { this.props.initialIndex > 0 && !this.hasDoneInitialScroll ) { - this.flatListRef.current.scrollToIndex({ - animated: false, - index: this.props.initialIndex, - viewOffset: 50, - viewPosition: 0.5, + requestAnimationFrame(() => { + this.flatListRef.current.scrollToIndex({ + animated: false, + index: this.props.initialIndex, + viewOffset: 0, + viewPosition: 1, // 0 is at bottom + }); }); this.hasDoneInitialScroll = true; } diff --git a/app/reducers/views/channel.js b/app/reducers/views/channel.js index 87fd7f930..3ffce2343 100644 --- a/app/reducers/views/channel.js +++ b/app/reducers/views/channel.js @@ -266,7 +266,11 @@ function postVisibility(state = {}, action) { } case ViewTypes.INCREASE_POST_VISIBILITY: { const nextState = {...state}; - nextState[action.data] += action.amount; + if (nextState[action.data]) { + nextState[action.data] += action.amount; + } else { + nextState[action.data] = action.amount; + } return nextState; } case ViewTypes.RECEIVED_FOCUSED_POST: { diff --git a/app/reducers/views/channel.test.js b/app/reducers/views/channel.test.js new file mode 100644 index 000000000..e5fa05ff3 --- /dev/null +++ b/app/reducers/views/channel.test.js @@ -0,0 +1,112 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import channelReducer from './channel'; +import {ViewTypes} from 'app/constants'; + +describe('Reducers.channel', () => { + const initialState = { + displayName: '', + drafts: {}, + loading: false, + refreshing: false, + postCountInChannel: {}, + postVisibility: {}, + loadingPosts: {}, + lastGetPosts: {}, + retryFailed: false, + loadMorePostsVisible: true, + lastChannelViewTime: {}, + keepChannelIdAsUnread: null, + }; + + test('Initial state', () => { + const nextState = channelReducer( + { + displayName: '', + drafts: {}, + loading: false, + refreshing: false, + postCountInChannel: {}, + postVisibility: {}, + loadingPosts: {}, + lastGetPosts: {}, + retryFailed: false, + loadMorePostsVisible: true, + lastChannelViewTime: {}, + keepChannelIdAsUnread: null, + }, + {} + ); + + expect(nextState).toEqual(initialState); + }); + + test('should set the postVisibility amount for a channel', () => { + const channelId = 'channel_id'; + const amount = 15; + const nextState = channelReducer( + { + displayName: '', + drafts: {}, + loading: false, + refreshing: false, + postCountInChannel: {}, + postVisibility: {}, + loadingPosts: {}, + lastGetPosts: {}, + retryFailed: false, + loadMorePostsVisible: true, + lastChannelViewTime: {}, + keepChannelIdAsUnread: null, + }, + { + type: ViewTypes.INCREASE_POST_VISIBILITY, + data: channelId, + amount, + } + ); + + expect(nextState).toEqual({ + ...initialState, + postVisibility: { + [channelId]: amount, + }, + }); + }); + + test('should increase the postVisibility amount for a channel', () => { + const channelId = 'channel_id'; + const amount = 15; + const nextState = channelReducer( + { + displayName: '', + drafts: {}, + loading: false, + refreshing: false, + postCountInChannel: {}, + postVisibility: { + [channelId]: amount, + }, + loadingPosts: {}, + lastGetPosts: {}, + retryFailed: false, + loadMorePostsVisible: true, + lastChannelViewTime: {}, + keepChannelIdAsUnread: null, + }, + { + type: ViewTypes.INCREASE_POST_VISIBILITY, + data: channelId, + amount, + } + ); + + expect(nextState).toEqual({ + ...initialState, + postVisibility: { + [channelId]: 2 * amount, + }, + }); + }); +});