Skip to content

Commit

Permalink
Merge b44fb1c into f3e8e06
Browse files Browse the repository at this point in the history
  • Loading branch information
barisusakli committed Dec 14, 2018
2 parents f3e8e06 + b44fb1c commit 9b051f3
Show file tree
Hide file tree
Showing 28 changed files with 374 additions and 134 deletions.
3 changes: 2 additions & 1 deletion install/data/defaults.json
Expand Up @@ -116,5 +116,6 @@
"eventLoopLagThreshold": 100,
"eventLoopInterval": 500,
"onlineCutoff": 30,
"timeagoCutoff": 30
"timeagoCutoff": 30,
"categoryWatchState": "watching"
}
6 changes: 5 additions & 1 deletion public/language/en-GB/admin/settings/user.json
Expand Up @@ -70,5 +70,9 @@
"email-post-notif": "Send an email when replies are made to topics I am subscribed to",
"follow-created-topics": "Follow topics you create",
"follow-replied-topics": "Follow topics that you reply to",
"default-notification-settings": "Default notification settings"
"default-notification-settings": "Default notification settings",
"categoryWatchState": "Default category watch state",
"categoryWatchState.watching": "Watching",
"categoryWatchState.notwatching": "Not Watching",
"categoryWatchState.ignoring": "Ignoring"
}
12 changes: 7 additions & 5 deletions public/language/en-GB/category.json
Expand Up @@ -10,16 +10,18 @@
"no_replies": "No one has replied",
"no_new_posts": "No new posts.",

"share_this_category": "Share this category",
"watch": "Watch",
"ignore": "Ignore",
"watching": "Watching",
"not-watching": "Not Watching",
"ignoring": "Ignoring",
"watching.description": "Show topics in unread",
"ignoring.description": "Do not show topics in unread",
"watching.description": "Show topics in unread and recent",
"not-watching.description": "Do not show topics in unread, show in recent",
"ignoring.description": "Do not show topics in unread and recent",

"watch.message": "You are now watching updates from this category and all subcategories",
"ignore.message": "You are now ignoring updates from this category and all subcategories",
"watching.message": "You are now watching updates from this category and all subcategories",
"notwatching.message": "You are not watching updates from this category and all subcategories",
"ignoring.message": "You are now ignoring updates from this category and all subcategories",

