also fix reverse infinite scroll when sorting is changed
v1.18.x
Baris Usakli 8 years ago
parent 1d26fc0d89
commit 037a0e5239

@ -264,7 +264,7 @@ define('forum/category', [
var topics = $('[component="category/topic"]');
var afterEl = direction > 0 ? topics.last() : topics.first();
var after = (parseInt(afterEl.attr('data-index'), 10) || 0) + 1;
var after = (parseInt(afterEl.attr('data-index'), 10) || 0) + (direction > 0 ? 1 : 0);
loadTopicsAfter(after, direction);
};
@ -281,8 +281,7 @@ define('forum/category', [
cid: ajaxify.data.cid,
after: after,
direction: direction,
author: params.author,
tag: params.tag,
query: params,
categoryTopicSort: config.categoryTopicSort,
}, function (data, done) {
if (data.topics && data.topics.length) {

@ -35,17 +35,13 @@ Categories.getCategoryById = function (data, callback) {
return next(new Error('[[error:invalid-cid]]'));
}
category = categories[0];
data.category = category;
async.parallel({
topics: function (next) {
Categories.getCategoryTopics(data, next);
},
topicCount: function (next) {
if (Array.isArray(data.set)) {
db.sortedSetIntersectCard(data.set, next);
} else {
next(null, category.topic_count);
}
Categories.getTopicCount(data, next);
},
isIgnored: function (next) {
Categories.isIgnored([data.cid], data.uid, next);

@ -5,6 +5,7 @@ var async = require('async');
var db = require('../database');
var topics = require('../topics');
var plugins = require('../plugins');
var meta = require('../meta');
module.exports = function (Categories) {
Categories.getCategoryTopics = function (data, callback) {
@ -37,40 +38,52 @@ module.exports = function (Categories) {
Categories.getTopicIds = function (data, callback) {
var pinnedTids;
var pinnedCount;
var totalPinnedCount;
var start = data.start;
var stop = data.stop;
var set = data.set;
async.waterfall([
function (next) {
Categories.getPinnedTids(data.cid, 0, -1, next);
},
function (_pinnedTids, next) {
totalPinnedCount = _pinnedTids.length;
var totalPinnedCount = _pinnedTids.length;
pinnedTids = _pinnedTids.slice(start, stop === -1 ? undefined : stop + 1);
pinnedTids = _pinnedTids.slice(data.start, data.stop === -1 ? undefined : data.stop + 1);
pinnedCount = pinnedTids.length;
var pinnedCount = pinnedTids.length;
var topicsPerPage = stop - start + 1;
var topicsPerPage = data.stop - data.start + 1;
var normalTidsToGet = Math.max(0, topicsPerPage - pinnedCount);
if (!normalTidsToGet && stop !== -1) {
if (!normalTidsToGet && data.stop !== -1) {
return next(null, []);
}
if (plugins.hasListeners('filter:categories.getTopicIds')) {
return plugins.fireHook('filter:categories.getTopicIds', {
tids: [],
data: data,
pinnedTids: pinnedTids,
allPinnedTids: _pinnedTids,
totalPinnedCount: totalPinnedCount,
normalTidsToGet: normalTidsToGet,
}, function (err, data) {
callback(err, data && data.tids);
});
}
var set = Categories.buildTopicsSortedSet(data);
var reverse = Categories.getSortedSetRangeDirection(data.sort);
var start = data.start;
if (start > 0 && totalPinnedCount) {
start -= totalPinnedCount - pinnedCount;
}
stop = stop === -1 ? stop : start + normalTidsToGet - 1;
var stop = data.stop === -1 ? data.stop : start + normalTidsToGet - 1;
if (Array.isArray(set)) {
db[data.reverse ? 'getSortedSetRevIntersect' : 'getSortedSetIntersect']({ sets: set, start: start, stop: stop }, next);
db[reverse ? 'getSortedSetRevIntersect' : 'getSortedSetIntersect']({ sets: set, start: start, stop: stop }, next);
} else {
db[data.reverse ? 'getSortedSetRevRange' : 'getSortedSetRange'](set, start, stop, next);
db[reverse ? 'getSortedSetRevRange' : 'getSortedSetRange'](set, start, stop, next);
}
},
function (normalTids, next) {
@ -83,6 +96,54 @@ module.exports = function (Categories) {
], callback);
};
Categories.getTopicCount = function (data, callback) {
if (plugins.hasListeners('filter:categories.getTopicCount')) {
return plugins.fireHook('filter:categories.getTopicCount', {
topicCount: data.category.topic_count,
data: data,
}, function (err, data) {
callback(err, data && data.topicCount);
});
}
var set = Categories.buildTopicsSortedSet(data);
if (Array.isArray(set)) {
db.sortedSetIntersectCard(set, callback);
} else {
callback(null, data.category.topic_count);
}
};
Categories.buildTopicsSortedSet = function (data) {
var cid = data.cid;
var set = 'cid:' + cid + ':tids';
var sort = data.sort || (data.settings && data.settings.categoryTopicSort) || meta.config.categoryTopicSort || 'newest_to_oldest';
if (sort === 'most_posts') {
set = 'cid:' + cid + ':tids:posts';
}
if (data.targetUid) {
set = 'cid:' + cid + ':uid:' + data.targetUid + ':tids';
}
if (data.tag) {
if (Array.isArray(data.tag)) {
set = [set].concat(data.tag.map(function (tag) {
return 'tag:' + tag + ':topics';
}));
} else {
set = [set, 'tag:' + data.tag + ':topics'];
}
}
return set;
};
Categories.getSortedSetRangeDirection = function (sort) {
sort = sort || 'newest_to_oldest';
var reverse = sort === 'newest_to_oldest' || sort === 'most_posts';
return reverse;
};
Categories.getAllTopicIds = function (cid, start, stop, callback) {
db.getSortedSetRange(['cid:' + cid + ':tids:pinned', 'cid:' + cid + ':tids'], start, stop, callback);
};

@ -77,49 +77,27 @@ categoryController.get = function (req, res, callback) {
topicIndex = 0;
}
var set = 'cid:' + cid + ':tids';
var reverse = false;
// `sort` qs has priority over user setting
var sort = req.query.sort || settings.categoryTopicSort;
if (sort === 'newest_to_oldest') {
reverse = true;
} else if (sort === 'most_posts') {
reverse = true;
set = 'cid:' + cid + ':tids:posts';
}
var start = ((currentPage - 1) * settings.topicsPerPage) + topicIndex;
var stop = start + settings.topicsPerPage - 1;
var payload = {
cid: cid,
set: set,
reverse: reverse,
start: start,
stop: stop,
uid: req.uid,
settings: settings,
};
async.waterfall([
function (next) {
user.getUidByUserslug(req.query.author, next);
},
function (uid, next) {
payload.targetUid = uid;
if (uid) {
payload.set = 'cid:' + cid + ':uid:' + uid + ':tids';
}
if (req.query.tag) {
if (Array.isArray(req.query.tag)) {
payload.set = [payload.set].concat(req.query.tag.map(function (tag) {
return 'tag:' + tag + ':topics';
}));
} else {
payload.set = [payload.set, 'tag:' + req.query.tag + ':topics'];
}
}
function (targetUid, next) {
var payload = {
uid: req.uid,
cid: cid,
start: start,
stop: stop,
sort: sort,
settings: settings,
query: req.query,
tag: req.query.tag,
targetUid: targetUid,
};
categories.getCategoryById(payload, next);
},
], next);

@ -59,6 +59,7 @@ SocketCategories.loadMore = function (socket, data, callback) {
if (!data) {
return callback(new Error('[[error:invalid-data]]'));
}
data.query = data.query || {};
var userPrivileges;
async.waterfall([
function (next) {
@ -70,8 +71,8 @@ SocketCategories.loadMore = function (socket, data, callback) {
user.getSettings(socket.uid, next);
},
targetUid: function (next) {
if (data.author) {
user.getUidByUserslug(data.author, next);
if (data.query.author) {
user.getUidByUserslug(data.query.author, next);
} else {
next();
}
@ -84,44 +85,28 @@ SocketCategories.loadMore = function (socket, data, callback) {
return callback(new Error('[[error:no-privileges]]'));
}
var infScrollTopicsPerPage = 20;
var set = 'cid:' + data.cid + ':tids';
var reverse = false;
if (data.categoryTopicSort === 'newest_to_oldest') {
reverse = true;
} else if (data.categoryTopicSort === 'most_posts') {
reverse = true;
set = 'cid:' + data.cid + ':tids:posts';
}
var sort = data.sort || data.categoryTopicSort;
var start = Math.max(0, parseInt(data.after, 10));
if (data.direction === -1) {
start -= reverse ? infScrollTopicsPerPage : -infScrollTopicsPerPage;
start -= infScrollTopicsPerPage;
}
var stop = start + infScrollTopicsPerPage - 1;
start = Math.max(0, start);
stop = Math.max(0, stop);
if (results.targetUid) {
set = 'cid:' + data.cid + ':uid:' + results.targetUid + ':tids';
}
if (data.tag) {
set = [set, 'tag:' + data.tag + ':topics'];
}
categories.getCategoryTopics({
uid: socket.uid,
cid: data.cid,
set: set,
reverse: reverse,
start: start,
stop: stop,
uid: socket.uid,
targetUid: results.targetUid,
sort: sort,
settings: results.settings,
query: data.query,
tag: data.query.tag,
targetUid: results.targetUid,
}, next);
},
function (data, next) {

@ -27,7 +27,12 @@ module.exports = function (Topics) {
async.waterfall([
function (next) {
if (cid) {
categories.getTopicIds(cid, 'cid:' + cid + ':tids', true, 0, 199, next);
categories.getTopicIds({
cid: cid,
start: 0,
stop: 199,
sort: 'newest_to_oldest',
}, next);
} else {
db.getSortedSetRevRange('topics:recent', 0, 199, next);
}

@ -73,7 +73,11 @@ module.exports = function (Topics) {
Topics.getTopicField(tid, 'cid', next);
},
function (cid, next) {
categories.getTopicIds(cid, 'cid:' + cid + ':tids', true, 0, 9, next);
categories.getTopicIds({
cid: cid,
start: 0,
stop: 9,
}, next);
},
], callback);
}

@ -54,8 +54,6 @@ describe('Categories', function () {
it('should retrieve a newly created category by its ID', function (done) {
Categories.getCategoryById({
cid: categoryObj.cid,
set: 'cid:' + categoryObj.cid + ':tids',
reverse: true,
start: 0,
stop: -1,
uid: 0,
@ -103,11 +101,10 @@ describe('Categories', function () {
it('should return a list of topics', function (done) {
Categories.getCategoryTopics({
cid: categoryObj.cid,
set: 'cid:' + categoryObj.cid + ':tids',
reverse: true,
start: 0,
stop: 10,
uid: 0,
sort: 'oldest-to-newest',
}, function (err, result) {
assert.equal(err, null);
@ -123,12 +120,11 @@ describe('Categories', function () {
it('should return a list of topics by a specific user', function (done) {
Categories.getCategoryTopics({
cid: categoryObj.cid,
set: 'cid:' + categoryObj.cid + ':uid:' + 1 + ':tids',
reverse: true,
start: 0,
stop: 10,
uid: 0,
targetUid: 1,
sort: 'oldest-to-newest',
}, function (err, result) {
assert.equal(err, null);
assert(Array.isArray(result.topics));
@ -226,7 +222,14 @@ describe('Categories', function () {
});
it('should load more topics', function (done) {
socketCategories.loadMore({ uid: posterUid }, { cid: categoryObj.cid, after: 0, author: 'poster', tag: 'nodebb' }, function (err, data) {
socketCategories.loadMore({ uid: posterUid }, {
cid: categoryObj.cid,
after: 0,
query: {
author: 'poster',
tag: 'nodebb',
},
}, function (err, data) {
assert.ifError(err);
assert(Array.isArray(data.topics));
assert.equal(data.topics[0].user.username, 'poster');
@ -244,7 +247,7 @@ describe('Categories', function () {
});
});
it('should load page count', function (done) {
it('should load topic count', function (done) {
socketCategories.getTopicCount({ uid: posterUid }, categoryObj.cid, function (err, topicCount) {
assert.ifError(err);
assert.equal(topicCount, 2);
@ -680,4 +683,31 @@ describe('Categories', function () {
});
});
});
describe('getTopicIds', function () {
var plugins = require('../src/plugins');
it('should get topic ids with filter', function (done) {
function method(data, callback) {
data.tids = [1, 2, 3];
callback(null, data);
}
plugins.registerHook('my-test-plugin', {
hook: 'filter:categories.getTopicIds',
method: method,
});
Categories.getTopicIds({
cid: categoryObj.cid,
start: 0,
stop: 19,
}, function (err, tids) {
assert.ifError(err);
assert.deepEqual(tids, [1, 2, 3]);
plugins.unregisterHook('my-test-plugin', 'filter:categories.getTopicIds', method);
done();
});
});
});
});

Loading…
Cancel
Save