Skip to content
27 changes: 23 additions & 4 deletions apps/meteor/app/lib/server/lib/notifyUsersOnMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ export function getMentions(message) {

const incGroupMentions = (rid, roomType, excludeUserId, unreadCount) => {
const incUnreadByGroup = ['all_messages', 'group_mentions_only', 'user_and_group_mentions_only'].includes(unreadCount);
const incUnread = roomType === 'd' || incUnreadByGroup ? 1 : 0;
const incUnread = roomType === 'd' || roomType === 'l' || incUnreadByGroup ? 1 : 0;

Subscriptions.incGroupMentionsAndUnreadForRoomIdExcludingUserId(rid, excludeUserId, 1, incUnread);
};

const incUserMentions = (rid, roomType, uids, unreadCount) => {
const incUnreadByUser = ['all_messages', 'user_mentions_only', 'user_and_group_mentions_only'].includes(unreadCount);
const incUnread = roomType === 'd' || incUnreadByUser ? 1 : 0;
const incUnread = roomType === 'd' || roomType === 'l' || incUnreadByUser ? 1 : 0;

Subscriptions.incUserMentionsAndUnreadForRoomIdAndUserIds(rid, uids, 1, incUnread);
};
Expand All @@ -86,15 +86,34 @@ const getUserIdsFromHighlights = (rid, message) => {
.map(({ u: { _id: uid } }) => uid);
};

/*
* {IRoom['t']} roomType - The type of the room
* @returns {string} - The setting value for unread count
*/
const getUnreadSettingCount = (roomType) => {
let unreadSetting = 'Unread_Count';
switch (roomType) {
case 'd': {
unreadSetting = 'Unread_Count_DM';
break;
}
case 'l': {
unreadSetting = 'Unread_Count_Omni';
break;
}
}

return settings.get(unreadSetting);
};

export async function updateUsersSubscriptions(message, room) {
// Don't increase unread counter on thread messages
if (room != null && !message.tmid) {
const { toAll, toHere, mentionIds } = getMentions(message);

const userIds = new Set(mentionIds);

const unreadSetting = room.t === 'd' ? 'Unread_Count_DM' : 'Unread_Count';
const unreadCount = settings.get(unreadSetting);
const unreadCount = getUnreadSettingCount(room.t);

getUserIdsFromHighlights(room._id, message).forEach((uid) => userIds.add(uid));

Expand Down
14 changes: 14 additions & 0 deletions apps/meteor/app/lib/server/startup/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,20 @@ settingsRegistry.addGroup('General', function () {
],
public: true,
});
this.add('Unread_Count_Omni', 'all_messages', {
type: 'select',
values: [
{
key: 'all_messages',
i18nLabel: 'All_messages',
},
{
key: 'mentions_only',
i18nLabel: 'Mentions_only',
},
],
public: true,
});

this.add('DeepLink_Url', 'https://go.rocket.chat', {
type: 'string',
Expand Down
3 changes: 2 additions & 1 deletion apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -4928,6 +4928,7 @@
"Unread": "Unread",
"Unread_Count": "Unread Count",
"Unread_Count_DM": "Unread Count for Direct Messages",
"Unread_Count_Omni": "Unread Count for Omnichannel Chats",
"Unread_Messages": "Unread Messages",
"Unread_on_top": "Unread on top",
"Unread_Rooms": "Unread Rooms",
Expand Down Expand Up @@ -5551,4 +5552,4 @@
"Theme_dark": "Dark",
"Join_your_team": "Join your team",
"Create_an_account": "Create an account"
}
}
10 changes: 8 additions & 2 deletions apps/meteor/tests/data/livechat/department.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ new Promise((resolve, reject) => {
});
});

