diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js
index aacaae19ab..0cba8ce384 100644
--- a/public/src/forum/topic.js
+++ b/public/src/forum/topic.js
@@ -155,6 +155,46 @@
if (postEls[x].getAttribute('data-deleted') === '1') toggle_post_delete_state(postEls[x].getAttribute('data-pid'));
postEls[x].removeAttribute('data-deleted');
}
+
+ // Follow Thread State
+ var followEl = $('.main-post .follow'),
+ set_follow_state = function(state, quiet) {
+ if (state && !followEl.hasClass('btn-success')) {
+ followEl.addClass('btn-success');
+ followEl[0].title = 'You are currently receiving updates to this topic';
+ if (!quiet) {
+ app.alert({
+ alert_id: 'topic_follow',
+ timeout: 2500,
+ title: 'Following Topic',
+ message: 'You will now be receiving notifications when somebody posts to this topic.',
+ type: 'success'
+ });
+ }
+ } else if (!state && followEl.hasClass('btn-success')) {
+ followEl.removeClass('btn-success');
+ followEl[0].title = 'Be notified of new replies in this topic';
+ if (!quiet) {
+ app.alert({
+ alert_id: 'topic_follow',
+ timeout: 2500,
+ title: 'Not Following Topic',
+ message: 'You will no longer receive notifications from this topic.',
+ type: 'success'
+ });
+ }
+ }
+ };
+ socket.on('api:topic.followCheck', function(state) {
+ set_follow_state(state, true);
+ });
+ socket.on('api:topic.follow', function(data) {
+ set_follow_state(data.follow);
+ });
+ socket.emit('api:topic.followCheck', tid);
+ followEl[0].addEventListener('click', function() {
+ socket.emit('api:topic.follow', tid);
+ }, false);
});
@@ -589,21 +629,46 @@
}
function toggle_post_delete_state(pid) {
- var postEl = $(document.querySelector('#post-container li[data-pid="' + pid + '"]'));
+ var postEl = $(document.querySelector('#post-container li[data-pid="' + pid + '"]'));
+
+ if (postEl[0]) {
quoteEl = $(postEl[0].querySelector('.quote')),
favEl = $(postEl[0].querySelector('.favourite')),
replyEl = $(postEl[0].querySelector('.post_reply'));
- if (!postEl.hasClass('deleted')) {
- quoteEl.addClass('none');
- favEl.addClass('none');
- replyEl.addClass('none');
- } else {
+ socket.once('api:post.privileges', function(privileges) {
+ if (privileges.editable) {
+ if (!postEl.hasClass('deleted')) {
+ toggle_post_tools(pid, false);
+ } else {
+ toggle_post_tools(pid, true);
+ }
+ }
+
+ if (privileges.view_deleted) {
+ postEl.toggleClass('deleted');
+ } else {
+ postEl.toggleClass('none');
+ }
+ });
+ socket.emit('api:post.privileges', pid);
+ }
+ }
+
+ function toggle_post_tools(pid, state) {
+ var postEl = $(document.querySelector('#post-container li[data-pid="' + pid + '"]')),
+ quoteEl = $(postEl[0].querySelector('.quote')),
+ favEl = $(postEl[0].querySelector('.favourite')),
+ replyEl = $(postEl[0].querySelector('.post_reply'));
+
+ if (state) {
quoteEl.removeClass('none');
favEl.removeClass('none');
replyEl.removeClass('none');
+ } else {
+ quoteEl.addClass('none');
+ favEl.addClass('none');
+ replyEl.addClass('none');
}
-
- postEl.toggleClass('deleted');
}
})();
\ No newline at end of file
diff --git a/public/templates/topic.tpl b/public/templates/topic.tpl
index 695366763e..7ad709958d 100644
--- a/public/templates/topic.tpl
+++ b/public/templates/topic.tpl
@@ -31,6 +31,7 @@
{main_posts.username}
+
diff --git a/src/postTools.js b/src/postTools.js
index c8a975aad4..ac1499aa8e 100644
--- a/src/postTools.js
+++ b/src/postTools.js
@@ -1,5 +1,6 @@
var RDB = require('./redis.js'),
posts = require('./posts.js'),
+ topics = require('./topics'),
threadTools = require('./threadTools.js'),
user = require('./user.js'),
async = require('async'),
diff --git a/src/posts.js b/src/posts.js
index 0920d045af..206ea03fd1 100644
--- a/src/posts.js
+++ b/src/posts.js
@@ -199,6 +199,9 @@ marked.setOptions({
timeout: 2000
});
+ // Send notifications to users who are following this topic
+ threadTools.notify_followers(tid, uid);
+
user.getUserFields(uid, ['username','reputation','picture','signature'], function(data) {
var timestamp = new Date().getTime();
diff --git a/src/threadTools.js b/src/threadTools.js
index 391aba631b..77b77aded5 100644
--- a/src/threadTools.js
+++ b/src/threadTools.js
@@ -2,8 +2,8 @@ var RDB = require('./redis.js'),
topics = require('./topics.js'),
categories = require('./categories.js'),
user = require('./user.js'),
- async = require('async');
-
+ async = require('async'),
+ notifications = require('./notifications.js');
(function(ThreadTools) {
@@ -160,4 +160,63 @@ var RDB = require('./redis.js'),
});
}
+ ThreadTools.isFollowing = function(tid, current_user, callback) {
+ RDB.sismember('tid:' + tid + ':followers', current_user, function(err, following) {
+ callback(following);
+ });
+ }
+
+ ThreadTools.toggleFollow = function(tid, current_user, callback) {
+ ThreadTools.isFollowing(tid, current_user, function(following) {
+ if (!following) {
+ RDB.sadd('tid:' + tid + ':followers', current_user, function(err, success) {
+ if (!err) {
+ callback({
+ status: 'ok',
+ follow: true
+ });
+ } else callback({ status: 'error' });
+ });
+ } else {
+ RDB.srem('tid:' + tid + ':followers', current_user, function(err, success) {
+ if (!err) {
+ callback({
+ status: 'ok',
+ follow: false
+ });
+ } else callback({ status: 'error' });
+ });
+ }
+ });
+ }
+
+ ThreadTools.get_followers = function(tid, callback) {
+ RDB.smembers('tid:' + tid + ':followers', function(err, followers) {
+ callback(err, followers);
+ });
+ }
+
+ ThreadTools.notify_followers = function(tid, exceptUid) {
+ async.parallel([
+ function(next) {
+ topics.get_topic(tid, 0, function(threadData) {
+ // console.log(threadData);
+ notifications.create(threadData.teaser_username + ' has posted a reply to: "' + threadData.title + '"', null, '/topic/' + tid, 'topic:' + tid, function(nid) {
+ next(null, nid);
+ });
+ });
+ },
+ function(next) {
+ ThreadTools.get_followers(tid, function(err, followers) {
+ if (followers.indexOf(exceptUid) !== -1) followers.splice(followers.indexOf(exceptUid), 1);
+ next(null, followers);
+ });
+ }
+ ], function(err, results) {
+ if (!err) {
+ notifications.push(results[0], results[1]);
+ }
+ });
+ }
+
}(exports));
\ No newline at end of file
diff --git a/src/webserver.js b/src/webserver.js
index e97779c534..68d8126acb 100644
--- a/src/webserver.js
+++ b/src/webserver.js
@@ -264,9 +264,9 @@ var express = require('express'),
app.get('/api/:method/:id*', api_method);
app.get('/test', function(req, res) {
- meta.config.get(function(config) {
- res.send(JSON.stringify(config, null, 4));
- });
+ var ThreadTools = require('./threadTools.js');
+ ThreadTools.notify_followers(3);
+ res.send();
});
diff --git a/src/websockets.js b/src/websockets.js
index e59784f518..5c222d8787 100644
--- a/src/websockets.js
+++ b/src/websockets.js
@@ -364,6 +364,24 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
})
})
});
+
+ socket.on('api:post.privileges', function(pid) {
+ postTools.privileges(pid, uid, function(privileges) {
+ socket.emit('api:post.privileges', privileges);
+ });
+ });
+
+ socket.on('api:topic.followCheck', function(tid) {
+ threadTools.isFollowing(tid, uid, function(following) {
+ socket.emit('api:topic.followCheck', following);
+ });
+ });
+
+ socket.on('api:topic.follow', function(tid) {
+ threadTools.toggleFollow(tid, uid, function(follow) {
+ if (follow.status === 'ok') socket.emit('api:topic.follow', follow);
+ });
+ });
});
}(SocketIO));