Skip to content

Commit e93b7a3

Browse files
committed
more progress towards live unread and new counts, unread message implemented, still to implement delete messages
1 parent f2da06a commit e93b7a3

19 files changed

Lines changed: 325 additions & 87 deletions

app/assets/javascripts/discourse/controllers/list_controller.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Discourse.ListController = Discourse.Controller.extend({
3535
var listController = this;
3636
this.set('loading', true);
3737

38-
var trackingState = Discourse.get('currentUser.userTrackingState');
38+
var trackingState = Discourse.TopicTrackingState.current();
3939

4040
if (filterMode === 'categories') {
4141
return Discourse.CategoryList.list(filterMode).then(function(items) {

app/assets/javascripts/discourse/controllers/list_topics_controller.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Discourse.ListTopicsController = Discourse.ObjectController.extend({
5555

5656
// Show newly inserted topics
5757
showInserted: function(e) {
58-
var tracker = Discourse.get('currentUser.userTrackingState');
58+
var tracker = Discourse.TopicTrackingState.current();
5959

6060
// Move inserted into topics
6161
this.get('content').loadBefore(tracker.get('newIncoming'));

app/assets/javascripts/discourse/models/nav_item.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ var validNavNames = ['latest', 'hot', 'categories', 'category', 'favorited', 'un
1010
var validAnon = ['latest', 'hot', 'categories', 'category'];
1111

1212
Discourse.NavItem = Discourse.Model.extend({
13-
userTrackingStateBinding: Ember.Binding.oneWay('Discourse.currentUser.userTrackingState.messageCount'),
13+
topicTrackingState: function(){
14+
return Discourse.TopicTrackingState.current();
15+
}.property(),
16+
1417
categoryName: function() {
1518
var split = this.get('name').split('/');
1619
return split[0] === 'category' ? split[1] : null;
@@ -25,11 +28,11 @@ Discourse.NavItem = Discourse.Model.extend({
2528
}.property('name'),
2629

2730
count: function() {
28-
var state = Discourse.get('currentUser.userTrackingState');
31+
var state = this.get('topicTrackingState');
2932
if (state) {
3033
return state.lookupCount(this.get('name'));
3134
}
32-
}.property('userTrackingState')
35+
}.property('topicTrackingState.messageCount')
3336
});
3437

3538
Discourse.NavItem.reopenClass({

app/assets/javascripts/discourse/models/user_tracking_state.js renamed to app/assets/javascripts/discourse/models/topic_tracking_state.js

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Discourse.UserTrackingState = Discourse.Model.extend({
1+
Discourse.TopicTrackingState = Discourse.Model.extend({
22
messageCount: 0,
33

44
init: function(){
@@ -17,7 +17,7 @@ Discourse.UserTrackingState = Discourse.Model.extend({
1717
tracker.removeTopic(data.topic_id);
1818
}
1919

20-
if (data.message_type === "new_topic") {
20+
if (data.message_type === "new_topic" || data.message_type === "unread") {
2121
tracker.states["t" + data.topic_id] = data.payload;
2222
tracker.notify(data);
2323
}
@@ -26,7 +26,10 @@ Discourse.UserTrackingState = Discourse.Model.extend({
2626
};
2727

2828
Discourse.MessageBus.subscribe("/new", process);
29-
Discourse.MessageBus.subscribe("/unread/" + Discourse.currentUser.id, process);
29+
var currentUser = Discourse.User.current();
30+
if(currentUser) {
31+
Discourse.MessageBus.subscribe("/unread/" + currentUser.id, process);
32+
}
3033
},
3134

3235
notify: function(data){
@@ -62,6 +65,8 @@ Discourse.UserTrackingState = Discourse.Model.extend({
6265
sync: function(list, filter){
6366
var tracker = this;
6467

68+
if(!list || !list.topics || !list.topics.length) { return; }
69+
6570
if(filter === "new" && !list.more_topics_url){
6671
// scrub all new rows and reload from list
6772
$.each(this.states, function(){
@@ -88,15 +93,19 @@ Discourse.UserTrackingState = Discourse.Model.extend({
8893
if(topic.unseen) {
8994
row.last_read_post_number = null;
9095
} else {
91-
row.last_read_post_number = topic.last_read_post_number;
96+
// subtle issue here
97+
row.last_read_post_number = topic.last_read_post_number || topic.highest_post_number;
9298
}
99+
93100
row.highest_post_number = topic.highest_post_number;
94101
if (topic.category) {
95102
row.category_name = topic.category.name;
96103
}
97104

98105
if (row.last_read_post_number === null || row.highest_post_number > row.last_read_post_number) {
99106
tracker.states["t" + topic.id] = row;
107+
} else {
108+
delete tracker.states["t" + topic.id];
100109
}
101110
});
102111

@@ -151,18 +160,28 @@ Discourse.UserTrackingState = Discourse.Model.extend({
151160
// not exposed
152161
var states = this.states;
153162

154-
data.each(function(row){
155-
states["t" + row.topic_id] = row;
156-
});
163+
if(data) {
164+
data.each(function(row){
165+
states["t" + row.topic_id] = row;
166+
});
167+
}
157168
}
158169
});
159170

160171

161-
Discourse.UserTrackingState.reopenClass({
172+
Discourse.TopicTrackingState.reopenClass({
162173
createFromStates: function(data){
163-
var instance = Discourse.UserTrackingState.create();
174+
var instance = Discourse.TopicTrackingState.create();
164175
instance.loadStates(data);
165176
instance.establishChannels();
166177
return instance;
178+
},
179+
current: function(){
180+
if (!this.tracker) {
181+
var data = PreloadStore.get('topicTrackingStates');
182+
this.tracker = this.createFromStates(data);
183+
PreloadStore.remove('topicTrackingStates');
184+
}
185+
return this.tracker;
167186
}
168187
});

app/assets/javascripts/discourse/routes/application_route.js

Lines changed: 0 additions & 24 deletions
This file was deleted.

app/assets/javascripts/discourse/templates/list/topics.js.handlebars

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@
2828
</tr>
2929
</thead>
3030

31-
{{#if Discourse.currentUser.userTrackingState.hasIncoming}}
31+
{{#if view.topicTrackingState.hasIncoming}}
3232
<tbody>
3333
<tr>
3434
<td colspan="9">
3535
<div class='alert alert-info'>
36-
{{countI18n new_topics_inserted countBinding="Discourse.currentUser.userTrackingState.incomingCount"}}
36+
{{countI18n new_topics_inserted countBinding="view.topicTrackingState.incomingCount"}}
3737
<a href='#' {{action showInserted}}>{{i18n show_new_topics}}</a>
3838
</div>
3939
</td>

app/assets/javascripts/discourse/views/list/list_topics_view.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ Discourse.ListTopicsView = Discourse.View.extend(Discourse.Scrolling, {
1414
listBinding: 'controller.model',
1515
loadedMore: false,
1616
currentTopicId: null,
17+
topicTrackingState: function() {
18+
return Discourse.TopicTrackingState.current();
19+
}.property(),
1720

1821
willDestroyElement: function() {
1922
this.unbindScrolling();
@@ -42,8 +45,11 @@ Discourse.ListTopicsView = Discourse.View.extend(Discourse.Scrolling, {
4245
},
4346

4447
showTable: function() {
45-
return this.get('list.topics').length > 0 || Discourse.get('currentUser.userTrackingState.hasIncoming');
46-
}.property('list.topics','Discourse.currentUser.userTrackingState.hasIncoming'),
48+
var topics = this.get('list.topics');
49+
if(topics) {
50+
return this.get('list.topics').length > 0 || this.get('topicTrackingState.hasIncoming');
51+
}
52+
}.property('list.topics','topicTrackingState.hasIncoming'),
4753

4854
loadMore: function() {
4955
var listTopicsView = this;

app/controllers/application_controller.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ def preload_json
107107

108108
if current_user.present?
109109
store_preloaded("currentUser", MultiJson.dump(CurrentUserSerializer.new(current_user, root: false)))
110+
111+
serializer = ActiveModel::ArraySerializer.new(TopicTrackingState.report([current_user.id]), each_serializer: TopicTrackingStateSerializer)
112+
store_preloaded("topicTrackingStates", MultiJson.dump(serializer))
110113
end
111114
store_preloaded("siteSettings", SiteSetting.client_settings_json)
112115
end

app/models/category.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ def allow(group)
133133
end
134134
end
135135

136+
def secure_group_ids
137+
if self.secure
138+
groups.pluck("groups.id")
139+
end
140+
end
141+
136142
end
137143

138144
# == Schema Information
Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,61 @@
33
# the allows end users to always know which topics have unread posts in them
44
# and which topics are new
55

6-
class UserTrackingState
6+
class TopicTrackingState
77

88
include ActiveModel::SerializerSupport
99

1010
CHANNEL = "/user-tracking"
1111

1212
attr_accessor :user_id, :topic_id, :highest_post_number, :last_read_post_number, :created_at, :category_name
1313

14-
MessageBus.client_filter(CHANNEL) do |user_id, message|
15-
if user_id
16-
UserTrackingState.new(User.find(user_id)).filter(message)
17-
else
18-
nil
14+
def self.publish_new(topic)
15+
16+
message = {
17+
topic_id: topic.id,
18+
message_type: "new_topic",
19+
payload: {
20+
last_read_post_number: nil,
21+
highest_post_number: 1,
22+
created_at: topic.created_at,
23+
topic_id: topic.id
24+
}
25+
}
26+
27+
group_ids = topic.category && topic.category.secure_group_ids
28+
29+
MessageBus.publish("/new", message.as_json, group_ids: group_ids)
30+
publish_read(topic.id, 1, topic.user_id)
31+
end
32+
33+
def self.publish_unread(post)
34+
# TODO at high scale we are going to have to defer this,
35+
# perhaps cut down to users that are around in the last 7 days as well
36+
#
37+
group_ids = post.topic.category && post.topic.category.secure_group_ids
38+
39+
TopicUser
40+
.tracking(post.topic_id)
41+
.select([:user_id,:last_read_post_number])
42+
.each do |tu|
43+
44+
message = {
45+
topic_id: post.topic_id,
46+
message_type: "unread",
47+
payload: {
48+
last_read_post_number: tu.last_read_post_number,
49+
highest_post_number: post.post_number,
50+
created_at: post.created_at,
51+
topic_id: post.topic_id
52+
}
53+
}
54+
55+
MessageBus.publish("/unread/#{tu.user_id}", message.as_json, group_ids: group_ids)
56+
1957
end
2058
end
2159

22-
def self.trigger_change(topic_id, post_number, user_id=nil)
23-
MessageBus.publish(CHANNEL, "CHANGE", user_ids: [user_id].compact)
60+
def self.publish_read(topic_id, highest_post_number, user_id)
2461
end
2562

2663
def self.treat_as_new_topic_clause
@@ -76,7 +113,7 @@ def self.report(user_ids, topic_id = nil)
76113
end
77114

78115
SqlBuilder.new(sql)
79-
.map_exec(UserTrackingState, user_ids: user_ids, topic_id: topic_id)
116+
.map_exec(TopicTrackingState, user_ids: user_ids, topic_id: topic_id)
80117

81118
end
82119

0 commit comments

Comments
 (0)