From 8b33e659a10382b0f6beb3d06e3cede08bba86a4 Mon Sep 17 00:00:00 2001
From: Robin Ward <robin.ward@gmail.com>
Date: Tue, 9 Sep 2014 12:57:13 -0400
Subject: [PATCH] FIX: Only use cached topic lists on popState

---
 .../discourse/components/home-logo.js.es6     |  4 --
 app/assets/javascripts/discourse/lib/url.js   |  1 +
 .../discourse/models/topic_list.js            | 42 +++++++++++--------
 .../discourse/routes/build-topic-route.js.es6 |  8 ++--
 .../discourse/routes/discourse_route.js       |  4 ++
 5 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/app/assets/javascripts/discourse/components/home-logo.js.es6 b/app/assets/javascripts/discourse/components/home-logo.js.es6
index 1e1545033..83ca9ec8d 100644
--- a/app/assets/javascripts/discourse/components/home-logo.js.es6
+++ b/app/assets/javascripts/discourse/components/home-logo.js.es6
@@ -24,10 +24,6 @@ export default Ember.Component.extend({
 
     e.preventDefault();
 
-    // When you click the logo, never use a cached list
-    var session = Discourse.Session.current();
-    session.setProperties({topicList: null, topicListScrollPosition: null});
-
     Discourse.URL.routeTo('/');
     return false;
   }
diff --git a/app/assets/javascripts/discourse/lib/url.js b/app/assets/javascripts/discourse/lib/url.js
index 0ee18f7b0..b7fe81d1a 100644
--- a/app/assets/javascripts/discourse/lib/url.js
+++ b/app/assets/javascripts/discourse/lib/url.js
@@ -317,6 +317,7 @@ Discourse.URL = Em.Object.createWithMixins({
     }
 
     var transition = router.handleURL(path);
+    transition._discourse_intercepted = true;
     transition.promise.then(function() {
       if (elementId) {
 
diff --git a/app/assets/javascripts/discourse/models/topic_list.js b/app/assets/javascripts/discourse/models/topic_list.js
index 0402f4ac1..d81ce353f 100644
--- a/app/assets/javascripts/discourse/models/topic_list.js
+++ b/app/assets/javascripts/discourse/models/topic_list.js
@@ -193,34 +193,40 @@ Discourse.TopicList.reopenClass({
     @method list
     @param {Object} filter The menu item to filter to
     @param {Object} params Any additional params to pass to TopicList.find()
+    @param {Object} extras Additional finding options, such as caching
     @returns {Promise} a promise that resolves to the list of topics
   **/
-  list: function(filter, params) {
-    var session = Discourse.Session.current(),
-        list = session.get('topicList'),
-        tracking = Discourse.TopicTrackingState.current();
+  list: function(filter, filterParams, extras) {
+    var tracking = Discourse.TopicTrackingState.current();
 
+    extras = extras || {};
     return new Ember.RSVP.Promise(function(resolve) {
-      // Try to use the cached version
-      if (list && (list.get('filter') === filter) &&
-               _.isEqual(list.get('listParams'), params)) {
-        list.set('loaded', true);
+      var session = Discourse.Session.current();
 
-        if (tracking) {
-          tracking.updateTopics(list.get('topics'));
+      if (extras.cached) {
+        var cachedList = session.get('topicList');
+
+        // Try to use the cached version
+        if (cachedList && (cachedList.get('filter') === filter) &&
+                 _.isEqual(cachedList.get('listParams'), filterParams)) {
+          cachedList.set('loaded', true);
+
+          if (tracking) {
+            tracking.updateTopics(cachedList.get('topics'));
+          }
+          return resolve(cachedList);
         }
-        return resolve(list);
       }
 
-      // Perform the search
+      // Clear the cache
       session.setProperties({topicList: null, topicListScrollPosition: null});
 
       // Clean up any string parameters that might slip through
-      params = params || {};
-      Ember.keys(params).forEach(function(k) {
-        var val = params[k];
+      filterParams = filterParams || {};
+      Ember.keys(filterParams).forEach(function(k) {
+        var val = filterParams[k];
         if (val === "undefined" || val === "null" || val === 'false') {
-          params[k] = undefined;
+          filterParams[k] = undefined;
         }
       });
 
@@ -233,10 +239,10 @@ Discourse.TopicList.reopenClass({
           }
         }
       });
-      return resolve(Discourse.TopicList.find(filter, _.extend(findParams, params || {})));
+      return resolve(Discourse.TopicList.find(filter, _.extend(findParams, filterParams || {})));
 
     }).then(function(list) {
-      list.set('listParams', params);
+      list.set('listParams', filterParams);
       if (tracking) {
         tracking.sync(list, list.filter);
         tracking.trackIncoming(list.filter);
diff --git a/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 b/app/assets/javascripts/discourse/routes/build-topic-route.js.es6
index e92464e4f..8d823ca53 100644
--- a/app/assets/javascripts/discourse/routes/build-topic-route.js.es6
+++ b/app/assets/javascripts/discourse/routes/build-topic-route.js.es6
@@ -21,13 +21,15 @@ export default function(filter, extras) {
       this.controllerFor('navigation/default').set('filterMode', filter);
     },
 
-    model: function(data, transaction) {
+    model: function(data, transition) {
 
       // attempt to stop early cause we need this to be called before .sync
       Discourse.ScreenTrack.current().stop();
 
-      var findOpts = filterQueryParams(transaction.queryParams);
-      return Discourse.TopicList.list(filter, findOpts);
+      var findOpts = filterQueryParams(transition.queryParams),
+          extras = { cached: this.isPoppedState(transition) };
+
+      return Discourse.TopicList.list(filter, findOpts, extras);
     },
 
     setupController: function(controller, model, trans) {
diff --git a/app/assets/javascripts/discourse/routes/discourse_route.js b/app/assets/javascripts/discourse/routes/discourse_route.js
index b43148b05..820c3c0b0 100644
--- a/app/assets/javascripts/discourse/routes/discourse_route.js
+++ b/app/assets/javascripts/discourse/routes/discourse_route.js
@@ -41,6 +41,10 @@ Discourse.Route = Em.Route.extend({
         });
       }
     }
+  },
+
+  isPoppedState: function(transition) {
+    return (!transition._discourse_intercepted) && (!!transition.intent.url);
   }
 
 });