From 5158d3a44671f6faf2474b812987a7d301db7a2d Mon Sep 17 00:00:00 2001 From: VeraLyu Date: Sat, 17 Jun 2017 01:12:22 +0800 Subject: Remove fake img preview before loaded (#5854) Remove fake img preview and collapse toggle before it is loaded, only show img and toggle after it is fully loaded. Fix markdown img size and add scroll down behaviour. --- .../components/post_body_additional_content.jsx | 30 ++++++++++++++----- .../components/post_view/components/post_image.jsx | 34 ++++++++++++---------- .../components/post_view/components/post_list.jsx | 5 +++- webapp/components/youtube_video.jsx | 26 ++++++++++++----- webapp/stores/scroll_store.jsx | 24 +++++++++++++++ webapp/utils/markdown.jsx | 3 ++ 6 files changed, 90 insertions(+), 32 deletions(-) create mode 100644 webapp/stores/scroll_store.jsx (limited to 'webapp') diff --git a/webapp/components/post_view/components/post_body_additional_content.jsx b/webapp/components/post_view/components/post_body_additional_content.jsx index 130031233..180681100 100644 --- a/webapp/components/post_view/components/post_body_additional_content.jsx +++ b/webapp/components/post_view/components/post_body_additional_content.jsx @@ -23,19 +23,20 @@ export default class PostBodyAdditionalContent extends React.Component { 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 + linkLoadError: false, + linkLoaded: false }; } componentWillReceiveProps(nextProps) { this.setState({ embedVisible: nextProps.previewCollapsed.startsWith('false'), - link: Utils.extractFirstLink(nextProps.post.message), - linkLoadError: false + link: Utils.extractFirstLink(nextProps.post.message) }); } @@ -52,6 +53,9 @@ export default class PostBodyAdditionalContent extends React.Component { if (nextState.linkLoadError !== this.state.linkLoadError) { return true; } + if (nextState.linkLoaded !== this.state.linkLoaded) { + return true; + } return false; } @@ -105,6 +109,12 @@ export default class PostBodyAdditionalContent extends React.Component { }); } + handleLinkLoaded() { + this.setState({ + linkLoaded: true + }); + } + generateToggleableEmbed() { const link = this.state.link; if (!link) { @@ -127,6 +137,8 @@ export default class PostBodyAdditionalContent extends React.Component { channelId={this.props.post.channel_id} link={link} onLinkLoadError={this.handleLinkLoadError} + onLinkLoaded={this.handleLinkLoaded} + childComponentDidUpdateFunction={this.props.childComponentDidUpdateFunction} /> ); } @@ -174,11 +186,13 @@ export default class PostBodyAdditionalContent extends React.Component { ); - let contents; - if (prependToggle) { - contents = [toggle, message]; - } else { - contents = [message, toggle]; + const contents = [message]; + if (this.state.linkLoaded) { + if (prependToggle) { + contents.unshift(toggle); + } else { + contents.push(toggle); + } } if (this.state.embedVisible) { diff --git a/webapp/components/post_view/components/post_image.jsx b/webapp/components/post_view/components/post_image.jsx index 2bdc5efc0..1268c9df2 100644 --- a/webapp/components/post_view/components/post_image.jsx +++ b/webapp/components/post_view/components/post_image.jsx @@ -32,6 +32,9 @@ export default class PostImageEmbed extends React.Component { } componentDidUpdate(prevProps) { + if (this.state.loaded && this.props.childComponentDidUpdateFunction) { + this.props.childComponentDidUpdateFunction(); + } if (!this.state.loaded && prevProps.link !== this.props.link) { this.loadImg(this.props.link); } @@ -46,8 +49,12 @@ export default class PostImageEmbed extends React.Component { handleLoadComplete() { this.setState({ - loaded: true + loaded: true, + errored: false }); + if (this.props.onLinkLoaded) { + this.props.onLinkLoaded(); + } } handleLoadError() { @@ -61,29 +68,26 @@ export default class PostImageEmbed extends React.Component { } render() { - if (this.state.errored) { + if (this.state.errored || !this.state.loaded) { return null; } - if (!this.state.loaded) { - return ( + return ( +
- ); - } - - return ( - +
); } } PostImageEmbed.propTypes = { link: PropTypes.string.isRequired, - onLinkLoadError: PropTypes.func + onLinkLoadError: PropTypes.func, + onLinkLoaded: PropTypes.func, + childComponentDidUpdateFunction: PropTypes.func }; diff --git a/webapp/components/post_view/components/post_list.jsx b/webapp/components/post_view/components/post_list.jsx index 403e26f84..ec3c8dc6a 100644 --- a/webapp/components/post_view/components/post_list.jsx +++ b/webapp/components/post_view/components/post_list.jsx @@ -23,7 +23,7 @@ const ScrollTypes = Constants.ScrollTypes; import PostStore from 'stores/post_store.jsx'; import PreferenceStore from 'stores/preference_store.jsx'; - +import ScrollStore from 'stores/scroll_store.jsx'; import {FormattedDate, FormattedMessage} from 'react-intl'; import PropTypes from 'prop-types'; @@ -49,6 +49,7 @@ export default class PostList extends React.Component { this.scrollToBottomAnimated = this.scrollToBottomAnimated.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.childComponentDidUpdate = this.childComponentDidUpdate.bind(this); + this.checkAndUpdateScrolling = this.checkAndUpdateScrolling.bind(this); this.jumpToPostNode = null; this.wasAtBottom = true; @@ -536,6 +537,7 @@ export default class PostList extends React.Component { window.addEventListener('keydown', this.handleKeyDown); PostStore.addPostDraftChangeListener(this.props.channelId, this.handlePostDraftChange); + ScrollStore.addPostScrollListener(this.checkAndUpdateScrolling); } handlePostDraftChange = (draft) => { @@ -550,6 +552,7 @@ export default class PostList extends React.Component { window.cancelAnimationFrame(this.animationFrameId); window.removeEventListener('resize', this.handleResize); window.removeEventListener('keydown', this.handleKeyDown); + ScrollStore.removePostScrollListener(this.checkAndUpdateScrolling); this.scrollStopAction.cancel(); PostStore.removePostDraftChangeListener(this.props.channelId, this.handlePostDraftChange); diff --git a/webapp/components/youtube_video.jsx b/webapp/components/youtube_video.jsx index 0127fcb88..49f490bda 100644 --- a/webapp/components/youtube_video.jsx +++ b/webapp/components/youtube_video.jsx @@ -156,7 +156,13 @@ export default class YoutubeVideo extends React.Component { render() { if (!this.state.loaded) { - return
; + return ( +
+
+
+ ); } let header; @@ -217,13 +223,17 @@ export default class YoutubeVideo extends React.Component { } return ( -
- {header} -
- {content} +
+
+ {header} +
+ {content} +
); diff --git a/webapp/stores/scroll_store.jsx b/webapp/stores/scroll_store.jsx new file mode 100644 index 000000000..03a5f4e08 --- /dev/null +++ b/webapp/stores/scroll_store.jsx @@ -0,0 +1,24 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import EventEmitter from 'events'; + +const UPDATE_POST_SCROLL_EVENT = 'update_post_scroll'; + +class ScrollStoreClass extends EventEmitter { + emitPostScroll() { + this.emit(UPDATE_POST_SCROLL_EVENT); + } + + addPostScrollListener(callback) { + this.on(UPDATE_POST_SCROLL_EVENT, callback); + } + + removePostScrollLisener(callback) { + this.removeListener(UPDATE_POST_SCROLL_EVENT, callback); + } +} + +var ScrollStore = new ScrollStoreClass(); +export default ScrollStore; + diff --git a/webapp/utils/markdown.jsx b/webapp/utils/markdown.jsx index 0d9e977d7..f47c45d10 100644 --- a/webapp/utils/markdown.jsx +++ b/webapp/utils/markdown.jsx @@ -7,6 +7,8 @@ import * as SyntaxHighlighting from './syntax_highlighting.jsx'; import marked from 'marked'; import katex from 'katex'; +import ScrollStore from 'stores/scroll_store.jsx'; + function markdownImageLoaded(image) { if (image.hasAttribute('height') && image.attributes.height.value !== 'auto') { const maxHeight = parseInt(global.getComputedStyle(image).maxHeight, 10); @@ -20,6 +22,7 @@ function markdownImageLoaded(image) { } else { image.style.height = 'auto'; } + ScrollStore.emitPostScroll(); } global.markdownImageLoaded = markdownImageLoaded; -- cgit v1.2.3-1-g7c22