From 1e6dea46ddd12c96a467593d4237b4562876794f Mon Sep 17 00:00:00 2001
From: Robin Ward <robin.ward@gmail.com>
Date: Mon, 12 Jan 2015 18:10:16 -0500
Subject: [PATCH] FIX: Jump to post was not respecting gaps

---
 .../discourse/components/post-gap.js.es6      |  8 ------
 .../controllers/topic-progress.js.es6         |  3 +--
 .../discourse/models/post_stream.js           | 26 +++++++++++++++++++
 .../models/post-stream-test.js.es6            | 11 ++++++++
 4 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/app/assets/javascripts/discourse/components/post-gap.js.es6 b/app/assets/javascripts/discourse/components/post-gap.js.es6
index 8cb313f6d19..38e40fa4460 100644
--- a/app/assets/javascripts/discourse/components/post-gap.js.es6
+++ b/app/assets/javascripts/discourse/components/post-gap.js.es6
@@ -1,11 +1,3 @@
-/**
-  Handles a gap between posts with a click to load more
-
-  @class PostGapComponent
-  @extends Ember.Component
-  @namespace Discourse
-  @module Discourse
-**/
 export default Ember.Component.extend({
   classNameBindings: [':gap', 'gap::hidden'],
 
diff --git a/app/assets/javascripts/discourse/controllers/topic-progress.js.es6 b/app/assets/javascripts/discourse/controllers/topic-progress.js.es6
index bad3916db13..1eef23fce36 100644
--- a/app/assets/javascripts/discourse/controllers/topic-progress.js.es6
+++ b/app/assets/javascripts/discourse/controllers/topic-progress.js.es6
@@ -29,8 +29,7 @@ export default Ember.ObjectController.extend({
       }
       this.set('toPostIndex', postIndex);
       var stream = this.get('postStream'),
-          idStream = stream.get('stream'),
-          postId = idStream[postIndex - 1];
+          postId = stream.findPostIdForPostNumber(postIndex);
 
       if (!postId) {
         Em.Logger.warn("jump-post code broken - requested an index outside the stream array");
diff --git a/app/assets/javascripts/discourse/models/post_stream.js b/app/assets/javascripts/discourse/models/post_stream.js
index cfdfa67d6b4..2a35c6ac8ae 100644
--- a/app/assets/javascripts/discourse/models/post_stream.js
+++ b/app/assets/javascripts/discourse/models/post_stream.js
@@ -667,6 +667,32 @@ Discourse.PostStream = Em.Object.extend({
     return closest;
   },
 
+  // Find a postId for a postNumber, respecting gaps
+  findPostIdForPostNumber: function(postNumber) {
+    var count = 1,
+        stream = this.get('stream'),
+        beforeLookup = this.get('gaps.before'),
+        streamLength = stream.length;
+
+    for (var i=0; i<streamLength; i++) {
+      var pid = stream[i];
+
+      // See if there are posts before this post
+      if (beforeLookup) {
+        var before = beforeLookup[pid];
+        if (before) {
+          for (var j=0; j<before.length; j++) {
+            if (count === postNumber) { return pid; }
+            count++;
+          }
+        }
+      }
+
+      if (count === postNumber) { return pid; }
+      count++;
+    }
+  },
+
   /**
     @private
 
diff --git a/test/javascripts/models/post-stream-test.js.es6 b/test/javascripts/models/post-stream-test.js.es6
index fccbbd24165..b4c68cb7016 100644
--- a/test/javascripts/models/post-stream-test.js.es6
+++ b/test/javascripts/models/post-stream-test.js.es6
@@ -121,6 +121,17 @@ test("cancelFilter", function() {
   blank(postStream.get('userFilters'), "cancelling the filters clears the userFilters");
 });
 
+test("findPostIdForPostNumber", function() {
+  var postStream = buildStream(1234, [10, 20, 30, 40, 50, 60, 70]);
+  postStream.set('gaps', { before: { 60: [55, 58] } });
+
+  equal(postStream.findPostIdForPostNumber(500), null, 'it returns null when the post cannot be found');
+  equal(postStream.findPostIdForPostNumber(1), 10, 'it finds the postId at the beginning');
+  equal(postStream.findPostIdForPostNumber(5), 50, 'it finds the postId in the middle');
+  equal(postStream.findPostIdForPostNumber(8), 60, 'it respects gaps');
+
+});
+
 test("toggleParticipant", function() {
   var postStream = buildStream(1236);
   sandbox.stub(postStream, "refresh");