summaryrefslogtreecommitdiffstats
path: root/web/react/components/post_list.jsx
diff options
context:
space:
mode:
authornickago <ngonella@calpoly.edu>2015-08-11 10:28:30 -0700
committernickago <ngonella@calpoly.edu>2015-08-12 09:28:54 -0700
commit3d492bf450a245aafbfb5b3cff320c1d45832b37 (patch)
tree9753ceee6d56e092c9457e2a1f0d29e993c16f17 /web/react/components/post_list.jsx
parent41248959c838c050a34bd27558684a5f1aa8a7e9 (diff)
downloadchat-3d492bf450a245aafbfb5b3cff320c1d45832b37.tar.gz
chat-3d492bf450a245aafbfb5b3cff320c1d45832b37.tar.bz2
chat-3d492bf450a245aafbfb5b3cff320c1d45832b37.zip
Completely rehauled scrolling system, finished base implementation
Diffstat (limited to 'web/react/components/post_list.jsx')
-rw-r--r--web/react/components/post_list.jsx123
1 files changed, 36 insertions, 87 deletions
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx
index 0abb3107e..cfbdad571 100644
--- a/web/react/components/post_list.jsx
+++ b/web/react/components/post_list.jsx
@@ -28,15 +28,13 @@ function getStateFromStores() {
module.exports = React.createClass({
displayName: "PostList",
- scrollPosition: 0,
- preventScrollTrigger: false, // Can't think of an intuitive name, but when true,
- // scrollPosition is affected by the 'on scroll' event below
- gotMorePosts: false,
- oldScrollHeight: 0,
oldZoom: 0,
- scrolledToNew: false, // Signifies we've already scrolled to the "new message" bar
- // one time, don't want to do it again even if the bar
- // doesn't go away
+ holdPosition: false, // The default state is to scroll to the bottom on change
+ // This behavior should NOT be taken advantage of, always set this to the desired state
+
+ scrollHeightFromBottom: 0, // This represents the distance from the container's scrollHeight
+ // and current scrollTop
+ // Based on equation scrollTop + scrollHeightFromBottom = scrollHeight
componentDidMount: function() {
// Add CSS required to have the theme colors
@@ -66,58 +64,10 @@ module.exports = React.createClass({
UserStore.addStatusesChangeListener(this._onTimeChange);
SocketStore.addChangeListener(this._onSocketChange);
- // Initialize perfect scrollbar
- $(".post-list-holder-by-time").perfectScrollbar();
-
- this.resize();
-
- // Set initial values of these component properties, will be updated on every re-render
- // scrollPosition - scroll point of bottom of current viewport
- // oldScrollHeight - bottom scroll point possible of viewport
- // oldZoom - represents "browser zoom"
- var post_holder = $(".post-list-holder-by-time")[0];
- this.scrollPosition = $(post_holder).scrollTop() + $(post_holder).innerHeight();
- this.oldScrollHeight = post_holder.scrollHeight;
- this.oldZoom = (window.outerWidth - 8) / window.innerWidth;
-
- /*************** End of 'run on mount' code, Start of event listeners *****************/
-
- var self = this;
- $(window).resize(function(){
- $(post_holder).perfectScrollbar('update');
-
- // this only kind of works, detecting zoom in browsers is a nightmare
- var newZoom = (window.outerWidth - 8) / window.innerWidth;
-
- // We resize if :
- // 1. We are scrolled below the max scroll
- // 2. Edge case similar to offscreen resizing
- // 3. We changed zoom sizes
- if (self.scrollPosition >= post_holder.scrollHeight ||
- (self.oldScrollHeight !== post_holder.scrollHeight && self.scrollPosition >= self.oldScrollHeight) ||
- self.oldZoom !== newZoom) {
- self.resize();
- }
-
- self.oldZoom = newZoom;
-
- // Sets the size of the viewport, doesn't affect the overflowed component
- if ($('#create_post').length > 0) {
- var height = $(window).height() - $('#create_post').height() - $('#error_bar').outerHeight() - 50;
- $(".post-list-holder-by-time").css("height", height + "px");
- }
- });
-
- // scrollPosistion records and holds every position that the user has been at
- // unless preventScrollTrigger is enabled, then it skips one reading
- // Consider storing this in localStorage instead
- $(post_holder).scroll(function(e){
- if (!self.preventScrollTrigger) {
- self.scrollPosition = $(post_holder).scrollTop() + $(post_holder).innerHeight();
- }
- self.preventScrollTrigger = false;
- });
+ // Timeout exists for the DOM to fully render before making changes
+ setTimeout(this.scrollWindow, 1)
+ // Highlight stylingx
$('body').on('click.userpopover', function(e){
if ($(e.target).attr('data-toggle') !== 'popover'
&& $(e.target).parents('.popover.in').length === 0) {
@@ -149,13 +99,15 @@ module.exports = React.createClass({
$(this).parent('div').next('.date-separator, .new-separator').removeClass('hovered--comment');
}
});
-
+ },
+ componentWillUpdate: function() {
+ var container = $('.post-list-holder-by-time');
+ if (this.holdPosition) {
+ this.scrollHeightFromBottom = container[0].scrollHeight - container.scrollTop();
+ }
},
componentDidUpdate: function() {
- this.resize();
- var post_holder = $(".post-list-holder-by-time")[0];
- this.scrollPosition = $(post_holder).scrollTop() + $(post_holder).innerHeight();
- this.oldScrollHeight = post_holder.scrollHeight;
+ this.scrollWindow()
$('.post-list__content div .post').removeClass('post--last');
$('.post-list__content div:last-child .post').addClass('post--last');
},
@@ -166,34 +118,25 @@ module.exports = React.createClass({
SocketStore.removeChangeListener(this._onSocketChange);
$('body').off('click.userpopover');
},
- resize: function() {
- var post_holder = $(".post-list-holder-by-time")[0];
- this.preventScrollTrigger = true;
- if (this.gotMorePosts) {
- this.gotMorePosts = false;
- $(post_holder).scrollTop($(post_holder).scrollTop() + (post_holder.scrollHeight-this.oldScrollHeight) );
- } else if ($("#new_message")[0] && !this.scrolledToNew) {
- $(post_holder).scrollTop($(post_holder).scrollTop() + $("#new_message").offset().top - 63);
- this.scrolledToNew = true;
+ scrollWindow: function() {
+ var container = $('.post-list-holder-by-time');
+
+ // If there's a new message, this jumps the window to that
+ // If there's no new message, we check if there is a scroll position to retrieve from the previous state
+ // If we don't, then we just jump to the bottom
+ if ($('#new_message').length) {
+ container.scrollTop(container.scrollTop() + $('#new_message').offset().top - container.offset().top - $('.new-separator').height());
+ } else if (this.holdPosition) {
+ container.scrollTop(container[0].scrollHeight - this.scrollHeightFromBottom);
+ this.holdPosition = false;
} else {
- $(post_holder).scrollTop(post_holder.scrollHeight);
+ container.scrollTop(container[0].scrollHeight - container.innerHeight());
}
- $(post_holder).perfectScrollbar('update');
},
_onChange: function() {
var newState = getStateFromStores();
if (!utils.areStatesEqual(newState, this.state)) {
- if (this.state.post_list &&
- this.state.post_list.order &&
- this.state.channel.id === newState.channel.id &&
- this.state.post_list.order.length !== newState.post_list.order.length &&
- newState.post_list.order.length > Constants.POST_CHUNK_SIZE) {
- this.gotMorePosts = true;
- }
- if (this.state.channel.id !== newState.channel.id) {
- this.scrolledToNew = false;
- }
this.setState(newState);
}
},
@@ -209,6 +152,8 @@ module.exports = React.createClass({
post_list.order.unshift(post.id);
}
+ this.holdPosition = false;
+
if (this.state.channel.id === msg.channel_id) {
this.setState({ post_list: post_list });
};
@@ -225,6 +170,8 @@ module.exports = React.createClass({
post_list.posts[post.id] = post;
this.setState({ post_list: post_list });
+ this.holdPosition = true;
+
PostStore.storePosts(msg.channel_id, post_list);
} else {
AsyncClient.getPosts(true, msg.channel_id);
@@ -241,6 +188,8 @@ module.exports = React.createClass({
var index = post_list.order.indexOf(msg.props.post_id);
if (index > -1) post_list.order.splice(index, 1);
+ this.holdPosition = true;
+
this.setState({ post_list: post_list });
PostStore.storePosts(msg.channel_id, post_list);
@@ -274,7 +223,7 @@ module.exports = React.createClass({
$(this.refs.loadmore.getDOMNode()).text("Retrieving more messages...");
var self = this;
- var currentPos = $(".post-list").scrollTop;
+ this.holdPosition = true;
Client.getPosts(
channel_id,
@@ -282,6 +231,7 @@ module.exports = React.createClass({
Constants.POST_CHUNK_SIZE,
function(data) {
$(self.refs.loadmore.getDOMNode()).text("Load more messages");
+ console.log("here")
if (!data) return;
@@ -298,7 +248,6 @@ module.exports = React.createClass({
});
Client.getProfiles();
- $(".post-list").scrollTop(currentPos);
},
function(err) {
$(self.refs.loadmore.getDOMNode()).text("Load more messages");