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:
Julian Lam
2023-02-06 15:56:07 -05:00
parent f13c4ace70
commit b79627a8ed
6 changed files with 57 additions and 36 deletions

View File

@@ -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();
}

View File

@@ -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 () {

View File

@@ -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') {

View File

@@ -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 });
};

View File

@@ -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,
});

View File

@@ -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) {