FIX: Small bugs with progress indicator

This commit is contained in:
Robin Ward 2013-07-03 12:30:22 -04:00
parent 80928de21e
commit b0e10673a2
5 changed files with 79 additions and 16 deletions

View file

@ -19,7 +19,7 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
}.property('postStream.filteredPostsCount', 'progressPosition'), }.property('postStream.filteredPostsCount', 'progressPosition'),
jumpBottomDisabled: function() { jumpBottomDisabled: function() {
return this.get('progressPosition') === this.get('postStream.filteredPostsCount'); return this.get('progressPosition') >= this.get('postStream.filteredPostsCount');
}.property('postStream.filteredPostsCount', 'progressPosition'), }.property('postStream.filteredPostsCount', 'progressPosition'),
canMergeTopic: function() { canMergeTopic: function() {
@ -60,6 +60,12 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
return canDelete; return canDelete;
}.property('selectedPostsCount'), }.property('selectedPostsCount'),
streamPercentage: function() {
if (!this.get('postStream.loaded')) { return 0; }
if (this.get('postStream.filteredPostsCount') === 0) { return 0; }
return this.get('progressPosition') / this.get('postStream.filteredPostsCount');
}.property('postStream.loaded', 'progressPosition', 'postStream.filteredPostsCount'),
multiSelectChanged: function() { multiSelectChanged: function() {
// Deselect all posts when multi select is turned off // Deselect all posts when multi select is turned off
if (!this.get('multiSelect')) { if (!this.get('multiSelect')) {

View file

@ -430,6 +430,30 @@ Discourse.PostStream = Em.Object.extend({
} }
}, },
/**
Returns the closest post number given a postNumber that may not exist in the stream.
For example, if the user asks for a post that's deleted or otherwise outside the range.
This allows us to set the progress bar with the correct number.
@method closestPostNumberFor
@param {Integer} postNumber the post number we're looking for
**/
closestPostNumberFor: function(postNumber) {
if (!this.get('hasPosts')) { return; }
var closest = null;
this.get('posts').forEach(function (p) {
if (closest === postNumber) { return; }
if (!closest) { closest = p.get('post_number'); }
if (Math.abs(postNumber - p.get('post_number')) < Math.abs(closest - postNumber)) {
closest = p.get('post_number');
}
});
return closest;
},
/** /**
@private @private

View file

@ -32,9 +32,13 @@ Discourse.TopicFromParamsRoute = Discourse.Route.extend({
var topicController = this.controllerFor('topic'); var topicController = this.controllerFor('topic');
postStream.refresh(params).then(function () { postStream.refresh(params).then(function () {
// The post we requested might not exist. Let's find the closest post
var closest = postStream.closestPostNumberFor(params.nearPost) || 1;
topicController.setProperties({ topicController.setProperties({
currentPost: params.nearPost || 1, currentPost: closest,
progressPosition: params.nearPost || 1 progressPosition: closest
}); });
if (topic.present('draft')) { if (topic.present('draft')) {
@ -46,7 +50,6 @@ Discourse.TopicFromParamsRoute = Discourse.Route.extend({
ignoreIfChanged: true ignoreIfChanged: true
}); });
} }
}); });

View file

@ -17,22 +17,19 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
postStream: Em.computed.alias('controller.postStream'), postStream: Em.computed.alias('controller.postStream'),
updateBar: function() {
if (!this.get('postStream.loaded')) return;
updateBar: function() {
var $topicProgress = $('#topic-progress'); var $topicProgress = $('#topic-progress');
if (!$topicProgress.length) return; if (!$topicProgress.length) return;
var ratio = this.get('controller.progressPosition') / this.get('postStream.filteredPostsCount');
var totalWidth = $topicProgress.width(); var totalWidth = $topicProgress.width();
var progressWidth = ratio * totalWidth; var progressWidth = this.get('controller.streamPercentage') * totalWidth;
var bg = $topicProgress.find('.bg');
var currentWidth = bg.width();
bg.css("border-right-width", (progressWidth === totalWidth) ? "0px" : "1px") $topicProgress.find('.bg')
.width(progressWidth); .css("border-right-width", (progressWidth === totalWidth) ? "0px" : "1px")
.width(progressWidth);
}.observes('controller.progressPosition', 'postStream.filteredPostsCount', 'topic.loaded'), }.observes('controller.streamPercentage'),
updateTitle: function() { updateTitle: function() {
var title = this.get('topic.title'); var title = this.get('topic.title');
@ -86,6 +83,9 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
}); });
this.updatePosition(); this.updatePosition();
// We want to make sure the progress bar is updated after it's rendered
this.updateBar();
}, },
debounceLoadSuggested: Discourse.debounce(function(){ debounceLoadSuggested: Discourse.debounce(function(){
@ -169,6 +169,7 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
if (!postView) return; if (!postView) return;
var post = postView.get('post'); var post = postView.get('post');
if (!post) return; if (!post) return;
this.set('controller.progressPosition', this.get('postStream').indexOf(post) + 1); this.set('controller.progressPosition', this.get('postStream').indexOf(post) + 1);
}, },
@ -184,9 +185,14 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
this.updatePosition(); this.updatePosition();
}, },
updatePosition: function() {
var topic = this.get('controller.model');
/**
Process the posts the current user has seen in the topic.
@private
@method processSeenPosts
**/
processSeenPosts: function() {
var rows = $('.topic-post.ready'); var rows = $('.topic-post.ready');
if (!rows || rows.length === 0) { return; } if (!rows || rows.length === 0) { return; }
@ -235,6 +241,16 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
} else { } else {
console.error("can't update position "); console.error("can't update position ");
} }
},
/**
The user has scrolled the window, or it is finished rendering and ready for processing.
@method updatePosition
**/
updatePosition: function() {
this.processSeenPosts();
var offset = window.pageYOffset || $('html').scrollTop(); var offset = window.pageYOffset || $('html').scrollTop();
if (!this.get('docAt')) { if (!this.get('docAt')) {
@ -244,7 +260,8 @@ Discourse.TopicView = Discourse.View.extend(Discourse.Scrolling, {
} }
} }
var headerController = this.get('controller.controllers.header'); var headerController = this.get('controller.controllers.header'),
topic = this.get('controller.model');
if (this.get('docAt')) { if (this.get('docAt')) {
headerController.set('showExtraInfo', offset >= this.get('docAt') || topic.get('postStream.firstPostNotLoaded')); headerController.set('showExtraInfo', offset >= this.get('docAt') || topic.get('postStream.firstPostNotLoaded'));
} else { } else {

View file

@ -54,6 +54,19 @@ test('appending posts', function() {
ok(postStream.get('lastPostLoaded'), "the last post is still the last post in the new stream"); ok(postStream.get('lastPostLoaded'), "the last post is still the last post in the new stream");
}); });
test('closestPostNumberFor', function() {
var postStream = buildStream(1231);
blank(postStream.closestPostNumberFor(1), "there is no closest post when nothing is loaded");
postStream.appendPost(Discourse.Post.create({id: 1, post_number: 2}));
postStream.appendPost(Discourse.Post.create({id: 2, post_number: 3}));
equal(postStream.closestPostNumberFor(2), 2, "If a post is in the stream it returns its post number");
equal(postStream.closestPostNumberFor(3), 3, "If a post is in the stream it returns its post number");
equal(postStream.closestPostNumberFor(10), 3, "it clips to the upper bound of the stream");
equal(postStream.closestPostNumberFor(0), 2, "it clips to the lower bound of the stream");
});
test('updateFromJson', function() { test('updateFromJson', function() {
var postStream = buildStream(1231); var postStream = buildStream(1231);