diff --git a/app/api/server/v1/channels.js b/app/api/server/v1/channels.js index 58a75e2667dfe..cc65fb7b4c070 100644 --- a/app/api/server/v1/channels.js +++ b/app/api/server/v1/channels.js @@ -387,17 +387,17 @@ API.v1.addRoute('channels.history', { authRequired: true }, { const unreads = this.queryParams.unreads || false; - let result; - Meteor.runAsUser(this.userId, () => { - result = Meteor.call('getChannelHistory', { - rid: findResult._id, - latest: latestDate, - oldest: oldestDate, - inclusive, - offset, - count, - unreads, - }); + const showThreadMessages = this.queryParams.showThreadMessages !== 'false'; + + const result = Meteor.call('getChannelHistory', { + rid: findResult._id, + latest: latestDate, + oldest: oldestDate, + inclusive, + offset, + count, + unreads, + showThreadMessages, }); if (!result) { diff --git a/app/api/server/v1/groups.js b/app/api/server/v1/groups.js index ce0f06fc1813f..4799f68bbf8be 100644 --- a/app/api/server/v1/groups.js +++ b/app/api/server/v1/groups.js @@ -359,9 +359,17 @@ API.v1.addRoute('groups.history', { authRequired: true }, { const unreads = this.queryParams.unreads || false; - let result; - Meteor.runAsUser(this.userId, () => { - result = Meteor.call('getChannelHistory', { rid: findResult.rid, latest: latestDate, oldest: oldestDate, inclusive, offset, count, unreads }); + const showThreadMessages = this.queryParams.showThreadMessages !== 'false'; + + const result = Meteor.call('getChannelHistory', { + rid: findResult.rid, + latest: latestDate, + oldest: oldestDate, + inclusive, + offset, + count, + unreads, + showThreadMessages, }); if (!result) { diff --git a/app/api/server/v1/im.js b/app/api/server/v1/im.js index b367596b46983..233f0320d8ad1 100644 --- a/app/api/server/v1/im.js +++ b/app/api/server/v1/im.js @@ -176,17 +176,17 @@ API.v1.addRoute(['dm.history', 'im.history'], { authRequired: true }, { const unreads = this.queryParams.unreads || false; - let result; - Meteor.runAsUser(this.userId, () => { - result = Meteor.call('getChannelHistory', { - rid: findResult.room._id, - latest: latestDate, - oldest: oldestDate, - inclusive, - offset, - count, - unreads, - }); + const showThreadMessages = this.queryParams.showThreadMessages !== 'false'; + + const result = Meteor.call('getChannelHistory', { + rid: findResult.room._id, + latest: latestDate, + oldest: oldestDate, + inclusive, + offset, + count, + unreads, + showThreadMessages, }); if (!result) { diff --git a/app/lib/server/functions/loadMessageHistory.js b/app/lib/server/functions/loadMessageHistory.js index 991f0976cc3e4..27e2d1d3db977 100644 --- a/app/lib/server/functions/loadMessageHistory.js +++ b/app/lib/server/functions/loadMessageHistory.js @@ -1,19 +1,13 @@ -import { settings } from '../../../settings'; -import { Messages, Rooms } from '../../../models'; +import { settings } from '../../../settings/server'; +import { Messages, Rooms } from '../../../models/server'; import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser'; - -const hideMessagesOfTypeServer = new Set(); - -settings.get('Hide_System_Messages', function(key, values) { - const hiddenTypes = values.reduce((array, value) => [...array, ...value === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [value]], []); - hideMessagesOfTypeServer.clear(); - hiddenTypes.forEach((item) => hideMessagesOfTypeServer.add(item)); -}); +import { getHiddenSystemMessages } from '../lib/getHiddenSystemMessages'; export const loadMessageHistory = function loadMessageHistory({ userId, rid, end, limit = 20, ls, showThreadMessages = true }) { - const room = Rooms.findOne(rid, { fields: { sysMes: 1 } }); + const room = Rooms.findOneById(rid, { fields: { sysMes: 1 } }); + + const hiddenMessageTypes = getHiddenSystemMessages(room); - const hiddenMessageTypes = Array.isArray(room && room.sysMes) ? room.sysMes : Array.from(hideMessagesOfTypeServer.values()); // TODO probably remove on chained event system const options = { sort: { ts: -1, diff --git a/app/lib/server/lib/getHiddenSystemMessages.ts b/app/lib/server/lib/getHiddenSystemMessages.ts new file mode 100644 index 0000000000000..0d734dacfc545 --- /dev/null +++ b/app/lib/server/lib/getHiddenSystemMessages.ts @@ -0,0 +1,23 @@ +import { settings } from '../../../settings/server'; +import { IRoom } from '../../../../definition/IRoom'; + +const hideMessagesOfTypeServer = new Set(); + +settings.get('Hide_System_Messages', function(_key, values) { + if (!values || !Array.isArray(values)) { + return; + } + + const hiddenTypes = values.reduce((array: string[], value: string) => [...array, ...value === 'mute_unmute' ? ['user-muted', 'user-unmuted'] : [value]], []); + + hideMessagesOfTypeServer.clear(); + + hiddenTypes.forEach((item) => hideMessagesOfTypeServer.add(item)); +}); + +// TODO probably remove on chained event system +export function getHiddenSystemMessages(room: IRoom): string[] { + return Array.isArray(room?.sysMes) + ? room.sysMes + : [...hideMessagesOfTypeServer]; +} diff --git a/app/lib/server/methods/getChannelHistory.js b/app/lib/server/methods/getChannelHistory.js index f506686d1f89b..2443a3b153028 100644 --- a/app/lib/server/methods/getChannelHistory.js +++ b/app/lib/server/methods/getChannelHistory.js @@ -2,13 +2,14 @@ import { Meteor } from 'meteor/meteor'; import { check } from 'meteor/check'; import _ from 'underscore'; -import { hasPermission } from '../../../authorization'; -import { Subscriptions, Messages } from '../../../models'; -import { settings } from '../../../settings'; +import { hasPermission } from '../../../authorization/server'; +import { Subscriptions, Messages } from '../../../models/server'; +import { settings } from '../../../settings/server'; import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser'; +import { getHiddenSystemMessages } from '../lib/getHiddenSystemMessages'; Meteor.methods({ - getChannelHistory({ rid, latest, oldest, inclusive, offset = 0, count = 20, unreads }) { + getChannelHistory({ rid, latest, oldest, inclusive, offset = 0, count = 20, unreads, showThreadMessages = true }) { check(rid, String); if (!Meteor.userId()) { @@ -36,6 +37,8 @@ Meteor.methods({ throw new Meteor.Error('error-invalid-date', 'Invalid date', { method: 'getChannelHistory' }); } + const hiddenMessageTypes = getHiddenSystemMessages(room); + const options = { sort: { ts: -1, @@ -48,16 +51,9 @@ Meteor.methods({ options.fields = { editedAt: 0 }; } - let records = []; - if (_.isUndefined(oldest) && inclusive) { - records = Messages.findVisibleByRoomIdBeforeTimestampInclusive(rid, latest, options).fetch(); - } else if (_.isUndefined(oldest) && !inclusive) { - records = Messages.findVisibleByRoomIdBeforeTimestamp(rid, latest, options).fetch(); - } else if (!_.isUndefined(oldest) && inclusive) { - records = Messages.findVisibleByRoomIdBetweenTimestampsInclusive(rid, oldest, latest, options).fetch(); - } else { - records = Messages.findVisibleByRoomIdBetweenTimestamps(rid, oldest, latest, options).fetch(); - } + const records = _.isUndefined(oldest) + ? Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(rid, latest, hiddenMessageTypes, options, showThreadMessages, inclusive).fetch() + : Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(rid, oldest, latest, options, showThreadMessages, inclusive).fetch(); const messages = normalizeMessagesForUser(records, fromUserId); @@ -68,7 +64,20 @@ Meteor.methods({ if (!_.isUndefined(oldest)) { const firstMsg = messages[messages.length - 1]; if (!_.isUndefined(firstMsg) && firstMsg.ts > oldest) { - const unreadMessages = Messages.findVisibleByRoomIdBetweenTimestamps(rid, oldest, firstMsg.ts, { limit: 1, sort: { ts: 1 } }); + const unreadMessages = Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes( + rid, + oldest, + firstMsg.ts, + hiddenMessageTypes, + { + limit: 1, + sort: { + ts: 1, + }, + }, + showThreadMessages, + ); + firstUnread = unreadMessages.fetch()[0]; unreadNotLoaded = unreadMessages.count(); } diff --git a/app/models/server/models/Messages.js b/app/models/server/models/Messages.js index f02dbf1c34a40..c02c902af2f14 100644 --- a/app/models/server/models/Messages.js +++ b/app/models/server/models/Messages.js @@ -323,58 +323,14 @@ export class Messages extends Base { return this.find(query, options); } - findVisibleByRoomIdBeforeTimestampInclusive(roomId, timestamp, options) { + findVisibleByRoomIdBeforeTimestampNotContainingTypes(roomId, timestamp, types, options, showThreadMessages = true, inclusive = false) { const query = { _hidden: { $ne: true, }, rid: roomId, ts: { - $lte: timestamp, - }, - }; - - return this.find(query, options); - } - - findVisibleByRoomIdBetweenTimestamps(roomId, afterTimestamp, beforeTimestamp, options) { - const query = { - _hidden: { - $ne: true, - }, - rid: roomId, - ts: { - $gt: afterTimestamp, - $lt: beforeTimestamp, - }, - }; - - return this.find(query, options); - } - - findVisibleByRoomIdBetweenTimestampsInclusive(roomId, afterTimestamp, beforeTimestamp, options) { - const query = { - _hidden: { - $ne: true, - }, - rid: roomId, - ts: { - $gte: afterTimestamp, - $lte: beforeTimestamp, - }, - }; - - return this.find(query, options); - } - - findVisibleByRoomIdBeforeTimestampNotContainingTypes(roomId, timestamp, types, options, showThreadMessages = true) { - const query = { - _hidden: { - $ne: true, - }, - rid: roomId, - ts: { - $lt: timestamp, + [inclusive ? '$lte' : '$lt']: timestamp, }, ...!showThreadMessages && { $or: [{ @@ -392,15 +348,15 @@ export class Messages extends Base { return this.find(query, options); } - findVisibleByRoomIdBetweenTimestampsNotContainingTypes(roomId, afterTimestamp, beforeTimestamp, types, options, showThreadMessages = true) { + findVisibleByRoomIdBetweenTimestampsNotContainingTypes(roomId, afterTimestamp, beforeTimestamp, types, options, showThreadMessages = true, inclusive = false) { const query = { _hidden: { $ne: true, }, rid: roomId, ts: { - $gt: afterTimestamp, - $lt: beforeTimestamp, + [inclusive ? '$gte' : '$gt']: afterTimestamp, + [inclusive ? '$lte' : '$lt']: beforeTimestamp, }, ...!showThreadMessages && { $or: [{ diff --git a/definition/IRoom.ts b/definition/IRoom.ts index b07fce566dc35..eae89900bb4c7 100644 --- a/definition/IRoom.ts +++ b/definition/IRoom.ts @@ -58,6 +58,8 @@ export interface IRoom extends IRocketChatRecord { unread?: number; alert?: boolean; hideUnreadStatus?: boolean; + + sysMes?: string[]; } export interface IDirectMessageRoom extends Omit { diff --git a/definition/ISetting.ts b/definition/ISetting.ts index 16cf30f1b3f23..8ee649a459ef5 100644 --- a/definition/ISetting.ts +++ b/definition/ISetting.ts @@ -9,8 +9,8 @@ export enum SettingEditor { EXPRESSION = 'expression' } -export type SettingValueMultiSelect = Array<{key: string; i18nLabel: string}> -export type SettingValueRoomPick = Array<{_id: string; name: string}> | string +export type SettingValueMultiSelect = string[]; +export type SettingValueRoomPick = Array<{_id: string; name: string}> | string; export type SettingValue = string | boolean | number | SettingValueMultiSelect | undefined; export interface ISettingSelectOption {