"watched-categories": "Watched categories"
}
1 change: 1 addition & 0 deletions public/language/en-GB/user.json
Expand Up @@ -30,6 +30,7 @@
"watched_categories": "Watched categories",
"watched": "Watched",
"ignored": "Ignored",
"default-category-watch-state": "Default category watch state",
"followers": "Followers",
"following": "Following",
"blocks": "Blocks",
Expand Down
19 changes: 11 additions & 8 deletions public/src/client/account/categories.js
Expand Up @@ -14,25 +14,28 @@ define('forum/account/categories', ['forum/account/header'], function (header) {

function handleIgnoreWatch(cid) {
var category = $('[data-cid="' + cid + '"]');
category.find('[component="category/watching"], [component="category/ignoring"]').on('click', function () {
category.find('[component="category/watching"], [component="category/ignoring"], [component="category/notwatching"]').on('click', function () {
var $this = $(this);
var command = $this.attr('component') === 'category/watching' ? 'watch' : 'ignore';
var state = $this.attr('data-state');

socket.emit('categories.' + command, { cid: cid, uid: ajaxify.data.uid }, function (err, modified_cids) {
socket.emit('categories.setWatchState', { cid: cid, state: state, uid: ajaxify.data.uid }, function (err, modified_cids) {
if (err) {
return app.alertError(err.message);
}

modified_cids.forEach(function (cid) {
var category = $('[data-cid="' + cid + '"]');
category.find('[component="category/watching/menu"]').toggleClass('hidden', command !== 'watch');
category.find('[component="category/watching/check"]').toggleClass('fa-check', command === 'watch');
category.find('[component="category/watching/menu"]').toggleClass('hidden', state !== 'watching');
category.find('[component="category/watching/check"]').toggleClass('fa-check', state === 'watching');

category.find('[component="category/ignoring/menu"]').toggleClass('hidden', command !== 'ignore');
category.find('[component="category/ignoring/check"]').toggleClass('fa-check', command === 'ignore');
category.find('[component="category/notwatching/menu"]').toggleClass('hidden', state !== 'notwatching');
category.find('[component="category/notwatching/check"]').toggleClass('fa-check', state === 'notwatching');

category.find('[component="category/ignoring/menu"]').toggleClass('hidden', state !== 'ignoring');
category.find('[component="category/ignoring/check"]').toggleClass('fa-check', state === 'ignoring');
});

app.alertSuccess('[[category:' + command + '.message]]');
app.alertSuccess('[[category:' + state + '.message]]');
});
});
}
Expand Down
19 changes: 11 additions & 8 deletions public/src/client/category.js
Expand Up @@ -62,22 +62,25 @@ define('forum/category', [
}

function handleIgnoreWatch(cid) {
$('[component="category/watching"], [component="category/ignoring"]').on('click', function () {
$('[component="category/watching"], [component="category/ignoring"], [component="category/notwatching"]').on('click', function () {
var $this = $(this);
var command = $this.attr('component') === 'category/watching' ? 'watch' : 'ignore';
var state = $this.attr('data-state');

socket.emit('categories.' + command, cid, function (err) {
socket.emit('categories.setWatchState', { cid: cid, state: state }, function (err) {
if (err) {
return app.alertError(err.message);
}

$('[component="category/watching/menu"]').toggleClass('hidden', command !== 'watch');
$('[component="category/watching/check"]').toggleClass('fa-check', command === 'watch');
$('[component="category/watching/menu"]').toggleClass('hidden', state !== 'watching');
$('[component="category/watching/check"]').toggleClass('fa-check', state === 'watching');

$('[component="category/ignoring/menu"]').toggleClass('hidden', command !== 'ignore');
$('[component="category/ignoring/check"]').toggleClass('fa-check', command === 'ignore');
$('[component="category/notwatching/menu"]').toggleClass('hidden', state !== 'notwatching');
$('[component="category/notwatching/check"]').toggleClass('fa-check', state === 'notwatching');

app.alertSuccess('[[category:' + command + '.message]]');
$('[component="category/ignoring/menu"]').toggleClass('hidden', state !== 'ignoring');
$('[component="category/ignoring/check"]').toggleClass('fa-check', state === 'ignoring');

app.alertSuccess('[[category:' + state + '.message]]');
});
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/categories/delete.js
Expand Up @@ -52,7 +52,7 @@ module.exports = function (Categories) {
'cid:' + cid + ':tids:posts',
'cid:' + cid + ':pids',
'cid:' + cid + ':read_by_uid',
'cid:' + cid + ':ignorers',
'cid:' + cid + ':uid:watch:state',
'cid:' + cid + ':children',
'cid:' + cid + ':tag:whitelist',
'category:' + cid,
Expand Down
33 changes: 6 additions & 27 deletions src/categories/index.js
Expand Up @@ -21,6 +21,7 @@ require('./unread')(Categories);
require('./activeusers')(Categories);
require('./recentreplies')(Categories);
require('./update')(Categories);
require('./watch')(Categories);

Categories.exists = function (cid, callback) {
db.exists('category:' + cid, callback);
Expand All @@ -45,8 +46,8 @@ Categories.getCategoryById = function (data, callback) {
topicCount: function (next) {
Categories.getTopicCount(data, next);
},
isIgnored: function (next) {
Categories.isIgnored([data.cid], data.uid, next);
watchState: function (next) {
Categories.getWatchState([data.cid], data.uid, next);
},
parent: function (next) {
if (category.parentCid) {
Expand All @@ -64,7 +65,9 @@ Categories.getCategoryById = function (data, callback) {
category.topics = results.topics.topics;
category.nextStart = results.topics.nextStart;
category.topic_count = results.topicCount;
category.isIgnored = results.isIgnored[0];
category.isWatched = results.watchState[0] === Categories.watchStates.watching;
category.isNotWatched = results.watchState[0] === Categories.watchStates.notwatching;
category.isIgnored = results.watchState[0] === Categories.watchStates.ignoring;
category.parent = results.parent;

calculateTopicPostCount(category);
Expand All @@ -76,14 +79,6 @@ Categories.getCategoryById = function (data, callback) {
], callback);
};

Categories.isIgnored = function (cids, uid, callback) {
if (parseInt(uid, 10) <= 0) {
return setImmediate(callback, null, cids.map(() => false));
}
const keys = cids.map(cid => 'cid:' + cid + ':ignorers');
db.isMemberOfSortedSets(keys, uid, callback);
};

Categories.getAllCidsFromSet = function (key, callback) {
const cids = cache.get(key);
if (cids) {
Expand Down Expand Up @@ -443,20 +438,4 @@ Categories.buildForSelectCategories = function (categories, callback) {
callback(null, categoriesData);
};

Categories.getIgnorers = function (cid, start, stop, callback) {
db.getSortedSetRevRange('cid:' + cid + ':ignorers', start, stop, callback);
};

Categories.filterIgnoringUids = function (cid, uids, callback) {
async.waterfall([
function (next) {
db.isSortedSetMembers('cid:' + cid + ':ignorers', uids, next);
},
function (isIgnoring, next) {
const readingUids = uids.filter((uid, index) => uid && !isIgnoring[index]);
next(null, readingUids);
},
], callback);
};

Categories.async = require('../promisify')(Categories);
80 changes: 80 additions & 0 deletions src/categories/watch.js
@@ -0,0 +1,80 @@
'use strict';

const async = require('async');

const db = require('../database');
const user = require('../user');

module.exports = function (Categories) {
Categories.watchStates = {
ignoring: 1,
notwatching: 2,
watching: 3,
};

Categories.isIgnored = function (cids, uid, callback) {
if (!(parseInt(uid, 10) > 0)) {
return setImmediate(callback, null, cids.map(() => false));
}
async.waterfall([
function (next) {
Categories.getWatchState(cids, uid, next);
},
function (states, next) {
next(null, states.map(state => state === Categories.watchStates.ignoring));
},
], callback);
};

Categories.getWatchState = function (cids, uid, callback) {
if (!(parseInt(uid, 10) > 0)) {
return setImmediate(callback, null, cids.map(() => Categories.watchStates.notwatching));
}
if (!Array.isArray(cids) || !cids.length) {
return setImmediate(callback, null, []);
}
async.waterfall([
function (next) {
const keys = cids.map(cid => 'cid:' + cid + ':uid:watch:state');
async.parallel({
userSettings: async.apply(user.getSettings, uid),
states: async.apply(db.sortedSetsScore, keys, uid),
}, next);
},
function (results, next) {
next(null, results.states.map(state => state || Categories.watchStates[results.userSettings.categoryWatchState]));
},
], callback);
};

Categories.getIgnorers = function (cid, start, stop, callback) {
const count = (stop === -1) ? -1 : (stop - start + 1);
db.getSortedSetRevRangeByScore('cid:' + cid + ':uid:watch:state', start, count, Categories.watchStates.ignoring, Categories.watchStates.ignoring, callback);
};

Categories.filterIgnoringUids = function (cid, uids, callback) {
async.waterfall([
function (next) {
Categories.getUidsWatchStates(cid, uids, next);
},
function (states, next) {
const readingUids = uids.filter((uid, index) => uid && states[index] !== Categories.watchStates.ignoring);
next(null, readingUids);
},
], callback);
};

Categories.getUidsWatchStates = function (cid, uids, callback) {
async.waterfall([
function (next) {
async.parallel({
userSettings: async.apply(user.getMultipleUserSettings, uids),
states: async.apply(db.sortedSetScores, 'cid:' + cid + ':uid:watch:state', uids),
}, next);
},
function (results, next) {
next(null, results.states.map((state, index) => state || Categories.watchStates[results.userSettings[index].categoryWatchState]));
},
], callback);
};
};
8 changes: 5 additions & 3 deletions src/controllers/accounts/categories.js
Expand Up @@ -21,8 +21,8 @@ categoriesController.get = function (req, res, callback) {
}

async.parallel({
ignored: function (next) {
user.getIgnoredCategories(userData.uid, next);
states: function (next) {
user.getCategoryWatchState(userData.uid, next);
},
categories: function (next) {
categories.buildForSelect(userData.uid, 'find', next);
Expand All @@ -32,7 +32,9 @@ categoriesController.get = function (req, res, callback) {
function (results) {
results.categories.forEach(function (category) {
if (category) {
category.isIgnored = results.ignored.includes(String(category.cid));
category.isIgnored = results.states[category.cid] === categories.watchStates.ignoring;
category.isWatched = results.states[category.cid] === categories.watchStates.watching;
category.isNotWatched = results.states[category.cid] === categories.watchStates.notwatching;
}
});
userData.categories = results.categories;
Expand Down
2 changes: 2 additions & 0 deletions src/controllers/accounts/settings.js
Expand Up @@ -161,6 +161,8 @@ settingsController.get = function (req, res, callback) {
};
});

userData.categoryWatchState = { [userData.settings.categoryWatchState]: true };

userData.disableCustomUserSkins = meta.config.disableCustomUserSkins;

userData.allowUserHomePage = meta.config.allowUserHomePage;
Expand Down
14 changes: 14 additions & 0 deletions src/controllers/helpers.js
Expand Up @@ -239,6 +239,20 @@ helpers.getCategories = function (set, uid, privilege, selectedCid, callback) {
], callback);
};

helpers.getCategoriesByStates = function (uid, selectedCid, states, callback) {
async.waterfall([
function (next) {
user.getCategoriesByStates(uid, states, next);
},
function (cids, next) {
privileges.categories.filterCids('read', cids, uid, next);
},
function (cids, next) {
getCategoryData(cids, uid, selectedCid, next);
},
], callback);
};

helpers.getWatchedCategories = function (uid, selectedCid, callback) {
async.waterfall([
function (next) {
Expand Down
7 changes: 4 additions & 3 deletions src/controllers/recent.js
Expand Up @@ -5,6 +5,7 @@ var async = require('async');
var nconf = require('nconf');

var user = require('../user');
var categories = require('../categories');
var topics = require('../topics');
var meta = require('../meta');
var helpers = require('./helpers');
Expand Down Expand Up @@ -47,8 +48,8 @@ recentController.getData = function (req, url, sort, callback) {
settings: function (next) {
user.getSettings(req.uid, next);
},
watchedCategories: function (next) {
helpers.getWatchedCategories(req.uid, cid, next);
categories: function (next) {
helpers.getCategoriesByStates(req.uid, cid, [categories.watchStates.watching, categories.watchStates.notwatching], next);
},
rssToken: function (next) {
user.auth.getFeedToken(req.uid, next);
Expand All @@ -58,7 +59,7 @@ recentController.getData = function (req, url, sort, callback) {
function (results, next) {
rssToken = results.rssToken;
settings = results.settings;
categoryData = results.watchedCategories;
categoryData = results.categories;

var start = Math.max(0, (page - 1) * settings.topicsPerPage);
stop = start + settings.topicsPerPage - 1;
Expand Down
3 changes: 2 additions & 1 deletion src/controllers/unread.js
Expand Up @@ -8,6 +8,7 @@ var querystring = require('querystring');
var meta = require('../meta');
var pagination = require('../pagination');
var user = require('../user');
var categories = require('../categories');
var topics = require('../topics');
var plugins = require('../plugins');
var helpers = require('./helpers');
Expand Down Expand Up @@ -35,7 +36,7 @@ unreadController.get = function (req, res, next) {
if (plugins.hasListeners('filter:unread.categories')) {
plugins.fireHook('filter:unread.categories', { uid: req.uid, cid: cid }, next);
} else {
helpers.getWatchedCategories(req.uid, cid, next);
helpers.getCategoriesByStates(req.uid, cid, [categories.watchStates.watching], next);
}
},
settings: function (next) {
Expand Down

0 comments on commit 9b051f3

Please sign in to comment.