mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-05-07 18:16:36 +02:00
refactor: allow frontend to mark chats as unread, use new API v3 routes instead of socket calls, better frontend event handling
This commit is contained in:
@@ -469,7 +469,7 @@ define('forum/chats', [
|
||||
Chats.addGlobalEventListeners = function () {
|
||||
$(window).on('mousemove keypress click', function () {
|
||||
if (newMessage && ajaxify.data.roomId) {
|
||||
socket.emit('modules.chats.markRead', ajaxify.data.roomId);
|
||||
api.del(`/chats/${ajaxify.data.roomId}/state`, {});
|
||||
newMessage = false;
|
||||
}
|
||||
});
|
||||
@@ -530,7 +530,7 @@ define('forum/chats', [
|
||||
const roomEls = document.querySelectorAll(`[component="chat/recent"] [data-roomid="${roomId}"], [component="chat/list"] [data-roomid="${roomId}"]`);
|
||||
|
||||
roomEls.forEach((roomEl) => {
|
||||
roomEl.classList.add('unread');
|
||||
roomEl.classList[state ? 'add' : 'remove']('unread');
|
||||
|
||||
const markEl = roomEl.querySelector('.mark-read');
|
||||
if (markEl) {
|
||||
@@ -543,8 +543,12 @@ define('forum/chats', [
|
||||
|
||||
Chats.setActive = function () {
|
||||
if (ajaxify.data.roomId) {
|
||||
socket.emit('modules.chats.markRead', ajaxify.data.roomId);
|
||||
$('[data-roomid="' + ajaxify.data.roomId + '"]').toggleClass('unread', false);
|
||||
const chatEl = document.querySelector(`[component="chat/recent"] [data-roomid="${ajaxify.data.roomId}"]`);
|
||||
if (chatEl.classList.contains('unread')) {
|
||||
api.del(`/chats/${ajaxify.data.roomId}/state`, {});
|
||||
chatEl.classList.remove('unread');
|
||||
}
|
||||
|
||||
if (!utils.isMobile()) {
|
||||
$('.expanded-chat [component="chat/input"]').focus();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
define('forum/chats/recent', ['alerts'], function (alerts) {
|
||||
define('forum/chats/recent', ['alerts', 'api'], function (alerts, api) {
|
||||
const recent = {};
|
||||
|
||||
recent.init = function () {
|
||||
@@ -16,14 +16,21 @@ define('forum/chats/recent', ['alerts'], function (alerts) {
|
||||
.on('click', '.mark-read', function (e) {
|
||||
e.stopPropagation();
|
||||
const chatEl = this.closest('[data-roomid]');
|
||||
const unread = chatEl.classList.contains('unread');
|
||||
if (unread) {
|
||||
const roomId = chatEl.getAttribute('data-roomid');
|
||||
socket.emit('modules.chats.markRead', roomId);
|
||||
chatEl.classList.remove('unread');
|
||||
this.querySelector('.unread').classList.add('hidden');
|
||||
this.querySelector('.read').classList.remove('hidden');
|
||||
}
|
||||
const state = !chatEl.classList.contains('unread'); // this is the new state
|
||||
const roomId = chatEl.getAttribute('data-roomid');
|
||||
api[state ? 'put' : 'del'](`/chats/${roomId}/state`, {}).catch((err) => {
|
||||
alerts.error(err);
|
||||
|
||||
// Revert on failure
|
||||
chatEl.classList[state ? 'remove' : 'add']('unread');
|
||||
this.querySelector('.unread').classList[state ? 'add' : 'remove']('hidden');
|
||||
this.querySelector('.read').classList[!state ? 'add' : 'remove']('hidden');
|
||||
});
|
||||
|
||||
// Immediate feedback
|
||||
chatEl.classList[state ? 'add' : 'remove']('unread');
|
||||
this.querySelector('.unread').classList[!state ? 'add' : 'remove']('hidden');
|
||||
this.querySelector('.read').classList[state ? 'add' : 'remove']('hidden');
|
||||
});
|
||||
|
||||
$('[component="chat/recent"]').on('scroll', function () {
|
||||
|
||||
@@ -131,10 +131,19 @@ define('chat', [
|
||||
const unread = chatEl.classList.contains('unread');
|
||||
if (unread) {
|
||||
const roomId = chatEl.getAttribute('data-roomid');
|
||||
socket.emit('modules.chats.markRead', roomId);
|
||||
api.del(`/chats/${roomId}/state`, {}).catch((err) => {
|
||||
alerts.error(err);
|
||||
|
||||
// Revert on failure
|
||||
chatEl.classList.add('unread');
|
||||
this.querySelector('.unread').classList.remove('hidden');
|
||||
this.querySelector('.read').classList.add('hidden');
|
||||
});
|
||||
|
||||
// Immediate feedback
|
||||
chatEl.classList.remove('unread');
|
||||
subselector.querySelector('.unread').classList.add('hidden');
|
||||
subselector.querySelector('.read').classList.remove('hidden');
|
||||
this.querySelector('.unread').classList.add('hidden');
|
||||
this.querySelector('.read').classList.remove('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -304,7 +313,7 @@ define('chat', [
|
||||
|
||||
chatModal.on('mousemove keypress click', function () {
|
||||
if (newMessage) {
|
||||
socket.emit('modules.chats.markRead', data.roomId);
|
||||
api.del(`/chats/${data.roomId}/state`, {});
|
||||
newMessage = false;
|
||||
}
|
||||
});
|
||||
@@ -400,7 +409,7 @@ define('chat', [
|
||||
taskbar.updateActive(uuid);
|
||||
ChatsMessages.scrollToBottom(chatModal.find('.chat-content'));
|
||||
module.focusInput(chatModal);
|
||||
socket.emit('modules.chats.markRead', chatModal.attr('data-roomid'));
|
||||
api.del(`/chats/${chatModal.attr('data-roomid')}/state`, {});
|
||||
|
||||
const env = utils.findBootstrapEnvironment();
|
||||
if (env === 'xs' || env === 'sm') {
|
||||
|
||||
@@ -5,6 +5,7 @@ const validator = require('validator');
|
||||
const user = require('../user');
|
||||
const meta = require('../meta');
|
||||
const messaging = require('../messaging');
|
||||
const notifications = require('../notifications');
|
||||
const plugins = require('../plugins');
|
||||
|
||||
// const websockets = require('../socket.io');
|
||||
@@ -79,9 +80,24 @@ chatsAPI.mark = async (caller, data) => {
|
||||
await messaging.markUnread([caller.uid], roomId);
|
||||
} else {
|
||||
await messaging.markRead(caller.uid, roomId);
|
||||
socketHelpers.emitToUids('event:chats.markedAsRead', { roomId: roomId }, [caller.uid]);
|
||||
|
||||
const uidsInRoom = await messaging.getUidsInRoom(roomId, 0, -1);
|
||||
if (!uidsInRoom.includes(String(caller.uid))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark notification read
|
||||
const nids = uidsInRoom.filter(uid => parseInt(uid, 10) !== caller.uid)
|
||||
.map(uid => `chat_${uid}_${roomId}`);
|
||||
|
||||
await notifications.markReadMultiple(nids, caller.uid);
|
||||
await user.notifications.pushCount(caller.uid);
|
||||
}
|
||||
|
||||
socketHelpers.emitToUids('event:chats.mark', { roomId, state }, [caller.uid]);
|
||||
messaging.pushUnreadCount(caller.uid);
|
||||
|
||||
return messaging.loadRoom(caller.uid, { roomId });
|
||||
};
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ Chats.rename = async (req, res) => {
|
||||
Chats.mark = async (req, res) => {
|
||||
const state = req.method === 'PUT' ? 1 : 0;
|
||||
const roomObj = await api.chats.mark(req, {
|
||||
...req.body,
|
||||
roomId: req.params.roomId,
|
||||
state,
|
||||
});
|
||||
|
||||
@@ -171,27 +171,13 @@ SocketModules.chats.canMessage = async function (socket, roomId) {
|
||||
};
|
||||
|
||||
SocketModules.chats.markRead = async function (socket, roomId) {
|
||||
sockets.warnDeprecated(socket, 'PUT/DELETE /api/v3/chats/:roomId/state');
|
||||
|
||||
if (!socket.uid || !roomId) {
|
||||
throw new Error('[[error:invalid-data]]');
|
||||
}
|
||||
const [uidsInRoom] = await Promise.all([
|
||||
Messaging.getUidsInRoom(roomId, 0, -1),
|
||||
Messaging.markRead(socket.uid, roomId),
|
||||
]);
|
||||
|
||||
Messaging.pushUnreadCount(socket.uid);
|
||||
server.in(`uid_${socket.uid}`).emit('event:chats.markedAsRead', { roomId: roomId });
|
||||
|
||||
if (!uidsInRoom.includes(String(socket.uid))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark notification read
|
||||
const nids = uidsInRoom.filter(uid => parseInt(uid, 10) !== socket.uid)
|
||||
.map(uid => `chat_${uid}_${roomId}`);
|
||||
|
||||
await notifications.markReadMultiple(nids, socket.uid);
|
||||
await user.notifications.pushCount(socket.uid);
|
||||
api.chats.mark(socket, { state: 0, roomId });
|
||||
};
|
||||
|
||||
SocketModules.chats.markAllRead = async function (socket) {
|
||||
|
||||
Reference in New Issue
Block a user