diff --git a/public/src/client/topic/posts.js b/public/src/client/topic/posts.js index b84953e915..1301e7289a 100644 --- a/public/src/client/topic/posts.js +++ b/public/src/client/topic/posts.js @@ -183,7 +183,7 @@ define('forum/topic/posts', [ } data.posts = data.posts.filter(function (post) { - return $('[component="post"][data-pid="' + post.pid + '"]').length === 0; + return post.index === -1 || $('[component="post"][data-pid="' + post.pid + '"]').length === 0; }); } @@ -206,9 +206,11 @@ define('forum/topic/posts', [ app.parseAndTranslate('topic', 'posts', Object.assign({}, ajaxify.data, data), function (html) { html = html.filter(function () { - const pid = $(this).attr('data-pid'); - const isPost = $(this).is('[component="post"]'); - return !isPost || (pid && $('[component="post"][data-pid="' + pid + '"]').length === 0); + const $this = $(this); + const pid = $this.attr('data-pid'); + const index = parseInt($this.attr('data-index'), 10); + const isPost = $this.is('[component="post"]'); + return !isPost || index === -1 || (pid && $('[component="post"][data-pid="' + pid + '"]').length === 0); }); if (after) { diff --git a/src/socket.io/topics/infinitescroll.js b/src/socket.io/topics/infinitescroll.js index c20730229f..506a87b6f7 100644 --- a/src/socket.io/topics/infinitescroll.js +++ b/src/socket.io/topics/infinitescroll.js @@ -16,7 +16,7 @@ module.exports = function (SocketTopics) { const [userPrivileges, topicData] = await Promise.all([ privileges.topics.get(data.tid, socket.uid), - topics.getTopicFields(data.tid, ['postcount', 'deleted', 'scheduled', 'uid']), + topics.getTopicData(data.tid), ]); if (!userPrivileges['topics:read'] || !privileges.topics.canViewDeletedScheduled(topicData, userPrivileges)) { @@ -32,28 +32,22 @@ module.exports = function (SocketTopics) { parseInt(data.count, 10) || meta.config.postsPerPage || 20 )); - if (data.direction === -1) { - start -= (infScrollPostsPerPage + 1); + if (data.direction === 1) { + start += 1; + } else if (data.direction === -1) { + start -= infScrollPostsPerPage; } let stop = start + infScrollPostsPerPage - 1; start = Math.max(0, start); stop = Math.max(0, stop); - - const [mainPost, posts, postSharing] = await Promise.all([ - start > 0 ? null : topics.getMainPost(data.tid, socket.uid), - topics.getTopicPosts(data.tid, set, start, stop, socket.uid, reverse), + const [posts, postSharing] = await Promise.all([ + topics.getTopicPosts(topicData, set, start, stop, socket.uid, reverse), social.getActivePostSharing(), ]); - if (mainPost) { - topicData.mainPost = mainPost; - topicData.posts = [mainPost].concat(posts); - } else { - topicData.posts = posts; - } - + topicData.posts = posts; topicData.privileges = userPrivileges; topicData.postSharing = postSharing; topicData['reputation:disabled'] = meta.config['reputation:disabled'] === 1; diff --git a/src/topics/index.js b/src/topics/index.js index 67614927ae..9584b8d7cf 100644 --- a/src/topics/index.js +++ b/src/topics/index.js @@ -168,7 +168,7 @@ Topics.getTopicWithPosts = async function (topicData, set, uid, start, stop, rev thumbs, events, ] = await Promise.all([ - getMainPostAndReplies(topicData, set, uid, start, stop, reverse), + Topics.getTopicPosts(topicData, set, start, stop, uid, reverse), categories.getCategoryData(topicData.cid), categories.getTagWhitelist([topicData.cid]), plugins.hooks.fire('filter:topic.thread_tools', { topic: topicData, uid: uid, tools: [] }), @@ -211,58 +211,6 @@ Topics.getTopicWithPosts = async function (topicData, set, uid, start, stop, rev return result.topic; }; -async function getMainPostAndReplies(topic, set, uid, start, stop, reverse) { - let repliesStart = start; - let repliesStop = stop; - if (stop > 0) { - repliesStop -= 1; - if (start > 0) { - repliesStart -= 1; - } - } - const pids = await posts.getPidsFromSet(set, repliesStart, repliesStop, reverse); - if (!pids.length && !topic.mainPid) { - return []; - } - - if (topic.mainPid && start === 0) { - pids.unshift(topic.mainPid); - } - const postData = await posts.getPostsByPids(pids, uid); - if (!postData.length) { - return []; - } - let replies = postData; - if (topic.mainPid && start === 0) { - postData[0].index = 0; - replies = postData.slice(1); - } - - Topics.calculatePostIndices(replies, repliesStart); - - await Topics.addNextPostTimestamp(postData, set, reverse); - return await Topics.addPostData(postData, uid); -} - -Topics.addNextPostTimestamp = async function (postData, set, reverse) { - if (!postData.length) { - return; - } - postData.forEach((p, index) => { - if (p && postData[index + 1]) { - p.nextPostTimestamp = postData[index + 1].timestamp; - } - }); - const lastPost = postData[postData.length - 1]; - if (lastPost) { - lastPost.nextPostTimestamp = Date.now(); - if (lastPost.index) { - const data = await db[reverse ? 'getSortedSetRevRangeWithScores' : 'getSortedSetRangeWithScores'](set, lastPost.index, lastPost.index); - lastPost.nextPostTimestamp = data.length ? data[0].score : lastPost.nextPostTimestamp; - } - } -}; - async function getDeleter(topicData) { if (!parseInt(topicData.deleterUid, 10)) { return null; diff --git a/src/topics/posts.js b/src/topics/posts.js index dc947c6e67..5185ce4066 100644 --- a/src/topics/posts.js +++ b/src/topics/posts.js @@ -4,6 +4,7 @@ const _ = require('lodash'); const validator = require('validator'); const nconf = require('nconf'); +const winston = require('winston'); const db = require('../database'); const user = require('../user'); @@ -20,12 +21,67 @@ module.exports = function (Topics) { await Topics.addPostToTopic(postData.tid, postData); }; - Topics.getTopicPosts = async function (tid, set, start, stop, uid, reverse) { - const postData = await posts.getPostsFromSet(set, start, stop, uid, reverse); - Topics.calculatePostIndices(postData, start); + Topics.getTopicPosts = async function (topicOrTid, set, start, stop, uid, reverse) { + if (topicOrTid && typeof topicOrTid !== 'object') { + // TODO: remove in 1.19.0 + winston.warn('[deprecated] Topics.getTopicPosts(tid, ...) usage is deprecated, pass a topic object as first argument!'); + topicOrTid = await Topics.getTopicData(topicOrTid); + } + + let repliesStart = start; + let repliesStop = stop; + if (stop > 0) { + repliesStop -= 1; + if (start > 0) { + repliesStart -= 1; + } + } + const pids = await posts.getPidsFromSet(set, repliesStart, repliesStop, reverse); + if (!pids.length && !topicOrTid.mainPid) { + return []; + } + + if (topicOrTid.mainPid && start === 0) { + pids.unshift(topicOrTid.mainPid); + } + const postData = await posts.getPostsByPids(pids, uid); + if (!postData.length) { + return []; + } + let replies = postData; + if (topicOrTid.mainPid && start === 0) { + postData[0].index = 0; + replies = postData.slice(1); + } + + Topics.calculatePostIndices(replies, repliesStart); await Topics.addNextPostTimestamp(postData, set, reverse); - return await Topics.addPostData(postData, uid); + const result = await plugins.hooks.fire('filter:topic.getPosts', { + topic: topicOrTid, + uid: uid, + posts: await Topics.addPostData(postData, uid), + }); + return result.posts; + }; + + Topics.addNextPostTimestamp = async function (postData, set, reverse) { + if (!postData.length) { + return; + } + postData.forEach((p, index) => { + if (p && postData[index + 1]) { + p.nextPostTimestamp = postData[index + 1].timestamp; + } + }); + const lastPost = postData[postData.length - 1]; + if (lastPost) { + lastPost.nextPostTimestamp = Date.now(); + if (lastPost.index) { + const data = await db[reverse ? 'getSortedSetRevRangeWithScores' : 'getSortedSetRangeWithScores'](set, lastPost.index, lastPost.index); + lastPost.nextPostTimestamp = data.length ? data[0].score : lastPost.nextPostTimestamp; + } + } }; Topics.addPostData = async function (postData, uid) {