From ea1fd9cda31bb947e103f076b6b256ca33a6a3a3 Mon Sep 17 00:00:00 2001 From: Marcos Defendi Date: Tue, 8 Oct 2019 15:16:11 -0300 Subject: [PATCH 1/8] Move removeFileByRoomId to FileUpload class to avoid circular dependencies --- app/file-upload/server/lib/FileUpload.js | 14 ++++++++++++++ app/lib/server/functions/deleteRoom.js | 3 ++- app/lib/server/functions/deleteUser.js | 2 +- app/livechat/server/lib/Livechat.js | 3 ++- app/models/server/models/Messages.js | 14 -------------- server/startup/migrations/v131.js | 3 ++- 6 files changed, 21 insertions(+), 18 deletions(-) diff --git a/app/file-upload/server/lib/FileUpload.js b/app/file-upload/server/lib/FileUpload.js index 4654c9f197e80..ca365fb9ff8d1 100644 --- a/app/file-upload/server/lib/FileUpload.js +++ b/app/file-upload/server/lib/FileUpload.js @@ -24,6 +24,7 @@ import { hasPermission } from '../../../authorization/server/functions/hasPermis import { canAccessRoom } from '../../../authorization/server/functions/canAccessRoom'; import { fileUploadIsValidContentType } from '../../../utils/lib/fileUploadRestrictions'; import { isValidJWT, generateJWT } from '../../../utils/server/lib/JWTHelper'; +import { Messages } from '../../../models/server'; const cookie = new Cookies(); let maxFileSize = 0; @@ -403,6 +404,19 @@ export const FileUpload = { fileId, }, settings.get('FileUpload_json_web_token_secret_for_files')); }, + + removeFilesByRoomId(roomId) { + Messages.find({ + rid: roomId, + 'file._id': { + $exists: true, + }, + }, { + fields: { + 'file._id': 1, + }, + }).fetch().forEach((document) => FileUpload.getStore('Uploads').deleteById(document.file._id)); + }, }; export class FileUploadClass { diff --git a/app/lib/server/functions/deleteRoom.js b/app/lib/server/functions/deleteRoom.js index a00d11d0acfab..dab074e4ccf54 100644 --- a/app/lib/server/functions/deleteRoom.js +++ b/app/lib/server/functions/deleteRoom.js @@ -1,8 +1,9 @@ import { Messages, Subscriptions, Rooms } from '../../../models'; import { callbacks } from '../../../callbacks'; +import { FileUpload } from '../../../file-upload/server'; export const deleteRoom = function(rid) { - Messages.removeFilesByRoomId(rid); + FileUpload.removeFilesByRoomId(rid); Messages.removeByRoomId(rid); callbacks.run('beforeDeleteRoom', rid); Subscriptions.removeByRoomId(rid); diff --git a/app/lib/server/functions/deleteUser.js b/app/lib/server/functions/deleteUser.js index 5f127edb1bf50..031ce3c612eb4 100644 --- a/app/lib/server/functions/deleteUser.js +++ b/app/lib/server/functions/deleteUser.js @@ -86,7 +86,7 @@ export const deleteUser = function(userId) { // Remove DMs and non-channel rooms with only 1 user (the one being deleted) if (roomData.t === 'd' || (roomData.t !== 'c' && roomData.subscribers === 1)) { Subscriptions.removeByRoomId(roomData.rid); - Messages.removeFilesByRoomId(roomData.rid); + FileUpload.removeFilesByRoomId(roomData.rid); Messages.removeByRoomId(roomData.rid); Rooms.removeById(roomData.rid); } diff --git a/app/livechat/server/lib/Livechat.js b/app/livechat/server/lib/Livechat.js index 6a9bca7bd8a33..530b83e7f21f5 100644 --- a/app/livechat/server/lib/Livechat.js +++ b/app/livechat/server/lib/Livechat.js @@ -35,6 +35,7 @@ import { LivechatInquiry } from '../../lib/LivechatInquiry'; import { sendMessage } from '../../../lib/server/functions/sendMessage'; import { updateMessage } from '../../../lib/server/functions/updateMessage'; import { deleteMessage } from '../../../lib/server/functions/deleteMessage'; +import { FileUpload } from '../../../file-upload/server'; export const Livechat = { Analytics, @@ -635,7 +636,7 @@ export const Livechat = { check(token, String); LivechatRooms.findByVisitorToken(token).forEach((room) => { - Messages.removeFilesByRoomId(room._id); + FileUpload.removeFilesByRoomId(room._id); Messages.removeByRoomId(room._id); }); diff --git a/app/models/server/models/Messages.js b/app/models/server/models/Messages.js index 0489bc85226c2..71515b51271ac 100644 --- a/app/models/server/models/Messages.js +++ b/app/models/server/models/Messages.js @@ -4,7 +4,6 @@ import _ from 'underscore'; import { Base } from './_Base'; import Rooms from './Rooms'; import { settings } from '../../../settings/server/functions/settings'; -import { FileUpload } from '../../../file-upload/server/lib/FileUpload'; export class Messages extends Base { constructor() { @@ -905,19 +904,6 @@ export class Messages extends Base { return this.remove(query); } - async removeFilesByRoomId(roomId) { - this.find({ - rid: roomId, - 'file._id': { - $exists: true, - }, - }, { - fields: { - 'file._id': 1, - }, - }).fetch().forEach((document) => FileUpload.getStore('Uploads').deleteById(document.file._id)); - } - getMessageByFileId(fileID) { return this.findOne({ 'file._id': fileID }); } diff --git a/server/startup/migrations/v131.js b/server/startup/migrations/v131.js index 0d047991e8f69..fb895ca9030d8 100644 --- a/server/startup/migrations/v131.js +++ b/server/startup/migrations/v131.js @@ -1,5 +1,6 @@ import { Migrations } from '../../../app/migrations'; import { Users, Subscriptions, Rooms, Messages } from '../../../app/models'; +import { FileUpload } from '../../../app/file-upload/server'; Migrations.add({ version: 131, @@ -35,7 +36,7 @@ Migrations.add({ // Remove direct messages and also non-channel rooms with only 1 user (the one being deleted) if (room.t === 'd' || (room.t !== 'c' && Subscriptions.findByRoomId(room._id).count() === 1)) { Subscriptions.removeByRoomId(subscription.rid); - Messages.removeFilesByRoomId(subscription.rid); + FileUpload.removeFilesByRoomId(subscription.rid); Messages.removeByRoomId(subscription.rid); Rooms.removeById(subscription.rid); } From b94a69a1ba92aa3bc77f7a1b36491cb9b72c8172 Mon Sep 17 00:00:00 2001 From: Marcos Defendi Date: Tue, 8 Oct 2019 15:22:09 -0300 Subject: [PATCH 2/8] Add endpoint to replace publication --- app/api/server/lib/messages.js | 30 ++++++++++++++++++++++ app/api/server/v1/chat.js | 22 +++++++++++++++++ app/models/server/raw/Messages.js | 13 ++++++++++ app/models/server/raw/index.js | 3 +++ tests/end-to-end/api/05-chat.js | 41 +++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+) create mode 100644 app/api/server/lib/messages.js create mode 100644 app/models/server/raw/Messages.js diff --git a/app/api/server/lib/messages.js b/app/api/server/lib/messages.js new file mode 100644 index 0000000000000..0ced4824da30f --- /dev/null +++ b/app/api/server/lib/messages.js @@ -0,0 +1,30 @@ +import { canAccessRoomAsync } from '../../../authorization/server/functions/canAccessRoom'; +import { Rooms, Messages, Users } from '../../../models/server/raw'; + +export async function findMentionedMessages({ userId, roomId, pagination: { offset, count, sort } }) { + const room = await Rooms.findOneById(roomId); + if (!await canAccessRoomAsync(room, { _id: userId })) { + throw new Error('error-not-allowed'); + } + const user = await Users.findOneById(userId, { fields: { username: 1 } }); + if (!user) { + throw new Error('invalid-user'); + } + + const cursor = await Messages.findVisibleByMentionAndRoomId(user.username, roomId, { + sort: sort || { ts: -1 }, + skip: offset, + limit: count, + }); + + const total = await cursor.count(); + + const messages = await cursor.toArray(); + + return { + messages, + count: messages.length, + offset, + total, + }; +} diff --git a/app/api/server/v1/chat.js b/app/api/server/v1/chat.js index 50b7eeb9d9ec6..40ac5768e9c11 100644 --- a/app/api/server/v1/chat.js +++ b/app/api/server/v1/chat.js @@ -9,6 +9,7 @@ import { API } from '../api'; import Rooms from '../../../models/server/models/Rooms'; import Users from '../../../models/server/models/Users'; import { settings } from '../../../settings'; +import { findMentionedMessages } from '../lib/messages'; API.v1.addRoute('chat.delete', { authRequired: true }, { post() { @@ -599,3 +600,24 @@ API.v1.addRoute('chat.unfollowMessage', { authRequired: true }, { return API.v1.success(); }, }); + +API.v1.addRoute('chat.getMentionedMessages', { authRequired: true }, { + get() { + const { roomId } = this.queryParams; + const { sort } = this.parseJsonQuery(); + const { offset, count } = this.getPaginationItems(); + if (!roomId) { + throw new Meteor.Error('error-invalid-params', 'The required "roomId" query param is missing.'); + } + const messages = Promise.await(findMentionedMessages({ + userId: this.userId, + roomId, + pagination: { + offset, + count, + sort, + }, + })); + return API.v1.success(messages); + }, +}); diff --git a/app/models/server/raw/Messages.js b/app/models/server/raw/Messages.js new file mode 100644 index 0000000000000..62496b4a8d346 --- /dev/null +++ b/app/models/server/raw/Messages.js @@ -0,0 +1,13 @@ +import { BaseRaw } from './BaseRaw'; + +export class MessagesRaw extends BaseRaw { + findVisibleByMentionAndRoomId(username, rid, options) { + const query = { + _hidden: { $ne: true }, + 'mentions.username': username, + rid, + }; + + return this.find(query, options); + } +} diff --git a/app/models/server/raw/index.js b/app/models/server/raw/index.js index 50456b5a61cd0..12b7ec7f556f9 100644 --- a/app/models/server/raw/index.js +++ b/app/models/server/raw/index.js @@ -14,6 +14,8 @@ import LivechatDepartmentModel from '../models/LivechatDepartment'; import { LivechatDepartmentRaw } from './LivechatDepartment'; import LivechatDepartmentAgentsModel from '../models/LivechatDepartmentAgents'; import { LivechatDepartmentAgentsRaw } from './LivechatDepartmentAgents'; +import MessagesModel from '../models/Messages'; +import { MessagesRaw } from './Messages'; export const Permissions = new PermissionsRaw(PermissionsModel.model.rawCollection()); export const Roles = new RolesRaw(RolesModel.model.rawCollection()); @@ -23,3 +25,4 @@ export const Users = new UsersRaw(UsersModel.model.rawCollection()); export const Rooms = new RoomsRaw(RoomsModel.model.rawCollection()); export const LivechatDepartment = new LivechatDepartmentRaw(LivechatDepartmentModel.model.rawCollection()); export const LivechatDepartmentAgents = new LivechatDepartmentAgentsRaw(LivechatDepartmentAgentsModel.model.rawCollection()); +export const Messages = new MessagesRaw(MessagesModel.model.rawCollection()); diff --git a/tests/end-to-end/api/05-chat.js b/tests/end-to-end/api/05-chat.js index c626cae609ed9..a3a12f3cc5cd8 100644 --- a/tests/end-to-end/api/05-chat.js +++ b/tests/end-to-end/api/05-chat.js @@ -2076,4 +2076,45 @@ describe('Threads', () => { }); }); }); + + describe('[/chat.getMentionedMessages]', () => { + it('should return an error when the required "roomId" parameter is not sent', (done) => { + request.get(api('chat.getMentionedMessages')) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + expect(res.body.errorType).to.be.equal('error-invalid-params'); + }) + .end(done); + }); + + it('should return an error when the roomId is invalid', (done) => { + request.get(api('chat.getMentionedMessages?roomId=invalid-room')) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + expect(res.body.error).to.be.equal('error-not-allowed'); + }) + .end(done); + }); + + it('should return the mentioned messages', (done) => { + request.get(api('chat.getMentionedMessages?roomId=GENERAL')) + .set(credentials) + .expect('Content-Type', 'application/json') + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body.messages).to.be.an('array'); + expect(res.body).to.have.property('offset'); + expect(res.body).to.have.property('total'); + expect(res.body).to.have.property('count'); + }) + .end(done); + }); + }); }); From 542722632ffe17b86f25eb87a2794eddf54dff0a Mon Sep 17 00:00:00 2001 From: Marcos Defendi Date: Tue, 8 Oct 2019 16:37:36 -0300 Subject: [PATCH 3/8] Remove mentionedMessage subscription --- .../client/lib/MentionedMessage.js | 3 - .../client/views/mentionsFlexTab.js | 55 +++++++++++++------ .../server/publications/mentionedMessages.js | 1 + 3 files changed, 40 insertions(+), 19 deletions(-) delete mode 100644 app/mentions-flextab/client/lib/MentionedMessage.js diff --git a/app/mentions-flextab/client/lib/MentionedMessage.js b/app/mentions-flextab/client/lib/MentionedMessage.js deleted file mode 100644 index 563e2344c1029..0000000000000 --- a/app/mentions-flextab/client/lib/MentionedMessage.js +++ /dev/null @@ -1,3 +0,0 @@ -import { Mongo } from 'meteor/mongo'; - -export const MentionedMessage = new Mongo.Collection('rocketchat_mentioned_message'); diff --git a/app/mentions-flextab/client/views/mentionsFlexTab.js b/app/mentions-flextab/client/views/mentionsFlexTab.js index ed3fad676e9f7..6582c6fed46c5 100644 --- a/app/mentions-flextab/client/views/mentionsFlexTab.js +++ b/app/mentions-flextab/client/views/mentionsFlexTab.js @@ -1,16 +1,18 @@ import _ from 'underscore'; +import { Meteor } from 'meteor/meteor'; import { ReactiveVar } from 'meteor/reactive-var'; import { Template } from 'meteor/templating'; -import { MentionedMessage } from '../lib/MentionedMessage'; import { messageContext } from '../../../ui-utils/client/lib/messageContext'; +import { APIClient } from '../../../utils/client'; +import { Messages } from '../../../models/client'; Template.mentionsFlexTab.helpers({ hasMessages() { - return Template.instance().cursor.count() > 0; + return Template.instance().mentionedMessages.get().length > 0; }, messages() { - return Template.instance().cursor; + return Template.instance().mentionedMessages.get(); }, hasMore() { return Template.instance().hasMore.get(); @@ -18,23 +20,44 @@ Template.mentionsFlexTab.helpers({ messageContext, }); -Template.mentionsFlexTab.onCreated(function() { - this.cursor = MentionedMessage.find({ - rid: this.data.rid, - }, { - sort: { - ts: -1, +const listenForMessageChanges = (instance) => { + const query = { + _hidden: { $ne: true }, + 'mentions.username': Meteor.user().username, + rid: instance.data.rid, + }; + + Messages.find(query).observe({ + added: (message) => { + instance.mentionedMessages.set(instance.mentionedMessages.curValue.concat(message)); + }, + changed: (message) => { + instance.mentionedMessages.set(instance.mentionedMessages.curValue.map((mentionedMessage) => { + if (message._id === mentionedMessage._id) { + mentionedMessage = message; + } + return mentionedMessage; + })); + }, + removed: ({ _id }) => { + instance.mentionedMessages.set(instance.mentionedMessages.curValue.filter((message) => message._id !== _id)); }, }); +}; + +Template.mentionsFlexTab.onCreated(function() { this.hasMore = new ReactiveVar(true); this.limit = new ReactiveVar(50); - return this.autorun(() => { - const mentionedMessageFind = MentionedMessage.find({ rid: this.data.rid }); - return this.subscribe('mentionedMessages', this.data.rid, this.limit.get(), () => { - if (mentionedMessageFind.count() < this.limit.get()) { - return this.hasMore.set(false); - } - }); + this.mentionedMessages = new ReactiveVar([]); + + listenForMessageChanges(this); + + return this.autorun(async () => { + const { messages, total } = await APIClient.v1.get(`chat.getMentionedMessages?roomId=${ this.data.rid }&count=${ this.limit.get() }`); + this.mentionedMessages.set(messages); + if (total < this.limit.get()) { + return this.hasMore.set(false); + } }); }); diff --git a/app/mentions-flextab/server/publications/mentionedMessages.js b/app/mentions-flextab/server/publications/mentionedMessages.js index 8eaa292347e00..1fd23b563604d 100644 --- a/app/mentions-flextab/server/publications/mentionedMessages.js +++ b/app/mentions-flextab/server/publications/mentionedMessages.js @@ -3,6 +3,7 @@ import { Meteor } from 'meteor/meteor'; import { Users, Messages } from '../../../models'; Meteor.publish('mentionedMessages', function(rid, limit = 50) { + console.warn('The publication "mentionedMessages" is deprecated and will be removed after version v3.0.0'); if (!this.userId) { return this.ready(); } From ab103184e41d01df7831642ea2c559dcc2e700c9 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 8 Oct 2019 17:07:00 -0300 Subject: [PATCH 4/8] Apply suggestions from code review --- app/api/server/lib/messages.js | 6 +++--- app/api/server/v1/chat.js | 2 +- app/file-upload/server/lib/FileUpload.js | 4 ++-- app/mentions-flextab/client/views/mentionsFlexTab.js | 4 +--- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/api/server/lib/messages.js b/app/api/server/lib/messages.js index 0ced4824da30f..2b2d9a9c23ef9 100644 --- a/app/api/server/lib/messages.js +++ b/app/api/server/lib/messages.js @@ -1,12 +1,12 @@ import { canAccessRoomAsync } from '../../../authorization/server/functions/canAccessRoom'; import { Rooms, Messages, Users } from '../../../models/server/raw'; -export async function findMentionedMessages({ userId, roomId, pagination: { offset, count, sort } }) { +export async function findMentionedMessages({ uid, roomId, pagination: { offset, count, sort } }) { const room = await Rooms.findOneById(roomId); - if (!await canAccessRoomAsync(room, { _id: userId })) { + if (!await canAccessRoomAsync(room, { _id: uid })) { throw new Error('error-not-allowed'); } - const user = await Users.findOneById(userId, { fields: { username: 1 } }); + const user = await Users.findOneById(uid, { fields: { username: 1 } }); if (!user) { throw new Error('invalid-user'); } diff --git a/app/api/server/v1/chat.js b/app/api/server/v1/chat.js index 40ac5768e9c11..b015651f0285c 100644 --- a/app/api/server/v1/chat.js +++ b/app/api/server/v1/chat.js @@ -610,7 +610,7 @@ API.v1.addRoute('chat.getMentionedMessages', { authRequired: true }, { throw new Meteor.Error('error-invalid-params', 'The required "roomId" query param is missing.'); } const messages = Promise.await(findMentionedMessages({ - userId: this.userId, + uid: this.userId, roomId, pagination: { offset, diff --git a/app/file-upload/server/lib/FileUpload.js b/app/file-upload/server/lib/FileUpload.js index ca365fb9ff8d1..8fb538c5b64dc 100644 --- a/app/file-upload/server/lib/FileUpload.js +++ b/app/file-upload/server/lib/FileUpload.js @@ -405,9 +405,9 @@ export const FileUpload = { }, settings.get('FileUpload_json_web_token_secret_for_files')); }, - removeFilesByRoomId(roomId) { + removeFilesByRoomId(rid) { Messages.find({ - rid: roomId, + rid, 'file._id': { $exists: true, }, diff --git a/app/mentions-flextab/client/views/mentionsFlexTab.js b/app/mentions-flextab/client/views/mentionsFlexTab.js index 6582c6fed46c5..ce018014ddce0 100644 --- a/app/mentions-flextab/client/views/mentionsFlexTab.js +++ b/app/mentions-flextab/client/views/mentionsFlexTab.js @@ -55,9 +55,7 @@ Template.mentionsFlexTab.onCreated(function() { return this.autorun(async () => { const { messages, total } = await APIClient.v1.get(`chat.getMentionedMessages?roomId=${ this.data.rid }&count=${ this.limit.get() }`); this.mentionedMessages.set(messages); - if (total < this.limit.get()) { - return this.hasMore.set(false); - } + this.hasMore.set(total > this.limit.get()); }); }); From 91ef03f6ba8546cad2a70b1786986fad4c40cb6e Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 8 Oct 2019 17:27:18 -0300 Subject: [PATCH 5/8] fix review --- .../client/views/mentionsFlexTab.js | 79 +++++++++++-------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/app/mentions-flextab/client/views/mentionsFlexTab.js b/app/mentions-flextab/client/views/mentionsFlexTab.js index ce018014ddce0..83eff72987707 100644 --- a/app/mentions-flextab/client/views/mentionsFlexTab.js +++ b/app/mentions-flextab/client/views/mentionsFlexTab.js @@ -5,14 +5,16 @@ import { Template } from 'meteor/templating'; import { messageContext } from '../../../ui-utils/client/lib/messageContext'; import { APIClient } from '../../../utils/client'; -import { Messages } from '../../../models/client'; +import { Messages, Users } from '../../../models/client'; + +const LIMIT_DEFAULT = 50; Template.mentionsFlexTab.helpers({ hasMessages() { return Template.instance().mentionedMessages.get().length > 0; }, messages() { - return Template.instance().mentionedMessages.get(); + return Template.instance().mentionedMessages.get().slice(0, Template.instance().limit.get()); }, hasMore() { return Template.instance().hasMore.get(); @@ -20,45 +22,58 @@ Template.mentionsFlexTab.helpers({ messageContext, }); -const listenForMessageChanges = (instance) => { - const query = { - _hidden: { $ne: true }, - 'mentions.username': Meteor.user().username, - rid: instance.data.rid, - }; - - Messages.find(query).observe({ - added: (message) => { - instance.mentionedMessages.set(instance.mentionedMessages.curValue.concat(message)); - }, - changed: (message) => { - instance.mentionedMessages.set(instance.mentionedMessages.curValue.map((mentionedMessage) => { - if (message._id === mentionedMessage._id) { - mentionedMessage = message; - } - return mentionedMessage; - })); - }, - removed: ({ _id }) => { - instance.mentionedMessages.set(instance.mentionedMessages.curValue.filter((message) => message._id !== _id)); - }, - }); -}; - Template.mentionsFlexTab.onCreated(function() { this.hasMore = new ReactiveVar(true); - this.limit = new ReactiveVar(50); + this.limit = new ReactiveVar(LIMIT_DEFAULT); this.mentionedMessages = new ReactiveVar([]); - listenForMessageChanges(this); + this.autorun(() => { + + const query = { + _hidden: { $ne: true }, + 'mentions.username': Users.findOne(Meteor.userId(), { fields: { username: 1 } }).username, + rid: this.data.rid, + _updatedAt: { + $gt: new Date(), + } + }; + + this.cursor && this.cursor.stop(); - return this.autorun(async () => { - const { messages, total } = await APIClient.v1.get(`chat.getMentionedMessages?roomId=${ this.data.rid }&count=${ this.limit.get() }`); + this.limit.set(LIMIT_DEFAULT); + + this.cursor = Messages.find(query, { sort: { ts : 1 } }).observe({ + added: (message) => { + this.mentionedMessages.set(this.mentionedMessages.curValue.concat(message)); + }, + changed: (message) => { + this.mentionedMessages.set(this.mentionedMessages.curValue.map((mentionedMessage) => { + if (message._id === mentionedMessage._id) { + mentionedMessage = message; + } + return mentionedMessage; + })); + }, + removed: ({ _id }) => { + this.mentionedMessages.set(this.mentionedMessages.curValue.filter((message) => message._id !== _id)); + }, + }); + + }) + + + this.autorun(async () => { + const limit = this.limit.get(); + const { messages, total } = await APIClient.v1.get(`chat.getMentionedMessages?roomId=${ this.data.rid }&count=${ limit }`); this.mentionedMessages.set(messages); - this.hasMore.set(total > this.limit.get()); + this.hasMore.set(total > limit); }); }); +Template.mentionsFlexTab.onDestroyed(function() { + this.cursor.stop(); +}); + Template.mentionsFlexTab.events({ 'scroll .js-list': _.throttle(function(e, instance) { if (e.target.scrollTop >= e.target.scrollHeight - e.target.clientHeight && instance.hasMore.get()) { From 8ab1117e31aadb419d1adc2a6959372b14ca9fb4 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 8 Oct 2019 17:45:21 -0300 Subject: [PATCH 6/8] improve collection logic --- .../client/views/mentionsFlexTab.js | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/app/mentions-flextab/client/views/mentionsFlexTab.js b/app/mentions-flextab/client/views/mentionsFlexTab.js index 83eff72987707..6feb4898d0773 100644 --- a/app/mentions-flextab/client/views/mentionsFlexTab.js +++ b/app/mentions-flextab/client/views/mentionsFlexTab.js @@ -4,6 +4,7 @@ import { ReactiveVar } from 'meteor/reactive-var'; import { Template } from 'meteor/templating'; import { messageContext } from '../../../ui-utils/client/lib/messageContext'; +import { upsertMessageBulk } from '../../../ui-utils/client/lib/RoomHistoryManager'; import { APIClient } from '../../../utils/client'; import { Messages, Users } from '../../../models/client'; @@ -11,10 +12,11 @@ const LIMIT_DEFAULT = 50; Template.mentionsFlexTab.helpers({ hasMessages() { - return Template.instance().mentionedMessages.get().length > 0; + return Template.instance().messages.find().count(); }, messages() { - return Template.instance().mentionedMessages.get().slice(0, Template.instance().limit.get()); + const instance = Template.instance(); + return instance.messages.find({}, { limit: instance.limit.get(), sort: { ts: -1 } }); }, hasMore() { return Template.instance().hasMore.get(); @@ -23,9 +25,10 @@ Template.mentionsFlexTab.helpers({ }); Template.mentionsFlexTab.onCreated(function() { + this.messages = new Mongo.Collection(null); + this.hasMore = new ReactiveVar(true); this.limit = new ReactiveVar(LIMIT_DEFAULT); - this.mentionedMessages = new ReactiveVar([]); this.autorun(() => { @@ -42,20 +45,15 @@ Template.mentionsFlexTab.onCreated(function() { this.limit.set(LIMIT_DEFAULT); - this.cursor = Messages.find(query, { sort: { ts : 1 } }).observe({ - added: (message) => { - this.mentionedMessages.set(this.mentionedMessages.curValue.concat(message)); + this.cursor = Messages.find(query).observe({ + added: ({ _id, ...message }) => { + this.messages.upsert({_id}, message); }, - changed: (message) => { - this.mentionedMessages.set(this.mentionedMessages.curValue.map((mentionedMessage) => { - if (message._id === mentionedMessage._id) { - mentionedMessage = message; - } - return mentionedMessage; - })); + changed: ({ _id, ...message }) => { + this.messages.upsert({ _id }, message); }, removed: ({ _id }) => { - this.mentionedMessages.set(this.mentionedMessages.curValue.filter((message) => message._id !== _id)); + this.messages.remove({ _id }); }, }); @@ -65,7 +63,9 @@ Template.mentionsFlexTab.onCreated(function() { this.autorun(async () => { const limit = this.limit.get(); const { messages, total } = await APIClient.v1.get(`chat.getMentionedMessages?roomId=${ this.data.rid }&count=${ limit }`); - this.mentionedMessages.set(messages); + + upsertMessageBulk({ msgs: messages }, this.messages); + this.hasMore.set(total > limit); }); }); From ddae6b87ce24eaebe1441838e86dc81dfa9b7558 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 8 Oct 2019 17:45:53 -0300 Subject: [PATCH 7/8] lint --- app/mentions-flextab/client/views/mentionsFlexTab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/mentions-flextab/client/views/mentionsFlexTab.js b/app/mentions-flextab/client/views/mentionsFlexTab.js index 6feb4898d0773..a263a8540e4c5 100644 --- a/app/mentions-flextab/client/views/mentionsFlexTab.js +++ b/app/mentions-flextab/client/views/mentionsFlexTab.js @@ -47,7 +47,7 @@ Template.mentionsFlexTab.onCreated(function() { this.cursor = Messages.find(query).observe({ added: ({ _id, ...message }) => { - this.messages.upsert({_id}, message); + this.messages.upsert({ _id }, message); }, changed: ({ _id, ...message }) => { this.messages.upsert({ _id }, message); From 55aba97ecfeeaded591214830b1f8c06a1fb7cfc Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 8 Oct 2019 17:50:42 -0300 Subject: [PATCH 8/8] lint --- app/mentions-flextab/client/views/mentionsFlexTab.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/mentions-flextab/client/views/mentionsFlexTab.js b/app/mentions-flextab/client/views/mentionsFlexTab.js index a263a8540e4c5..b1b09030ba98d 100644 --- a/app/mentions-flextab/client/views/mentionsFlexTab.js +++ b/app/mentions-flextab/client/views/mentionsFlexTab.js @@ -1,5 +1,6 @@ import _ from 'underscore'; import { Meteor } from 'meteor/meteor'; +import { Mongo } from 'meteor/mongo'; import { ReactiveVar } from 'meteor/reactive-var'; import { Template } from 'meteor/templating'; @@ -31,14 +32,13 @@ Template.mentionsFlexTab.onCreated(function() { this.limit = new ReactiveVar(LIMIT_DEFAULT); this.autorun(() => { - const query = { _hidden: { $ne: true }, 'mentions.username': Users.findOne(Meteor.userId(), { fields: { username: 1 } }).username, rid: this.data.rid, _updatedAt: { $gt: new Date(), - } + }, }; this.cursor && this.cursor.stop(); @@ -56,9 +56,7 @@ Template.mentionsFlexTab.onCreated(function() { this.messages.remove({ _id }); }, }); - - }) - + }); this.autorun(async () => { const limit = this.limit.get();