Show loading when filtering by user / best of

This commit is contained in:
Robin Ward 2013-03-21 16:46:22 -04:00
parent ce3fa4d507
commit 35ec6c6806
3 changed files with 83 additions and 80 deletions

View File

@ -11,6 +11,9 @@ Discourse.TopicController = Discourse.ObjectController.extend({
multiSelect: false, multiSelect: false,
bestOf: false, bestOf: false,
summaryCollapsed: true, summaryCollapsed: true,
loading: false,
loadingBelow: false,
loadingAbove: false,
needs: ['header', 'modal', 'composer', 'quoteButton'], needs: ['header', 'modal', 'composer', 'quoteButton'],
filter: (function() { filter: (function() {
@ -64,11 +67,11 @@ Discourse.TopicController = Discourse.ObjectController.extend({
multiSelectChanged: (function() { multiSelectChanged: (function() {
// Deselect all posts when multi select is turned off // Deselect all posts when multi select is turned off
var posts;
if (!this.get('multiSelect')) { if (!this.get('multiSelect')) {
if (posts = this.get('content.posts')) { var posts = this.get('content.posts');
return posts.forEach(function(p) { if (posts) {
return p.set('selected', false); posts.forEach(function(p) {
p.set('selected', false);
}); });
} }
} }
@ -187,6 +190,9 @@ Discourse.TopicController = Discourse.ObjectController.extend({
// Leave the first post -- we keep it above the filter controls // Leave the first post -- we keep it above the filter controls
posts.removeAt(1, posts.length - 1); posts.removeAt(1, posts.length - 1);
this.set('loadingBelow', true);
var topicController = this; var topicController = this;
return Discourse.Topic.find(this.get('id'), this.get('postFilters')).then(function(result) { return Discourse.Topic.find(this.get('id'), this.get('postFilters')).then(function(result) {
var first = result.posts.first(); var first = result.posts.first();
@ -199,6 +205,7 @@ Discourse.TopicController = Discourse.ObjectController.extend({
if (p.post_number === 1) return; if (p.post_number === 1) return;
posts.pushObject(Discourse.Post.create(p, topic)); posts.pushObject(Discourse.Post.create(p, topic));
}); });
topicController.set('loadingBelow', false);
}); });
}).observes('postFilters'), }).observes('postFilters'),

View File

@ -54,19 +54,19 @@
</nav> </nav>
</div> </div>
{{#if view.loadingAbove}} {{#if loadingAbove}}
<div class='spinner'>{{i18n loading}}</div> <div class='spinner'>{{i18n loading}}</div>
{{/if}} {{/if}}
{{collection itemViewClass="Discourse.PostView" contentBinding="content.posts" topicViewBinding="view"}} {{collection itemViewClass="Discourse.PostView" contentBinding="content.posts" topicViewBinding="view"}}
{{#if view.loadingBelow}} {{#if loadingBelow}}
<div class='spinner'>{{i18n loading}}</div> <div class='spinner'>{{i18n loading}}</div>
{{/if}} {{/if}}
</div> </div>
<div id='topic-bottom'></div> <div id='topic-bottom'></div>
{{#if view.loading}} {{#if loading}}
{{#unless view.loadingBelow}} {{#unless loadingBelow}}
<div class='spinner small'>{{i18n loading}}</div> <div class='spinner small'>{{i18n loading}}</div>
{{/unless}} {{/unless}}
{{else}} {{else}}

View File

@ -112,7 +112,7 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
willDestroyElement: function() { willDestroyElement: function() {
var screenTrack, controller; var screenTrack, controller;
this.unbindScrolling(); this.unbindScrolling();
controller = this.get('controller'); controller = this.get('controller');
controller.unsubscribe(); controller.unsubscribe();
controller.set('onPostRendered', null); controller.set('onPostRendered', null);
@ -127,48 +127,44 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
$(window).unbind('scroll.discourse-on-scroll'); $(window).unbind('scroll.discourse-on-scroll');
$(document).unbind('touchmove.discourse-on-scroll'); $(document).unbind('touchmove.discourse-on-scroll');
$(window).unbind('resize.discourse-on-scroll'); $(window).unbind('resize.discourse-on-scroll');
this.resetExamineDockCache(); this.resetExamineDockCache();
}, },
didInsertElement: function(e) { didInsertElement: function(e) {
var eyeline, onScroll, screenTrack, controller, var topicView = this;
_this = this; var onScroll = Discourse.debounce(function() { return topicView.onScroll(); }, 10);
onScroll = Discourse.debounce((function() {
return _this.onScroll();
}), 10);
$(window).bind('scroll.discourse-on-scroll', onScroll); $(window).bind('scroll.discourse-on-scroll', onScroll);
$(document).bind('touchmove.discourse-on-scroll', onScroll); $(document).bind('touchmove.discourse-on-scroll', onScroll);
$(window).bind('resize.discourse-on-scroll', onScroll); $(window).bind('resize.discourse-on-scroll', onScroll);
this.bindScrolling(); this.bindScrolling();
controller = this.get('controller');
var controller = this.get('controller');
controller.subscribe(); controller.subscribe();
controller.set('onPostRendered', function(){ controller.set('onPostRendered', function(){
_this.postsRendered.apply(_this); topicView.postsRendered.apply(topicView);
}); });
// Insert our screen tracker // Insert our screen tracker
screenTrack = Discourse.ScreenTrack.create({ topic_id: this.get('topic.id') }); var screenTrack = Discourse.ScreenTrack.create({ topic_id: this.get('topic.id') });
screenTrack.start(); screenTrack.start();
this.set('screenTrack', screenTrack); this.set('screenTrack', screenTrack);
// Track the user's eyeline // Track the user's eyeline
eyeline = new Discourse.Eyeline('.topic-post'); var eyeline = new Discourse.Eyeline('.topic-post');
eyeline.on('saw', function(e) {
eyeline.on('saw', function(e) { topicView.postSeen(e.detail);
_this.postSeen(e.detail);
});
eyeline.on('sawBottom', function(e) {
_this.postSeen(e.detail);
_this.nextPage(e.detail);
}); });
eyeline.on('sawTop', function(e) { eyeline.on('sawBottom', function(e) {
_this.postSeen(e.detail); topicView.postSeen(e.detail);
_this.prevPage(e.detail); topicView.nextPage(e.detail);
});
eyeline.on('sawTop', function(e) {
topicView.postSeen(e.detail);
topicView.prevPage(e.detail);
}); });
this.set('eyeline', eyeline); this.set('eyeline', eyeline);
@ -177,33 +173,32 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
}); });
this.onScroll(); this.onScroll();
}, },
// Triggered whenever any posts are rendered, debounced to save over calling // Triggered whenever any posts are rendered, debounced to save over calling
postsRendered: Discourse.debounce(function() { postsRendered: Discourse.debounce(function() {
var $window = $(window);
var $lastPost = $('.row:last');
var $lastPost, $window,
_this = this;
$window = $(window);
$lastPost = $('.row:last');
// we consider stuff at the end of the list as read, right away (if it is visible) // we consider stuff at the end of the list as read, right away (if it is visible)
if ($window.height() + $window.scrollTop() >= $lastPost.offset().top + $lastPost.height()) { if ($window.height() + $window.scrollTop() >= $lastPost.offset().top + $lastPost.height()) {
this.examineRead(); this.examineRead();
} else { } else {
// last is not in view, so only examine in 2 seconds // last is not in view, so only examine in 2 seconds
Em.run.later(function() { _this.examineRead(); }, 2000); var topicView = this;
Em.run.later(function() { topicView.examineRead(); }, 2000);
} }
}, 100), }, 100),
resetRead: function(e) { resetRead: function(e) {
var _this = this;
this.get('screenTrack').cancel(); this.get('screenTrack').cancel();
this.set('screenTrack', null); this.set('screenTrack', null);
this.get('controller').unsubscribe(); this.get('controller').unsubscribe();
var topicView = this;
this.get('topic').resetRead(function() { this.get('topic').resetRead(function() {
_this.set('controller.message', Em.String.i18n("topic.read_position_reset")); topicView.set('controller.message', Em.String.i18n("topic.read_position_reset"));
_this.set('controller.loaded', false); topicView.set('controller.loaded', false);
}); });
}, },
@ -253,11 +248,10 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
// Load previous posts if there are some // Load previous posts if there are some
prevPage: function($post) { prevPage: function($post) {
var opts, post, postView, var postView = Ember.View.views[$post.prop('id')];
_this = this;
postView = Ember.View.views[$post.prop('id')];
if (!postView) return; if (!postView) return;
post = postView.get('post');
var post = postView.get('post');
if (!post) return; if (!post) return;
// We don't load upwards from the first page // We don't load upwards from the first page
@ -267,22 +261,21 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
if (this.topic && this.topic.posts && this.topic.posts.length > 0 && this.topic.posts.first().post_number !== post.post_number) return; if (this.topic && this.topic.posts && this.topic.posts.length > 0 && this.topic.posts.first().post_number !== post.post_number) return;
// half mutex // half mutex
if (this.loading) return; if (this.get('controller.loading')) return;
this.set('loading', true); this.set('controller.loading', true);
this.set('loadingAbove', true); this.set('controller.loadingAbove', true);
opts = $.extend({ var opts = $.extend({ postsBefore: post.get('post_number') }, this.get('controller.postFilters'));
postsBefore: post.get('post_number')
}, this.get('controller.postFilters'));
var topicView = this;
return Discourse.Topic.find(this.get('topic.id'), opts).then(function(result) { return Discourse.Topic.find(this.get('topic.id'), opts).then(function(result) {
var lastPostNum, posts; var lastPostNum, posts;
posts = _this.get('topic.posts'); posts = topicView.get('topic.posts');
// Add a scrollTo record to the last post inserted to the DOM // Add a scrollTo record to the last post inserted to the DOM
lastPostNum = result.posts.first().post_number; lastPostNum = result.posts.first().post_number;
result.posts.each(function(p) { result.posts.each(function(p) {
var newPost; var newPost;
newPost = Discourse.Post.create(p, _this.get('topic')); newPost = Discourse.Post.create(p, topicView.get('topic'));
if (p.post_number === lastPostNum) { if (p.post_number === lastPostNum) {
newPost.set('scrollTo', { newPost.set('scrollTo', {
top: $(window).scrollTop(), top: $(window).scrollTop(),
@ -291,42 +284,43 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
} }
return posts.unshiftObject(newPost); return posts.unshiftObject(newPost);
}); });
_this.set('loading', false); topicView.set('controller.loading', false);
return _this.set('loadingAbove', false); return topicView.set('controller.loadingAbove', false);
}); });
}, },
fullyLoaded: (function() { fullyLoaded: (function() {
return this.seenBottom || this.topic.at_bottom; return this.get('controller.seenBottom') || this.get('topic.at_bottom');
}).property('topic.at_bottom', 'seenBottom'), }).property('topic.at_bottom', 'controller.seenBottom'),
// Load new posts if there are some // Load new posts if there are some
nextPage: function($post) { nextPage: function($post) {
var post, postView; if (this.get('controller.loading') || this.get('controller.seenBottom')) return;
if (this.loading || this.seenBottom) return;
postView = Ember.View.views[$post.prop('id')]; var postView = Ember.View.views[$post.prop('id')];
if (!postView) return; if (!postView) return;
post = postView.get('post');
var post = postView.get('post');
return this.loadMore(post); return this.loadMore(post);
}, },
postCountChanged: (function() { postCountChanged: (function() {
this.set('seenBottom', false); this.set('controller.seenBottom', false);
}).observes('topic.highest_post_number'), }).observes('topic.highest_post_number'),
loadMore: function(post) { loadMore: function(post) {
var opts, postNumberSeen, _ref, if (this.get('controller.loading') || this.get('controller.seenBottom')) return;
_this = this;
if (this.loading || this.seenBottom) return;
// Don't load if we know we're at the bottom // Don't load if we know we're at the bottom
if (this.get('topic.highest_post_number') === post.get('post_number')) { if (this.get('topic.highest_post_number') === post.get('post_number')) {
if (_ref = this.get('eyeline')) { var eyeline = this.get('eyeline');
_ref.flushRest(); if (eyeline) {
eyeline.flushRest();
} }
// Update our current post to the last number we saw // Update our current post to the last number we saw
if (postNumberSeen = this.get('postNumberSeen')) { var postNumberSeen = this.get('postNumberSeen');
if (postNumberSeen) {
this.set('controller.currentPost', postNumberSeen); this.set('controller.currentPost', postNumberSeen);
} }
return; return;
@ -334,26 +328,28 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
// Don't double load ever // Don't double load ever
if (this.topic.posts.last().post_number !== post.post_number) return; if (this.topic.posts.last().post_number !== post.post_number) return;
this.set('loadingBelow', true); this.set('controller.loadingBelow', true);
this.set('loading', true); this.set('controller.loading', true);
opts = $.extend({ postsAfter: post.get('post_number') }, this.get('controller.postFilters')); var opts = $.extend({ postsAfter: post.get('post_number') }, this.get('controller.postFilters'));
return Discourse.Topic.find(this.get('topic.id'), opts).then(function(result) {
var suggested; var topicView = this;
var topic = this.get('controller.content');
return Discourse.Topic.find(topic.get('id'), opts).then(function(result) {
if (result.at_bottom || result.posts.length === 0) { if (result.at_bottom || result.posts.length === 0) {
_this.set('seenBottom', 'true'); topicView.set('controller.seenBottom', 'true');
} }
_this.get('topic').pushPosts(result.posts.map(function(p) { topic.pushPosts(result.posts.map(function(p) {
return Discourse.Post.create(p, _this.get('topic')); return Discourse.Post.create(p, topic);
})); }));
if (result.suggested_topics) { if (result.suggested_topics) {
suggested = Em.A(); var suggested = Em.A();
result.suggested_topics.each(function(st) { result.suggested_topics.each(function(st) {
return suggested.pushObject(Discourse.Topic.create(st)); return suggested.pushObject(Discourse.Topic.create(st));
}); });
_this.set('topic.suggested_topics', suggested); topicView.set('topic.suggested_topics', suggested);
} }
_this.set('loadingBelow', false); topicView.set('controller.loadingBelow', false);
return _this.set('loading', false); return topicView.set('controller.loading', false);
}); });
}, },