diff --git a/public/language/en-GB/topic.json b/public/language/en-GB/topic.json index d7533b80f3..ac69995c89 100644 --- a/public/language/en-GB/topic.json +++ b/public/language/en-GB/topic.json @@ -254,6 +254,7 @@ "no-more-next-post": "You don't have more posts in this topic", "open-composer": "Open composer", "post-quick-reply": "Quick reply", + "post-quick-create": "Quick post", "navigator.index": "Post %1 of %2", "navigator.unread": "%1 unread", diff --git a/public/src/client/world.js b/public/src/client/world.js index adf6925e57..8d7a11b927 100644 --- a/public/src/client/world.js +++ b/public/src/client/world.js @@ -3,8 +3,10 @@ define('forum/world', [ 'forum/infinitescroll', 'search', 'sort', 'hooks', 'alerts', 'api', 'bootbox', 'helpers', 'forum/category/tools', - 'translator', -], function (infinitescroll, search, sort, hooks, alerts, api, bootbox, helpers, categoryTools, translator) { + 'translator', 'quickreply', +], function (infinitescroll, search, sort, hooks, + alerts, api, bootbox, helpers, categoryTools, + translator, quickreply) { const World = {}; $(window).on('action:ajaxify.start', function () { @@ -14,6 +16,7 @@ define('forum/world', [ World.init = function () { app.enterRoom('world'); categoryTools.init($('#world-feed')); + quickreply.init(); sort.handleSort('categoryTopicSort', 'world'); diff --git a/public/src/modules/quickreply.js b/public/src/modules/quickreply.js index 3293bb3275..602c1ace05 100644 --- a/public/src/modules/quickreply.js +++ b/public/src/modules/quickreply.js @@ -69,6 +69,18 @@ define('quickreply', [ handle: undefined, content: replyMsg, }; + let replyRoute = '/topics'; + switch(ajaxify.data.template.name) { + case 'topic': + replyData.tid = ajaxify.data.tid; + replyRoute = `/topics/${ajaxify.data.tid}`; + break; + + case 'world': + replyData.cid = '-1'; + break; + } + const replyLen = replyMsg.length; if (replyLen < parseInt(config.minimumPostLength, 10)) { return alerts.error('[[error:content-too-short, ' + config.minimumPostLength + ']]'); @@ -78,7 +90,7 @@ define('quickreply', [ ready = false; element.val(''); - api.post(`/topics/${ajaxify.data.tid}`, replyData, function (err, data) { + api.post(replyRoute, replyData, function (err, data) { ready = true; if (err) { element.val(replyMsg); diff --git a/src/controllers/activitypub/topics.js b/src/controllers/activitypub/topics.js index 11cc8368f4..d780f954c7 100644 --- a/src/controllers/activitypub/topics.js +++ b/src/controllers/activitypub/topics.js @@ -7,6 +7,7 @@ const user = require('../../user'); const topics = require('../../topics'); const posts = require('../../posts'); const categories = require('../../categories'); +const privileges = require('../../privileges'); const translator = require('../../translator'); const pagination = require('../../pagination'); const utils = require('../../utils'); @@ -24,7 +25,10 @@ controller.list = async function (req, res) { const start = Math.max(0, (page - 1) * topicsPerPage); const stop = start + topicsPerPage - 1; - const userSettings = await user.getSettings(req.uid); + const [userSettings, userPrivileges] = await Promise.all([ + user.getSettings(req.uid), + privileges.categories.get('-1', req.uid), + ]); const targetUid = await user.getUidByUserslug(req.query.author); let cidQuery = { uid: req.uid, @@ -40,6 +44,7 @@ controller.list = async function (req, res) { const data = await categories.getCategoryById(cidQuery); delete data.children; data.sort = req.query.sort; + data.privileges = userPrivileges; let tids; let topicCount; diff --git a/src/routes/write/topics.js b/src/routes/write/topics.js index a1c7810558..107fdac8bd 100644 --- a/src/routes/write/topics.js +++ b/src/routes/write/topics.js @@ -10,7 +10,7 @@ const { setupApiRoute } = routeHelpers; module.exports = function () { const middlewares = [middleware.ensureLoggedIn]; - setupApiRoute(router, 'post', '/', [middleware.checkRequired.bind(null, ['cid', 'title', 'content'])], controllers.write.topics.create); + setupApiRoute(router, 'post', '/', [middleware.checkRequired.bind(null, ['cid', 'content'])], controllers.write.topics.create); setupApiRoute(router, 'get', '/:tid', [], controllers.write.topics.get); setupApiRoute(router, 'post', '/:tid', [middleware.checkRequired.bind(null, ['content']), middleware.assert.topic], controllers.write.topics.reply); setupApiRoute(router, 'delete', '/:tid', [...middlewares], controllers.write.topics.purge); diff --git a/src/topics/create.js b/src/topics/create.js index 56fbe49830..f4a5ac8b04 100644 --- a/src/topics/create.js +++ b/src/topics/create.js @@ -3,6 +3,7 @@ const _ = require('lodash'); const winston = require('winston'); +const tokenizer = require('sbd'); const db = require('../database'); const utils = require('../utils'); @@ -102,9 +103,17 @@ module.exports = function (Topics) { privileges.users.isAdministrator(uid), ]); - data.title = String(data.title).trim(); data.tags = data.tags || []; data.content = String(data.content || '').trimEnd(); + + if (data.title) { + data.title = String(data.title).trim(); + } else { + const sentences = tokenizer.sentences(data.content, { sanitize: true, newline_boundaries: true }); + data.title = sentences.shift(); + data.generatedTitle = 1; + } + if (!isAdmin) { Topics.checkTitle(data.title); } @@ -259,6 +268,7 @@ module.exports = function (Topics) { Topics.addParentPosts([postData], uid), Topics.syncBacklinks(postData), Topics.markAsRead([tid], uid), + activitypub.notes.syncUserInboxes(tid, uid), ]); // Returned data is a superset of post summary data