From 33683715a9cce3c7618efe8f052569f670d9250c Mon Sep 17 00:00:00 2001 From: Sam <sam.saffron@gmail.com> Date: Tue, 28 May 2013 08:43:17 +1000 Subject: [PATCH] work in progress live unread / new counts --- .../discourse/controllers/list_controller.js | 4 +- .../javascripts/discourse/models/nav_item.js | 12 ++- .../discourse/models/topic_list.js | 1 - .../javascripts/discourse/models/user.js | 1 + .../discourse/models/user_tracking_state.js | 80 +++++++++++++++++-- .../discourse/routes/application_route.js | 24 ++++++ .../discourse/views/nav_item_view.js | 21 +++-- app/serializers/topic_list_serializer.rb | 2 +- 8 files changed, 124 insertions(+), 21 deletions(-) create mode 100644 app/assets/javascripts/discourse/routes/application_route.js diff --git a/app/assets/javascripts/discourse/controllers/list_controller.js b/app/assets/javascripts/discourse/controllers/list_controller.js index aa22cb6c8..3a052f72c 100644 --- a/app/assets/javascripts/discourse/controllers/list_controller.js +++ b/app/assets/javascripts/discourse/controllers/list_controller.js @@ -18,12 +18,12 @@ Discourse.ListController = Discourse.Controller.extend({ return Discourse.SiteSettings.top_menu.split("|").map(function(i) { return Discourse.NavItem.fromText(i, { loggedOn: loggedOn, - countSummary: summary + hasCategories: hasCategories }); }).filter(function(i) { return i !== null; }); - }.property('filterSummary'), + }.property(), /** Load a list based on a filter diff --git a/app/assets/javascripts/discourse/models/nav_item.js b/app/assets/javascripts/discourse/models/nav_item.js index 7d268d634..fa9278608 100644 --- a/app/assets/javascripts/discourse/models/nav_item.js +++ b/app/assets/javascripts/discourse/models/nav_item.js @@ -10,6 +10,7 @@ var validNavNames = ['latest', 'hot', 'categories', 'category', 'favorited', 'un var validAnon = ['latest', 'hot', 'categories', 'category']; Discourse.NavItem = Discourse.Model.extend({ + userTrackingStateBinding: Ember.Binding.oneWay('Discourse.currentUser.userTrackingState.messageCount'), categoryName: function() { var split = this.get('name').split('/'); return split[0] === 'category' ? split[1] : null; @@ -21,7 +22,14 @@ Discourse.NavItem = Discourse.Model.extend({ href = Discourse.getURL("/") + name.replace(' ', '-'); if (name === 'category') href += "/" + this.get('categoryName'); return href; - }.property('name') + }.property('name'), + + count: function() { + var state = Discourse.get('currentUser.userTrackingState'); + if (state) { + return state.lookupCount(this.get('name')); + } + }.property('userTrackingState') }); Discourse.NavItem.reopenClass({ @@ -43,7 +51,7 @@ Discourse.NavItem.reopenClass({ filters: split.splice(1) }; - if (countSummary && countSummary[name]) opts.count = countSummary[name]; + // if (countSummary && countSummary[name]) opts.count = countSummary[name]; return Discourse.NavItem.create(opts); } diff --git a/app/assets/javascripts/discourse/models/topic_list.js b/app/assets/javascripts/discourse/models/topic_list.js index e5bc0f4ee..c9901fd7c 100644 --- a/app/assets/javascripts/discourse/models/topic_list.js +++ b/app/assets/javascripts/discourse/models/topic_list.js @@ -118,7 +118,6 @@ Discourse.TopicList.reopenClass({ topics: Discourse.TopicList.topicsFrom(result), can_create_topic: result.topic_list.can_create_topic, more_topics_url: result.topic_list.more_topics_url, - filter_summary: result.topic_list.filter_summary, draft_key: result.topic_list.draft_key, draft_sequence: result.topic_list.draft_sequence, draft: result.topic_list.draft, diff --git a/app/assets/javascripts/discourse/models/user.js b/app/assets/javascripts/discourse/models/user.js index 68850c912..3ba11f68b 100644 --- a/app/assets/javascripts/discourse/models/user.js +++ b/app/assets/javascripts/discourse/models/user.js @@ -314,6 +314,7 @@ Discourse.User.reopenClass({ }); }, + /** Checks if given username is valid for this email address diff --git a/app/assets/javascripts/discourse/models/user_tracking_state.js b/app/assets/javascripts/discourse/models/user_tracking_state.js index 5843d1250..db6cbd413 100644 --- a/app/assets/javascripts/discourse/models/user_tracking_state.js +++ b/app/assets/javascripts/discourse/models/user_tracking_state.js @@ -1,16 +1,80 @@ Discourse.UserTrackingState = Discourse.Model.extend({ - unreadPosts: function(){ - return 10; - }.property(), + init: function(){ + this._super(); + this.states = {}; - newPosts: function() { - return 10; - }.property() + var _this = this; + setTimeout(function(){ + console.log("YYYYYYYYYYY"); + _this.loadStates([{ + topic_id: 100, + last_read_post_number: null + }]); + _this.set('messageCount', 100); + }, 2000); + }, + + establishChannels: function() { + + + }, + + countNew: function(){ + var count = 0; + $.each(this.states, function(){ + count += this.last_read_post_number === null ? 1 : 0; + }); + return count; + }, + + countUnread: function(){ + var count = 0; + $.each(this.states, function(){ + count += (this.last_read_post_number !== null && + this.last_read_post_number < this.highest_post_number) ? 1 : 0; + }); + return count; + }, + + countCategory: function(category) { + var count = 0; + $.each(this.states, function(){ + if (this.category_name === category) { + count += (this.last_read_post_number === null || + this.last_read_post_number < this.highest_post_number) ? 1 : 0; + } + }); + return count; + }, + + lookupCount: function(name){ + if(name==="new") { + return this.countNew(); + } else if(name==="unread") { + return this.countUnread(); + } else { + var category = name.split("/")[1]; + if(category) { + return this.countCategory(category); + } + } + }, + loadStates: function (data) { + // not exposed + var states = this.states; + + data.each(function(row){ + states["t" + row.topic_id] = row; + }); + } }); Discourse.UserTrackingState.reopenClass({ - init: function(data){ - + createFromStates: function(data){ + var instance = Discourse.UserTrackingState.create(); + instance.loadStates(data); + instance.establishChannels(); + return instance; } }); diff --git a/app/assets/javascripts/discourse/routes/application_route.js b/app/assets/javascripts/discourse/routes/application_route.js new file mode 100644 index 000000000..337f3df6e --- /dev/null +++ b/app/assets/javascripts/discourse/routes/application_route.js @@ -0,0 +1,24 @@ +/** + The base Application route + + @class ApplicationRoute + @extends Discourse.Route + @namespace Discourse + @module Discourse +**/ +Discourse.ApplicationRoute = Discourse.Route.extend({ + setupController: function(controller) { + Discourse.set('site', Discourse.Site.create(PreloadStore.get('site'))); + var currentUser = PreloadStore.get('currentUser'); + if (currentUser) { + var states = currentUser.user_tracking_states; + currentUser.user_tracking_states = null; + + Discourse.set('currentUser', Discourse.User.create(currentUser)); + Discourse.set('currentUser.userTrackingState', Discourse.UserTrackingState.createFromStates(states)); + } + // make sure we delete preloaded data + PreloadStore.remove('site'); + PreloadStore.remove('currentUser'); + } +}); diff --git a/app/assets/javascripts/discourse/views/nav_item_view.js b/app/assets/javascripts/discourse/views/nav_item_view.js index bf54870ad..d4adab7b3 100644 --- a/app/assets/javascripts/discourse/views/nav_item_view.js +++ b/app/assets/javascripts/discourse/views/nav_item_view.js @@ -10,12 +10,12 @@ Discourse.NavItemView = Discourse.View.extend({ tagName: 'li', classNameBindings: ['isActive', 'content.hasIcon:has-icon'], attributeBindings: ['title'], + countBinding: Ember.Binding.oneWay('content.count'), title: function() { - var name = this.get('content.name'); - var categoryName = this.get('content.categoryName'); - - var extra; + var categoryName, extra, name; + name = this.get('content.name'); + categoryName = this.get('content.categoryName'); if (categoryName) { extra = { categoryName: categoryName }; name = "category"; @@ -30,10 +30,17 @@ Discourse.NavItemView = Discourse.View.extend({ hidden: Em.computed.not('content.visible'), + countChanged: function(){ + this.rerender(); + }.observes('count'), + name: function() { - var name = this.get('content.name'); - var categoryName = this.get('content.categoryName'); - var extra = { count: this.get('content.count') || 0 }; + var categoryName, extra, name; + name = this.get('content.name'); + categoryName = this.get('content.categoryName'); + extra = { + count: this.get('content.count') || 0 + }; if (categoryName) { name = 'category'; extra.categoryName = categoryName.titleize(); diff --git a/app/serializers/topic_list_serializer.rb b/app/serializers/topic_list_serializer.rb index c6d609cd2..f3bf96cf4 100644 --- a/app/serializers/topic_list_serializer.rb +++ b/app/serializers/topic_list_serializer.rb @@ -2,7 +2,7 @@ class TopicListSerializer < ApplicationSerializer attributes :can_create_topic, :more_topics_url, - :filter_summary, + # :filter_summary, :draft, :draft_key, :draft_sequence,