mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-01 11:35:55 +01:00
added infinite scrolling to unread page, issue #141
This commit is contained in:
@@ -47,20 +47,6 @@
|
|||||||
++newPostCount;
|
++newPostCount;
|
||||||
updateAlertText();
|
updateAlertText();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#mark-allread-btn').on('click', function() {
|
|
||||||
var btn = $(this);
|
|
||||||
socket.emit('api:topics.markAllRead', {} , function(success) {
|
|
||||||
if(success) {
|
|
||||||
btn.remove();
|
|
||||||
$('#topics-container').empty();
|
|
||||||
$('#category-no-topics').removeClass('hidden');
|
|
||||||
app.alertSuccess('All topics marked as read!');
|
|
||||||
} else {
|
|
||||||
app.alertError('There was an error marking topics read!');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function onTopicsLoaded(topics) {
|
function onTopicsLoaded(topics) {
|
||||||
|
|
||||||
|
|||||||
103
public/src/forum/unread.js
Normal file
103
public/src/forum/unread.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
(function() {
|
||||||
|
var loadingMoreTopics = false;
|
||||||
|
|
||||||
|
app.enter_room('recent_posts');
|
||||||
|
|
||||||
|
ajaxify.register_events([
|
||||||
|
'event:new_topic',
|
||||||
|
'event:new_post'
|
||||||
|
]);
|
||||||
|
|
||||||
|
var newTopicCount = 0, newPostCount = 0;
|
||||||
|
|
||||||
|
$('#new-topics-alert').on('click', function() {
|
||||||
|
$(this).hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('event:new_topic', function(data) {
|
||||||
|
|
||||||
|
++newTopicCount;
|
||||||
|
updateAlertText();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateAlertText() {
|
||||||
|
var text = '';
|
||||||
|
|
||||||
|
if(newTopicCount > 1)
|
||||||
|
text = 'There are ' + newTopicCount + ' new topics';
|
||||||
|
else if(newTopicCount === 1)
|
||||||
|
text = 'There is 1 new topic';
|
||||||
|
else
|
||||||
|
text = 'There are no new topics';
|
||||||
|
|
||||||
|
if(newPostCount > 1)
|
||||||
|
text += ' and ' + newPostCount + ' new posts.';
|
||||||
|
else if(newPostCount === 1)
|
||||||
|
text += ' and 1 new post.';
|
||||||
|
else
|
||||||
|
text += ' and no new posts.';
|
||||||
|
|
||||||
|
text += ' Click here to reload.';
|
||||||
|
|
||||||
|
$('#new-topics-alert').html(text).fadeIn('slow');
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on('event:new_post', function(data) {
|
||||||
|
++newPostCount;
|
||||||
|
updateAlertText();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#mark-allread-btn').on('click', function() {
|
||||||
|
var btn = $(this);
|
||||||
|
socket.emit('api:topics.markAllRead', {} , function(success) {
|
||||||
|
if(success) {
|
||||||
|
btn.remove();
|
||||||
|
$('#topics-container').empty();
|
||||||
|
$('#category-no-topics').removeClass('hidden');
|
||||||
|
app.alertSuccess('All topics marked as read!');
|
||||||
|
} else {
|
||||||
|
app.alertError('There was an error marking topics read!');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function onTopicsLoaded(topics) {
|
||||||
|
|
||||||
|
var html = templates.prepare(templates['unread'].blocks['topics']).parse({ topics: topics }),
|
||||||
|
container = $('#topics-container');
|
||||||
|
|
||||||
|
$('#category-no-topics').remove();
|
||||||
|
|
||||||
|
container.append(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadMoreTopics() {
|
||||||
|
loadingMoreTopics = true;
|
||||||
|
socket.emit('api:topics.loadMoreUnreadTopics', {after:parseInt($('#topics-container').attr('data-next-start'), 10)}, function(data) {
|
||||||
|
if(data.topics && data.topics.length) {
|
||||||
|
onTopicsLoaded(data.topics);
|
||||||
|
$('#topics-container').attr('data-next-start', data.nextStart);
|
||||||
|
}
|
||||||
|
loadingMoreTopics = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$(window).off('scroll').on('scroll', function() {
|
||||||
|
var windowHeight = document.body.offsetHeight - $(window).height(),
|
||||||
|
half = windowHeight / 2;
|
||||||
|
|
||||||
|
if (document.body.scrollTop > half && !loadingMoreTopics) {
|
||||||
|
loadMoreTopics();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if($("body").height() <= $(window).height() && $('#topics-container').children().length)
|
||||||
|
$('#load-more-btn').show();
|
||||||
|
|
||||||
|
$('#load-more-btn').on('click', function() {
|
||||||
|
loadMoreTopics();
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<div class="category row">
|
<div class="category row">
|
||||||
<div class="{topic_row_size}">
|
<div class="{topic_row_size}">
|
||||||
<ul id="topics-container">
|
<ul id="topics-container" data-next-start="{nextStart}">
|
||||||
<!-- BEGIN topics -->
|
<!-- BEGIN topics -->
|
||||||
<a href="../../topic/{topics.slug}" id="tid-{topics.tid}">
|
<a href="../../topic/{topics.slug}" id="tid-{topics.tid}">
|
||||||
<li class="category-item {topics.deleted-class}">
|
<li class="category-item {topics.deleted-class}">
|
||||||
@@ -48,7 +48,8 @@
|
|||||||
</a>
|
</a>
|
||||||
<!-- END topics -->
|
<!-- END topics -->
|
||||||
</ul>
|
</ul>
|
||||||
|
<button id="load-more-btn" class="btn hide">Load More</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="{relative_path}/src/forum/recent.js"></script>
|
<script type="text/javascript" src="{relative_path}/src/forum/unread.js"></script>
|
||||||
49
src/posts.js
49
src/posts.js
@@ -178,34 +178,30 @@ var RDB = require('./redis.js'),
|
|||||||
alert_id: 'post_error'
|
alert_id: 'post_error'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Posts.emitTooManyPostsAlert = function(socket) {
|
||||||
|
socket.emit('event:alert', {
|
||||||
|
title: 'Too many posts!',
|
||||||
|
message: 'You can only post every '+ (config.post_delay / 1000) + ' seconds.',
|
||||||
|
type: 'error',
|
||||||
|
timeout: 2000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Posts.reply = function(socket, tid, uid, content, images) {
|
Posts.reply = function(tid, uid, content, images, callback) {
|
||||||
if(content) {
|
if(content) {
|
||||||
content = content.trim();
|
content = content.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uid < 1) {
|
if (!content || content.length < Posts.minimumPostLength) {
|
||||||
socket.emit('event:alert', {
|
callback(new Error('content-too-short'), null);
|
||||||
title: 'Reply Unsuccessful',
|
|
||||||
message: 'You don't seem to be logged in, so you cannot reply.',
|
|
||||||
type: 'error',
|
|
||||||
timeout: 2000
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
} else if (!content || content.length < Posts.minimumPostLength) {
|
|
||||||
Posts.emitContentTooShortAlert(socket);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
||||||
|
|
||||||
if(Date.now() - lastposttime < config.post_delay) {
|
if(Date.now() - lastposttime < config.post_delay) {
|
||||||
socket.emit('event:alert', {
|
callback(new Error('too-many-posts'), null);
|
||||||
title: 'Too many posts!',
|
|
||||||
message: 'You can only post every '+ (config.post_delay / 1000) + ' seconds.',
|
|
||||||
type: 'error',
|
|
||||||
timeout: 2000
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,18 +217,8 @@ var RDB = require('./redis.js'),
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Posts.getTopicPostStats(socket);
|
|
||||||
|
|
||||||
// Send notifications to users who are following this topic
|
|
||||||
threadTools.notify_followers(tid, uid);
|
threadTools.notify_followers(tid, uid);
|
||||||
|
|
||||||
socket.emit('event:alert', {
|
|
||||||
title: 'Reply Successful',
|
|
||||||
message: 'You have successfully replied. Click here to view your reply.',
|
|
||||||
type: 'notify',
|
|
||||||
timeout: 2000
|
|
||||||
});
|
|
||||||
|
|
||||||
postData.content = postTools.markdownToHTML(postData.content);
|
postData.content = postTools.markdownToHTML(postData.content);
|
||||||
postData.post_rep = 0;
|
postData.post_rep = 0;
|
||||||
postData.relativeTime = utils.relativeTime(postData.timestamp)
|
postData.relativeTime = utils.relativeTime(postData.timestamp)
|
||||||
@@ -251,14 +237,9 @@ var RDB = require('./redis.js'),
|
|||||||
io.sockets.in('recent_posts').emit('event:new_post', socketData);
|
io.sockets.in('recent_posts').emit('event:new_post', socketData);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
callback(null, 'Reply successful');
|
||||||
} else {
|
} else {
|
||||||
socket.emit('event:alert', {
|
callback(new Error('reply-error'), null);
|
||||||
title: 'Reply Unsuccessful',
|
|
||||||
message: 'Your reply could not be posted at this time. Please try again later.',
|
|
||||||
type: 'notify',
|
|
||||||
timeout: 2000
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ var user = require('./../user.js'),
|
|||||||
|
|
||||||
app.get('/api/unread', function(req, res) {
|
app.get('/api/unread', function(req, res) {
|
||||||
var uid = (req.user) ? req.user.uid : 0;
|
var uid = (req.user) ? req.user.uid : 0;
|
||||||
topics.getUnreadTopics(uid, 0, -1, function(data) {
|
topics.getUnreadTopics(uid, 0, 19, function(data) {
|
||||||
res.json(data);
|
res.json(data);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ marked.setOptions({
|
|||||||
function sendUnreadTopics(topicIds) {
|
function sendUnreadTopics(topicIds) {
|
||||||
Topics.getTopicsByTids(topicIds, uid, function(topicData) {
|
Topics.getTopicsByTids(topicIds, uid, function(topicData) {
|
||||||
unreadTopics.topics = topicData;
|
unreadTopics.topics = topicData;
|
||||||
|
unreadTopics.nextStart = start + tids.length;
|
||||||
callback(unreadTopics);
|
callback(unreadTopics);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -532,7 +533,7 @@ marked.setOptions({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Topics.post = function(socket, uid, title, content, category_id, images) {
|
Topics.post = function(uid, title, content, category_id, images, callback) {
|
||||||
if (!category_id)
|
if (!category_id)
|
||||||
throw new Error('Attempted to post without a category_id');
|
throw new Error('Attempted to post without a category_id');
|
||||||
|
|
||||||
@@ -542,33 +543,20 @@ marked.setOptions({
|
|||||||
title = title.trim();
|
title = title.trim();
|
||||||
|
|
||||||
if (uid === 0) {
|
if (uid === 0) {
|
||||||
socket.emit('event:alert', {
|
callback(new Error('not-logged-in'), null);
|
||||||
title: 'Thank you for posting',
|
return;
|
||||||
message: 'Since you are unregistered, your post is awaiting approval. Click here to register now.',
|
|
||||||
type: 'warning',
|
|
||||||
timeout: 7500,
|
|
||||||
clickfn: function() {
|
|
||||||
ajaxify.go('register');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return; // for now, until anon code is written.
|
|
||||||
} else if(!title || title.length < Topics.minimumTitleLength) {
|
} else if(!title || title.length < Topics.minimumTitleLength) {
|
||||||
Topics.emitTitleTooShortAlert(socket);
|
callback(new Error('title-too-short'), null);
|
||||||
return;
|
return;
|
||||||
} else if (!content || content.length < posts.miminumPostLength) {
|
} else if (!content || content.length < posts.miminumPostLength) {
|
||||||
posts.emitContentTooShortAlert(socket);
|
callback(new Error('content-too-short'), null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
user.getUserField(uid, 'lastposttime', function(lastposttime) {
|
||||||
|
|
||||||
if(Date.now() - lastposttime < config.post_delay) {
|
if(Date.now() - lastposttime < config.post_delay) {
|
||||||
socket.emit('event:alert', {
|
callback(new Error('too-many-posts'), null);
|
||||||
title: 'Too many posts!',
|
|
||||||
message: 'You can only post every '+ (config.post_delay / 1000) + ' seconds.',
|
|
||||||
type: 'error',
|
|
||||||
timeout: 2000
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,23 +592,6 @@ marked.setOptions({
|
|||||||
topicSearch.index(title, tid);
|
topicSearch.index(title, tid);
|
||||||
RDB.set('topicslug:' + slug + ':tid', tid);
|
RDB.set('topicslug:' + slug + ':tid', tid);
|
||||||
|
|
||||||
posts.create(uid, tid, content, images, function(postData) {
|
|
||||||
if (postData) {
|
|
||||||
RDB.lpush(schema.topics(tid).posts, postData.pid);
|
|
||||||
|
|
||||||
// Auto-subscribe the post creator to the newly created topic
|
|
||||||
threadTools.toggleFollow(tid, uid);
|
|
||||||
|
|
||||||
// Notify any users looking at the category that a new topic has arrived
|
|
||||||
Topics.getTopicForCategoryView(tid, uid, function(topicData) {
|
|
||||||
io.sockets.in('category_' + category_id).emit('event:new_topic', topicData);
|
|
||||||
io.sockets.in('recent_posts').emit('event:new_topic', topicData);
|
|
||||||
});
|
|
||||||
|
|
||||||
posts.getTopicPostStats(socket);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
user.addTopicIdToUser(uid, tid);
|
user.addTopicIdToUser(uid, tid);
|
||||||
|
|
||||||
// let everyone know that there is an unread topic in this category
|
// let everyone know that there is an unread topic in this category
|
||||||
@@ -636,11 +607,21 @@ marked.setOptions({
|
|||||||
|
|
||||||
feed.updateCategory(category_id);
|
feed.updateCategory(category_id);
|
||||||
|
|
||||||
socket.emit('event:alert', {
|
posts.create(uid, tid, content, images, function(postData) {
|
||||||
title: 'Thank you for posting',
|
if (postData) {
|
||||||
message: 'You have successfully posted. Click here to view your post.',
|
RDB.lpush(schema.topics(tid).posts, postData.pid);
|
||||||
type: 'notify',
|
|
||||||
timeout: 2000
|
// Auto-subscribe the post creator to the newly created topic
|
||||||
|
threadTools.toggleFollow(tid, uid);
|
||||||
|
|
||||||
|
// Notify any users looking at the category that a new topic has arrived
|
||||||
|
Topics.getTopicForCategoryView(tid, uid, function(topicData) {
|
||||||
|
io.sockets.in('category_' + category_id).emit('event:new_topic', topicData);
|
||||||
|
io.sockets.in('recent_posts').emit('event:new_topic', topicData);
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(null, postData);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -400,6 +400,7 @@ var express = require('express'),
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}(WebServer));
|
}(WebServer));
|
||||||
|
|||||||
@@ -304,7 +304,41 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:topics.post', function(data) {
|
socket.on('api:topics.post', function(data) {
|
||||||
topics.post(socket, uid, data.title, data.content, data.category_id, data.images);
|
|
||||||
|
topics.post(uid, data.title, data.content, data.category_id, data.images, function(err, result) {
|
||||||
|
if(err) {
|
||||||
|
if(err.message === 'not-logged-in') {
|
||||||
|
socket.emit('event:alert', {
|
||||||
|
title: 'Thank you for posting',
|
||||||
|
message: 'Since you are unregistered, your post is awaiting approval. Click here to register now.',
|
||||||
|
type: 'warning',
|
||||||
|
timeout: 7500,
|
||||||
|
clickfn: function() {
|
||||||
|
ajaxify.go('register');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if(err.message === 'title-too-short') {
|
||||||
|
topics.emitTitleTooShortAlert(socket);
|
||||||
|
} else if(err.message === 'content-too-short') {
|
||||||
|
posts.emitContentTooShortAlert(socket);
|
||||||
|
} else if (err.message === 'too-many-posts') {
|
||||||
|
posts.emitTooManyPostsAlert(socket);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result) {
|
||||||
|
posts.getTopicPostStats(socket);
|
||||||
|
|
||||||
|
socket.emit('event:alert', {
|
||||||
|
title: 'Thank you for posting',
|
||||||
|
message: 'You have successfully posted. Click here to view your post.',
|
||||||
|
type: 'notify',
|
||||||
|
timeout: 2000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:topics.markAllRead', function(data, callback) {
|
socket.on('api:topics.markAllRead', function(data, callback) {
|
||||||
@@ -318,7 +352,47 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:posts.reply', function(data) {
|
socket.on('api:posts.reply', function(data) {
|
||||||
posts.reply(socket, data.topic_id, uid, data.content, data.images);
|
if(uid < 1) {
|
||||||
|
socket.emit('event:alert', {
|
||||||
|
title: 'Reply Unsuccessful',
|
||||||
|
message: 'You don't seem to be logged in, so you cannot reply.',
|
||||||
|
type: 'error',
|
||||||
|
timeout: 2000
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
posts.reply(data.topic_id, uid, data.content, data.images, function(err, result) {
|
||||||
|
if(err) {
|
||||||
|
if(err.message === 'content-too-short') {
|
||||||
|
posts.emitContentTooShortAlert(socket);
|
||||||
|
} else if(err.messages === 'too-many-posts') {
|
||||||
|
posts.emitTooManyPostsAlert(socket);
|
||||||
|
} else if(err.message === 'reply-error') {
|
||||||
|
socket.emit('event:alert', {
|
||||||
|
title: 'Reply Unsuccessful',
|
||||||
|
message: 'Your reply could not be posted at this time. Please try again later.',
|
||||||
|
type: 'notify',
|
||||||
|
timeout: 2000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result) {
|
||||||
|
|
||||||
|
posts.getTopicPostStats(socket);
|
||||||
|
|
||||||
|
socket.emit('event:alert', {
|
||||||
|
title: 'Reply Successful',
|
||||||
|
message: 'You have successfully replied. Click here to view your reply.',
|
||||||
|
type: 'notify',
|
||||||
|
timeout: 2000
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('api:user.active.get', function() {
|
socket.on('api:user.active.get', function() {
|
||||||
@@ -578,6 +652,16 @@ var SocketIO = require('socket.io').listen(global.server, { log:false }),
|
|||||||
callback(latestTopics);
|
callback(latestTopics);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on('api:topics.loadMoreUnreadTopics', function(data, callback) {
|
||||||
|
var start = data.after,
|
||||||
|
end = start + 9;
|
||||||
|
|
||||||
|
console.log(start, end);
|
||||||
|
topics.getUnreadTopics(uid, start, end, function(unreadTopics) {
|
||||||
|
callback(unreadTopics);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
socket.on('api:admin.topics.getMore', function(data) {
|
socket.on('api:admin.topics.getMore', function(data) {
|
||||||
topics.getAllTopics(data.limit, data.after, function(topics) {
|
topics.getAllTopics(data.limit, data.after, function(topics) {
|
||||||
|
|||||||
Reference in New Issue
Block a user