summaryrefslogtreecommitdiffstats
path: root/web/react/components/posts_view.jsx
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2015-11-18 17:29:06 -0500
committerChristopher Speller <crspeller@gmail.com>2015-11-23 09:53:15 -0500
commit9e8cd937908d5d2e730e94f761d6533eb2d95e28 (patch)
treefb6324a5896da7123b76854e7eb504c239113824 /web/react/components/posts_view.jsx
parent5ee226d7f92d9408736b0e2a9ff105eb6f520a19 (diff)
downloadchat-9e8cd937908d5d2e730e94f761d6533eb2d95e28.tar.gz
chat-9e8cd937908d5d2e730e94f761d6533eb2d95e28.tar.bz2
chat-9e8cd937908d5d2e730e94f761d6533eb2d95e28.zip
Implementing Permalinks and jumping to post from search. Performance
improvements.
Diffstat (limited to 'web/react/components/posts_view.jsx')
-rw-r--r--web/react/components/posts_view.jsx91
1 files changed, 65 insertions, 26 deletions
diff --git a/web/react/components/posts_view.jsx b/web/react/components/posts_view.jsx
index 5b36ecbc5..5e374b877 100644
--- a/web/react/components/posts_view.jsx
+++ b/web/react/components/posts_view.jsx
@@ -2,6 +2,7 @@
// See License.txt for license information.
import UserStore from '../stores/user_store.jsx';
+import * as EventHelpers from '../dispatcher/event_helpers.jsx';
import * as Utils from '../utils/utils.jsx';
import Post from './post.jsx';
import Constants from '../utils/constants.jsx';
@@ -13,6 +14,7 @@ export default class PostsView extends React.Component {
this.handleScroll = this.handleScroll.bind(this);
this.isAtBottom = this.isAtBottom.bind(this);
this.loadMorePostsTop = this.loadMorePostsTop.bind(this);
+ this.loadMorePostsBottom = this.loadMorePostsBottom.bind(this);
this.createPosts = this.createPosts.bind(this);
this.updateScrolling = this.updateScrolling.bind(this);
this.handleResize = this.handleResize.bind(this);
@@ -27,12 +29,15 @@ export default class PostsView extends React.Component {
static get SCROLL_TYPE_BOTTOM() {
return 2;
}
- static get SIDEBAR_OPEN() {
+ static get SCROLL_TYPE_SIDEBAR_OPEN() {
return 3;
}
static get SCROLL_TYPE_NEW_MESSAGE() {
return 4;
}
+ static get SCROLL_TYPE_POST() {
+ return 5;
+ }
isAtBottom() {
return ((this.refs.postlist.scrollHeight - this.refs.postlist.scrollTop) === this.refs.postlist.clientHeight);
}
@@ -47,15 +52,22 @@ export default class PostsView extends React.Component {
}
}
this.wasAtBottom = this.isAtBottom();
+ if (!this.jumpToPostNode && childNodes.length > 0) {
+ this.jumpToPostNode = childNodes[childNodes.length - 1];
+ }
// --- --------
this.props.postViewScrolled(this.isAtBottom());
this.prevScrollHeight = this.refs.postlist.scrollHeight;
+ this.prevOffsetTop = this.jumpToPostNode.offsetTop;
}
loadMorePostsTop() {
this.props.loadMorePostsTopClicked();
}
+ loadMorePostsBottom() {
+ this.props.loadMorePostsBottomClicked();
+ }
createPosts(posts, order) {
const postCtls = [];
let previousPostDay = new Date(0);
@@ -63,12 +75,7 @@ export default class PostsView extends React.Component {
let renderedLastViewed = false;
- let numToDisplay = this.props.numPostsToDisplay;
- if (order.length - 1 < numToDisplay) {
- numToDisplay = order.length - 1;
- }
-
- for (let i = numToDisplay; i >= 0; i--) {
+ for (let i = order.length - 1; i >= 0; i--) {
const post = posts[order[i]];
const parentPost = posts[post.parent_id];
const prevPost = posts[order[i + 1]];
@@ -113,6 +120,8 @@ export default class PostsView extends React.Component {
const keyPrefix = post.id ? post.id : i;
+ const shouldHighlight = this.props.postsToHighlight && this.props.postsToHighlight.hasOwnProperty(post.id);
+
const postCtl = (
<Post
key={keyPrefix + 'postKey'}
@@ -124,6 +133,8 @@ export default class PostsView extends React.Component {
posts={posts}
hideProfilePic={hideProfilePic}
isLastComment={isLastComment}
+ shouldHighlight={shouldHighlight}
+ onClick={() => EventHelpers.emitPostFocusEvent(post.id)} //eslint-disable-line no-loop-func
/>
);
@@ -185,9 +196,12 @@ export default class PostsView extends React.Component {
this.refs.postlist.scrollTop = this.refs.postlist.scrollHeight;
}
});
- } else if (this.props.scrollType === PostsView.SCROLL_TYPE_POST && this.props.scrollPost) {
+ } else if (this.props.scrollType === PostsView.SCROLL_TYPE_POST && this.props.scrollPostId) {
window.requestAnimationFrame(() => {
- const postNode = ReactDOM.findDOMNode(this.refs[this.props.scrollPost]);
+ const postNode = ReactDOM.findDOMNode(this.refs[this.props.scrollPostId]);
+ if (postNode == null) {
+ return;
+ }
postNode.scrollIntoView();
if (this.refs.postlist.scrollTop === postNode.offsetTop) {
this.refs.postlist.scrollTop -= (this.refs.postlist.offsetHeight / 3);
@@ -195,7 +209,7 @@ export default class PostsView extends React.Component {
this.refs.postlist.scrollTop -= (this.refs.postlist.offsetHeight / 3) + (this.refs.postlist.scrollTop - postNode.offsetTop);
}
});
- } else if (this.props.scrollType === PostsView.SIDEBAR_OPEN) {
+ } else if (this.props.scrollType === PostsView.SCROLL_TYPE_SIDEBAR_OPEN) {
// If we are at the bottom then stay there
if (this.wasAtBottom) {
this.refs.postlist.scrollTop = this.refs.postlist.scrollHeight;
@@ -211,7 +225,10 @@ export default class PostsView extends React.Component {
}
} else if (this.refs.postlist.scrollHeight !== this.prevScrollHeight) {
window.requestAnimationFrame(() => {
- this.refs.postlist.scrollTop += (this.refs.postlist.scrollHeight - this.prevScrollHeight);
+ // Only need to jump if we added posts to the top.
+ if (this.jumpToPostNode && (this.jumpToPostNode.offsetTop !== this.prevOffsetTop)) {
+ this.refs.postlist.scrollTop += (this.refs.postlist.scrollHeight - this.prevScrollHeight);
+ }
});
}
}
@@ -219,14 +236,18 @@ export default class PostsView extends React.Component {
this.updateScrolling();
}
componentDidMount() {
- this.updateScrolling();
+ if (this.props.postList != null) {
+ this.updateScrolling();
+ }
window.addEventListener('resize', this.handleResize);
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
}
componentDidUpdate() {
- this.updateScrolling();
+ if (this.props.postList != null) {
+ this.updateScrolling();
+ }
}
shouldComponentUpdate(nextProps) {
if (this.props.isActive !== nextProps.isActive) {
@@ -235,15 +256,12 @@ export default class PostsView extends React.Component {
if (this.props.postList !== nextProps.postList) {
return true;
}
- if (this.props.scrollPost !== nextProps.scrollPost) {
+ if (this.props.scrollPostId !== nextProps.scrollPostId) {
return true;
}
if (this.props.scrollType !== nextProps.scrollType && nextProps.scrollType !== PostsView.SCROLL_TYPE_FREE) {
return true;
}
- if (this.props.numPostsToDisplay !== nextProps.numPostsToDisplay) {
- return true;
- }
if (this.props.messageSeparatorTime !== nextProps.messageSeparatorTime) {
return true;
}
@@ -256,7 +274,8 @@ export default class PostsView extends React.Component {
render() {
let posts = [];
let order = [];
- let moreMessages;
+ let moreMessagesTop;
+ let moreMessagesBottom;
let postElements;
let activeClass = 'inactive';
if (this.props.postList != null) {
@@ -264,10 +283,10 @@ export default class PostsView extends React.Component {
order = this.props.postList.order;
// Create intro message or top loadmore link
- if (order.length >= this.props.numPostsToDisplay) {
- moreMessages = (
+ if (this.props.showMoreMessagesTop) {
+ moreMessagesTop = (
<a
- ref='loadmore'
+ ref='loadmoretop'
className='more-messages-text theme'
href='#'
onClick={this.loadMorePostsTop}
@@ -276,7 +295,23 @@ export default class PostsView extends React.Component {
</a>
);
} else {
- moreMessages = this.props.introText;
+ moreMessagesTop = this.props.introText;
+ }
+
+ // Give option to load more posts at bottom if nessisary
+ if (this.props.showMoreMessagesBottom) {
+ moreMessagesBottom = (
+ <a
+ ref='loadmorebottom'
+ className='more-messages-text theme'
+ href='#'
+ onClick={this.loadMorePostsBottom}
+ >
+ {'Load more messages'}
+ </a>
+ );
+ } else {
+ moreMessagesBottom = null;
}
// Create post elements
@@ -299,8 +334,9 @@ export default class PostsView extends React.Component {
ref='postlistcontent'
className='post-list__content'
>
- {moreMessages}
+ {moreMessagesTop}
{postElements}
+ {moreMessagesBottom}
</div>
</div>
</div>
@@ -313,11 +349,14 @@ PostsView.defaultProps = {
PostsView.propTypes = {
isActive: React.PropTypes.bool,
postList: React.PropTypes.object,
- scrollPost: React.PropTypes.string,
+ scrollPostId: React.PropTypes.string,
scrollType: React.PropTypes.number,
postViewScrolled: React.PropTypes.func.isRequired,
loadMorePostsTopClicked: React.PropTypes.func.isRequired,
- numPostsToDisplay: React.PropTypes.number,
+ loadMorePostsBottomClicked: React.PropTypes.func.isRequired,
+ showMoreMessagesTop: React.PropTypes.bool,
+ showMoreMessagesBottom: React.PropTypes.bool,
introText: React.PropTypes.element,
- messageSeparatorTime: React.PropTypes.number
+ messageSeparatorTime: React.PropTypes.number,
+ postsToHighlight: React.PropTypes.object
};