diff --git a/app/ui-flextab/client/tabs/uploadedFilesList.js b/app/ui-flextab/client/tabs/uploadedFilesList.js index 764e78c8cde..d0fba2143c1 100644 --- a/app/ui-flextab/client/tabs/uploadedFilesList.js +++ b/app/ui-flextab/client/tabs/uploadedFilesList.js @@ -6,31 +6,122 @@ import { ReactiveVar } from 'meteor/reactive-var'; import { ReactiveDict } from 'meteor/reactive-dict'; import { DateFormat } from '../../../lib/client'; -import { canDeleteMessage, getURL, handleError, t } from '../../../utils/client'; +import { canDeleteMessage, getURL, handleError, t, APIClient } from '../../../utils/client'; import { popover, modal } from '../../../ui-utils/client'; - -const roomFiles = new Mongo.Collection('room_files'); +import { Rooms, Messages } from '../../../models/client'; +import { upsertMessageBulk } from '../../../ui-utils/client/lib/RoomHistoryManager'; const LIST_SIZE = 50; +const DEBOUNCE_TIME_TO_SEARCH_IN_MS = 500; + +const getFileUrl = (attachments) => { + if (!attachments || !attachments.length) { + return; + } + return attachments[0].image_url || attachments[0].audio_url || attachments[0].video_url; +}; + +const mountFileObject = (message) => ({ + ...message.file, + rid: message.rid, + user: message.u, + description: message.attachments && message.attachments[0].description, + url: getFileUrl(message.attachments), + _updatedAt: message.attachments && message.attachments[0].ts, +}); + +const roomTypes = { + c: 'channels', + d: 'im', + p: 'groups', +}; + +const fields = { + _id: 1, + userId: 1, + rid: 1, + name: 1, + description: 1, + type: 1, + url: 1, + uploadedAt: 1, +}; Template.uploadedFilesList.onCreated(function() { const { rid } = Template.currentData(); + const room = Rooms.findOne({ _id: rid }); this.searchText = new ReactiveVar(null); - + this.roomFiles = new ReactiveVar([]); + this.files = new Mongo.Collection(null); this.state = new ReactiveDict({ limit: LIST_SIZE, hasMore: true, }); + const messageQuery = { + rid, + 'file._id': { $exists: true }, + }; + + this.cursor = Messages.find(messageQuery).observe({ + added: ({ ...message }) => { + this.files.upsert(message.file._id, mountFileObject(message)); + }, + changed: ({ ...message }) => { + this.files.upsert(message.file._id, mountFileObject(message)); + }, + removed: ({ ...message }) => { + this.files.remove(message.file._id); + }, + }); + + const loadFiles = _.debounce(async (query, limit) => { + this.state.set('loading', true); + + const { files } = await APIClient.v1.get(`${ roomTypes[room.t] }.files?roomId=${ query.rid }&limit=${ limit }&query=${ JSON.stringify(query) }&fields=${ JSON.stringify(fields) }`); + + upsertMessageBulk({ msgs: files }, this.files); + + this.state.set({ + hasMore: this.state.get('limit') <= files.length, + loading: false, + }); + }, DEBOUNCE_TIME_TO_SEARCH_IN_MS); + + const query = { + rid, + complete: true, + uploading: false, + _hidden: { + $ne: true, + }, + }; + + this.autorun(() => { + this.searchText.get(); + this.state.set('limit', LIST_SIZE); + }); + this.autorun(() => { - const ready = this.subscribe('roomFilesWithSearchText', rid, this.searchText.get(), this.state.get('limit'), () => this.state.set('hasMore', this.state.get('limit') <= roomFiles.find({ rid }).count())).ready(); - this.state.set('loading', !ready); + const limit = this.state.get('limit'); + const searchText = this.searchText.get(); + if (!searchText) { + return loadFiles(query, limit); + } + this.files.remove({}); + const regex = { $regex: searchText, $options: 'i' }; + return loadFiles({ ...query, name: regex }, limit); }); }); +Template.mentionsFlexTab.onDestroyed(function() { + this.cursor.stop(); +}); + Template.uploadedFilesList.helpers({ files() { - return roomFiles.find({ rid: this.rid }, { sort: { uploadedAt: -1 } }); + const instance = Template.instance(); + return instance.files.find({}, { limit: instance.state.get('limit') }); }, url() { diff --git a/server/publications/roomFilesWithSearchText.js b/server/publications/roomFilesWithSearchText.js index f7f26d13a01..a7290886115 100644 --- a/server/publications/roomFilesWithSearchText.js +++ b/server/publications/roomFilesWithSearchText.js @@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { roomFiles } from '../lib/roomFiles'; +console.warn('The publication "roomFilesWithSearchText" is deprecated and will be removed after version v3.0.0'); Meteor.publish('roomFilesWithSearchText', function(rid, searchText, limit = 50) { return roomFiles(this, { rid, searchText, limit }); });