export const createDepartmentWithAnOnlineAgent = async (): Promise<{department: ILivechatDepartment, agent: IUser}> => {
export const createDepartmentWithAnOnlineAgent = async (): Promise<{department: ILivechatDepartment, agent: {
credentials: { 'X-Auth-Token': string; 'X-User-Id': string; };
user: IUser;
}}> => {
const agent: IUser = await createUser();
const createdUserCredentials = await login(agent.username, password);
await createAgent(agent.username);
Expand All @@ -69,7 +72,10 @@ export const createDepartmentWithAnOnlineAgent = async (): Promise<{department:

return {
department,
agent,
agent: {
credentials: createdUserCredentials,
user: agent,
}
};
};

Expand Down
15 changes: 15 additions & 0 deletions apps/meteor/tests/data/subscriptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { ISubscription } from "@rocket.chat/core-typings";
import { api, credentials, request } from "./api-data";

export const getSubscriptionForRoom = async (roomId: string, overrideCredential?: { 'X-Auth-Token': string; 'X-User-Id': string; }): Promise<ISubscription> => {
const response = await request
.get(api('subscriptions.getOne'))
.set(overrideCredential || credentials)
.query({ roomId })
.expect('Content-Type', 'application/json')
.expect(200);

const { subscription } = response.body;

return subscription;
}
59 changes: 59 additions & 0 deletions apps/meteor/tests/end-to-end/api/livechat/00-rooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { createDepartmentWithAnOnlineAgent } from '../../../data/livechat/depart
import { sleep } from '../../../data/livechat/utils';
import { IS_EE } from '../../../e2e/config/constants';
import { createCustomField } from '../../../data/livechat/custom-fields';
import { getSubscriptionForRoom } from '../../../data/subscriptions';

describe('LIVECHAT - rooms', function () {
this.retries(0);
Expand Down Expand Up @@ -1446,4 +1447,62 @@ describe('LIVECHAT - rooms', function () {
expect(response.body.filters.find((f: IOmnichannelRoom['source']) => f.type === 'api')).to.not.be.undefined;
});
});

describe('it should mark room as unread when a new message arrives and the config is activated', () => {
let room: IOmnichannelRoom;
let visitor: ILivechatVisitor;
let totalMessagesSent = 0;
let departmentWithAgent: Awaited<ReturnType<typeof createDepartmentWithAnOnlineAgent>>;

before(async () => {
Comment thread
murtaza98 marked this conversation as resolved.
await updateSetting('Livechat_Routing_Method', 'Auto_Selection');
await updateSetting('Unread_Count_Omni', 'all_messages');
});

it('it should prepare the required data for further tests', async () => {
departmentWithAgent = await createDepartmentWithAnOnlineAgent();
visitor = await createVisitor(departmentWithAgent.department._id);
room = await createLivechatRoom(visitor.token);

await sendMessage(room._id, 'message 1', visitor.token);
await sendMessage(room._id, 'message 2', visitor.token);

// 1st message is for the room creation, so we need to add 1 to the total messages sent
totalMessagesSent = 3;
});

it("room's subscription should have correct unread count", async () => {
const { unread } = await getSubscriptionForRoom(room._id, departmentWithAgent.agent.credentials);
expect(unread).to.equal(totalMessagesSent);
});
});

describe('it should NOT mark room as unread when a new message arrives and the config is deactivated', () => {
let room: IOmnichannelRoom;
let visitor: ILivechatVisitor;
let totalMessagesSent = 0;
let departmentWithAgent: Awaited<ReturnType<typeof createDepartmentWithAnOnlineAgent>>;

before(async () => {
await updateSetting('Livechat_Routing_Method', 'Auto_Selection');
await updateSetting('Unread_Count_Omni', 'mentions_only');
});

it('it should prepare the required data for further tests', async () => {
departmentWithAgent = await createDepartmentWithAnOnlineAgent();
visitor = await createVisitor(departmentWithAgent.department._id);
room = await createLivechatRoom(visitor.token);

await sendMessage(room._id, 'message 1', visitor.token);
await sendMessage(room._id, 'message 2', visitor.token);

// 1st message is for the room creation, so we need to add 1 to the total messages sent
totalMessagesSent = 1;
});

it("room's subscription should have correct unread count", async () => {
const { unread } = await getSubscriptionForRoom(room._id, departmentWithAgent.agent.credentials);
expect(unread).to.equal(totalMessagesSent);
});
});
});