fix: unread badge

- only increase unread badge if topic or category is watched
- fix logic for "there are new posts/topics" on /unread and /recent
v1.18.x
Barış Soner Uşaklı 6 years ago
parent d2c2d56f59
commit 9f5062682d

@ -4,6 +4,12 @@
define('forum/unread', ['topicSelect', 'components', 'topicList'], function (topicSelect, components, topicList) { define('forum/unread', ['topicSelect', 'components', 'topicList'], function (topicSelect, components, topicList) {
var Unread = {}; var Unread = {};
var watchStates = {
ignoring: 1,
notwatching: 2,
watching: 3,
};
Unread.init = function () { Unread.init = function () {
app.enterRoom('unread_topics'); app.enterRoom('unread_topics');
@ -95,8 +101,11 @@ define('forum/unread', ['topicSelect', 'components', 'topicList'], function (top
function onNewPost(data) { function onNewPost(data) {
if (data && data.posts && data.posts.length) { if (data && data.posts && data.posts.length) {
var post = data.posts[0]; var post = data.posts[0];
if (
if (parseInt(post.uid, 10) !== parseInt(app.user.uid, 10) && !unreadTopics[post.topic.tid]) { parseInt(post.uid, 10) !== parseInt(app.user.uid, 10) &&
!unreadTopics[post.topic.tid] &&
(post.topic.isFollowing || post.categoryWatchState === watchStates.watching)
) {
increaseUnreadCount(post); increaseUnreadCount(post);
markTopicsUnread(post.topic.tid); markTopicsUnread(post.topic.tid);
unreadTopics[post.topic.tid] = true; unreadTopics[post.topic.tid] = true;
@ -119,16 +128,10 @@ define('forum/unread', ['topicSelect', 'components', 'topicList'], function (top
var unreadUnrepliedTopicCount = parseInt($('a[href="' + config.relative_path + '/unread?filter=unreplied"].navigation-link i').attr('data-content'), 10) + 1; var unreadUnrepliedTopicCount = parseInt($('a[href="' + config.relative_path + '/unread?filter=unreplied"].navigation-link i').attr('data-content'), 10) + 1;
updateUnreadTopicCount('/unread?filter=unreplied', unreadUnrepliedTopicCount); updateUnreadTopicCount('/unread?filter=unreplied', unreadUnrepliedTopicCount);
} }
if ($('a[href="' + config.relative_path + '/unread?filter=watched"].navigation-link i').length) {
socket.emit('topics.isFollowed', post.topic.tid, function (err, isFollowed) { if (post.topic.isFollowing) {
if (err) { var unreadWatchedTopicCount = parseInt($('a[href="' + config.relative_path + '/unread?filter=watched"].navigation-link i').attr('data-content'), 10) + 1;
return app.alertError(err.message); updateUnreadTopicCount('/unread?filter=watched', unreadWatchedTopicCount);
}
if (isFollowed) {
var unreadWatchedTopicCount = parseInt($('a[href="' + config.relative_path + '/unread?filter=watched"].navigation-link i').attr('data-content'), 10) + 1;
updateUnreadTopicCount('/unread?filter=watched', unreadWatchedTopicCount);
}
});
} }
} }

@ -82,10 +82,19 @@ define('topicList', [
socket.removeListener('event:new_post', onNewPost); socket.removeListener('event:new_post', onNewPost);
}; };
function isCategoryVisible(cid) {
return ajaxify.data.categories && ajaxify.data.categories.length && ajaxify.data.categories.some(function (c) {
return parseInt(c.cid, 10) === parseInt(cid, 10);
});
}
function onNewTopic(data) { function onNewTopic(data) {
if ((ajaxify.data.selectedCids && ajaxify.data.selectedCids.length && ajaxify.data.selectedCids.indexOf(parseInt(data.cid, 10)) === -1) || if (
(ajaxify.data.selectedCids && ajaxify.data.selectedCids.length && ajaxify.data.selectedCids.indexOf(parseInt(data.cid, 10)) === -1) ||
(ajaxify.data.selectedFilter && ajaxify.data.selectedFilter.filter === 'watched') || (ajaxify.data.selectedFilter && ajaxify.data.selectedFilter.filter === 'watched') ||
(ajaxify.data.template.category && parseInt(ajaxify.data.cid, 10) !== parseInt(data.cid, 10))) { (ajaxify.data.template.category && parseInt(ajaxify.data.cid, 10) !== parseInt(data.cid, 10)) ||
(!isCategoryVisible(data.cid))
) {
return; return;
} }
@ -94,35 +103,23 @@ define('topicList', [
} }
function onNewPost(data) { function onNewPost(data) {
function showAlert() {
newPostCount += 1;
updateAlertText();
}
var post = data.posts[0]; var post = data.posts[0];
if ( if (!post || !post.topic) {
(!post || !post.topic) || return;
}
if (!post.topic.isFollowing && (
(parseInt(post.topic.mainPid, 10) === parseInt(post.pid, 10)) || (parseInt(post.topic.mainPid, 10) === parseInt(post.pid, 10)) ||
(ajaxify.data.selectedCids && ajaxify.data.selectedCids.length && ajaxify.data.selectedCids.indexOf(parseInt(post.topic.cid, 10)) === -1) || (ajaxify.data.selectedCids && ajaxify.data.selectedCids.length && ajaxify.data.selectedCids.indexOf(parseInt(post.topic.cid, 10)) === -1) ||
(ajaxify.data.selectedFilter && ajaxify.data.selectedFilter.filter === 'new') || (ajaxify.data.selectedFilter && ajaxify.data.selectedFilter.filter === 'new') ||
(ajaxify.data.template.category && parseInt(ajaxify.data.cid, 10) !== parseInt(post.topic.cid, 10)) (ajaxify.data.selectedFilter && ajaxify.data.selectedFilter.filter === 'watched' && !post.topic.isFollowing) ||
) { (ajaxify.data.template.category && parseInt(ajaxify.data.cid, 10) !== parseInt(post.topic.cid, 10)) ||
(!isCategoryVisible(post.topic.cid))
)) {
return; return;
} }
if (ajaxify.data.selectedFilter && ajaxify.data.selectedFilter.filter === 'watched') { newPostCount += 1;
socket.emit('topics.isFollowed', post.tid, function (err, isFollowed) { updateAlertText();
if (err) {
app.alertError(err.message);
}
if (isFollowed) {
showAlert();
}
});
return;
}
showAlert();
} }
function updateAlertText() { function updateAlertText() {

@ -41,7 +41,7 @@ profileController.get = function (req, res, callback) {
} }
userData = _userData; userData = _userData;
if (!req.isSpider()) { if (req.uid >= 0) {
req.session.uids_viewed = req.session.uids_viewed || {}; req.session.uids_viewed = req.session.uids_viewed || {};
if (req.uid !== userData.uid && (!req.session.uids_viewed[userData.uid] || req.session.uids_viewed[userData.uid] < Date.now() - 3600000)) { if (req.uid !== userData.uid && (!req.session.uids_viewed[userData.uid] || req.session.uids_viewed[userData.uid] < Date.now() - 3600000)) {

@ -57,7 +57,7 @@ apiController.loadConfig = function (req, callback) {
config.requireEmailConfirmation = meta.config.requireEmailConfirmation === 1; config.requireEmailConfirmation = meta.config.requireEmailConfirmation === 1;
config.topicPostSort = meta.config.topicPostSort || 'oldest_to_newest'; config.topicPostSort = meta.config.topicPostSort || 'oldest_to_newest';
config.categoryTopicSort = meta.config.categoryTopicSort || 'newest_to_oldest'; config.categoryTopicSort = meta.config.categoryTopicSort || 'newest_to_oldest';
config.csrf_token = !req.isSpider() && req.csrfToken && req.csrfToken(); config.csrf_token = req.uid >= 0 && req.csrfToken && req.csrfToken();
config.searchEnabled = plugins.hasListeners('filter:search.query'); config.searchEnabled = plugins.hasListeners('filter:search.query');
config.bootswatchSkin = meta.config.bootswatchSkin || ''; config.bootswatchSkin = meta.config.bootswatchSkin || '';
config.enablePostHistory = (meta.config.enablePostHistory || 1) === 1; config.enablePostHistory = (meta.config.enablePostHistory || 1) === 1;

@ -161,7 +161,7 @@ topicsController.get = function (req, res, callback) {
res.locals.linkTags.push(rel); res.locals.linkTags.push(rel);
}); });
if (!req.isSpider()) { if (req.uid >= 0) {
req.session.tids_viewed = req.session.tids_viewed || {}; req.session.tids_viewed = req.session.tids_viewed || {};
if (!req.session.tids_viewed[tid] || req.session.tids_viewed[tid] < Date.now() - 3600000) { if (!req.session.tids_viewed[tid] || req.session.tids_viewed[tid] < Date.now() - 3600000) {
topics.increaseViewCount(tid); topics.increaseViewCount(tid);

@ -26,7 +26,7 @@ module.exports = function (middleware) {
res.locals.isAPI = false; res.locals.isAPI = false;
async.waterfall([ async.waterfall([
function (next) { function (next) {
if (!req.isSpider()) { if (req.uid >= 0) {
middleware.applyCSRF(req, res, next); middleware.applyCSRF(req, res, next);
} else { } else {
setImmediate(next); setImmediate(next);
@ -241,7 +241,7 @@ module.exports = function (middleware) {
data.templateValues.useCustomJS = meta.config.useCustomJS; data.templateValues.useCustomJS = meta.config.useCustomJS;
data.templateValues.customJS = data.templateValues.useCustomJS ? meta.config.customJS : ''; data.templateValues.customJS = data.templateValues.useCustomJS ? meta.config.customJS : '';
data.templateValues.isSpider = req.isSpider(); data.templateValues.isSpider = req.uid === -1;
req.app.render('footer', data.templateValues, next); req.app.render('footer', data.templateValues, next);
}, },
], callback); ], callback);

@ -9,7 +9,7 @@ module.exports = function (app, middleware, controllers) {
app.use('/api', router); app.use('/api', router);
router.get('/config', function (req, res, next) { router.get('/config', function (req, res, next) {
if (!req.isSpider()) { if (req.uid >= 0) {
middleware.applyCSRF(req, res, next); middleware.applyCSRF(req, res, next);
} else { } else {
setImmediate(next); setImmediate(next);

@ -2,6 +2,7 @@
var async = require('async'); var async = require('async');
var winston = require('winston'); var winston = require('winston');
var _ = require('lodash');
var db = require('../database'); var db = require('../database');
var websockets = require('./index'); var websockets = require('./index');
@ -17,21 +18,32 @@ var utils = require('../utils');
var SocketHelpers = module.exports; var SocketHelpers = module.exports;
SocketHelpers.notifyNew = function (uid, type, result) { SocketHelpers.notifyNew = function (uid, type, result) {
let watchStateUids;
let categoryWatchStates;
let topicFollowState;
const post = result.posts[0];
const tid = post.topic.tid;
const cid = post.topic.cid;
async.waterfall([ async.waterfall([
function (next) { function (next) {
user.getUidsFromSet('users:online', 0, -1, next); user.getUidsFromSet('users:online', 0, -1, next);
}, },
function (uids, next) { function (uids, next) {
privileges.topics.filterUids('read', result.posts[0].topic.tid, uids, next); uids = uids.filter(uid => parseInt(uid, 10) !== uid);
privileges.topics.filterUids('read', tid, uids, next);
}, },
function (uids, next) { function (uids, next) {
filterTidCidIgnorers(uids, result.posts[0].topic.tid, result.posts[0].topic.cid, next); watchStateUids = uids;
getWatchStates(watchStateUids, tid, cid, next);
}, },
function (uids, next) { function (watchStates, next) {
categoryWatchStates = _.zipObject(watchStateUids, watchStates.categoryWatchStates);
topicFollowState = _.zipObject(watchStateUids, watchStates.topicFollowed);
const uids = filterTidCidIgnorers(watchStateUids, watchStates);
user.blocks.filterUids(uid, uids, next); user.blocks.filterUids(uid, uids, next);
}, },
function (uids, next) { function (uids, next) {
user.blocks.filterUids(result.posts[0].topic.uid, uids, next); user.blocks.filterUids(post.topic.uid, uids, next);
}, },
function (uids, next) { function (uids, next) {
plugins.fireHook('filter:sockets.sendNewPostToUids', { uidsTo: uids, uidFrom: uid, type: type }, next); plugins.fireHook('filter:sockets.sendNewPostToUids', { uidsTo: uids, uidFrom: uid, type: type }, next);
@ -41,42 +53,38 @@ SocketHelpers.notifyNew = function (uid, type, result) {
return winston.error(err.stack); return winston.error(err.stack);
} }
result.posts[0].ip = undefined; post.ip = undefined;
data.uidsTo.forEach(function (toUid) { data.uidsTo.forEach(function (toUid) {
if (parseInt(toUid, 10) !== uid) { post.categoryWatchState = categoryWatchStates[toUid];
websockets.in('uid_' + toUid).emit('event:new_post', result); post.topic.isFollowing = topicFollowState[toUid];
if (result.topic && type === 'newTopic') { websockets.in('uid_' + toUid).emit('event:new_post', result);
websockets.in('uid_' + toUid).emit('event:new_topic', result.topic); if (result.topic && type === 'newTopic') {
} websockets.in('uid_' + toUid).emit('event:new_topic', result.topic);
} }
}); });
}); });
}; };
function filterTidCidIgnorers(uids, tid, cid, callback) { function getWatchStates(uids, tid, cid, callback) {
async.waterfall([ async.parallel({
function (next) { topicFollowed: function (next) {
async.parallel({ db.isSetMembers('tid:' + tid + ':followers', uids, next);
topicFollowed: function (next) {
db.isSetMembers('tid:' + tid + ':followers', uids, next);
},
topicIgnored: function (next) {
db.isSetMembers('tid:' + tid + ':ignorers', uids, next);
},
categoryWatchStates: function (next) {
categories.getUidsWatchStates(cid, uids, next);
},
}, next);
}, },
function (results, next) { topicIgnored: function (next) {
uids = uids.filter(function (uid, index) { db.isSetMembers('tid:' + tid + ':ignorers', uids, next);
return results.topicFollowed[index] || },
(!results.topicIgnored[index] && results.categoryWatchStates[index] !== categories.watchStates.ignoring); categoryWatchStates: function (next) {
}); categories.getUidsWatchStates(cid, uids, next);
next(null, uids);
}, },
], callback); }, callback);
}
function filterTidCidIgnorers(uids, watchStates) {
return uids.filter(function (uid, index) {
return watchStates.topicFollowed[index] ||
(!watchStates.topicIgnored[index] && watchStates.categoryWatchStates[index] !== categories.watchStates.ignoring);
});
} }
SocketHelpers.sendNotificationToPostOwner = function (pid, fromuid, command, notification) { SocketHelpers.sendNotificationToPostOwner = function (pid, fromuid, command, notification) {

Loading…
Cancel
Save