The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Rocket.Chat/app/threads/client/flextab/threads.js

167 lines
4.7 KiB

import { Mongo } from 'meteor/mongo';
import { Tracker } from 'meteor/tracker';
import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';
import _ from 'underscore';
import { lazyloadtick } from '../../../lazy-load';
import { call } from '../../../ui-utils';
import { Messages, Subscriptions } from '../../../models';
import { messageContext } from '../../../ui-utils/client/lib/messageContext';
import { messageArgs } from '../../../ui-utils/client/lib/messageArgs';
import { upsert } from '../upsert';
import './threads.html';
const LIST_SIZE = 50;
const sort = { tlm: -1 };
Template.threads.events({
'click .js-open-thread'(e, instance) {
const { msg } = messageArgs(this);
instance.state.set('mid', msg._id);
e.preventDefault();
e.stopPropagation();
return false;
},
'scroll .js-scroll-threads': _.throttle(({ currentTarget: e }, { incLimit }) => {
lazyloadtick();
if (e.offsetHeight + e.scrollTop <= e.scrollHeight - 50) {
incLimit && incLimit();
}
}, 500),
});
Template.threads.helpers({
doDotLoadThreads() {
return Template.instance().state.get('close');
},
close() {
const { state, data } = Template.instance();
const { tabBar } = data;
return () => (state.get('close') ? tabBar.close() : state.set('mid', null));
},
message() {
return Template.instance().state.get('thread');
},
isLoading() {
return Template.instance().state.get('loading');
},
hasNoThreads() {
return !Template.instance().state.get('loading') && Template.instance().Threads.find({ rid: Template.instance().state.get('rid') }, { sort }).count() === 0;
},
threads() {
return Template.instance().Threads.find({ rid: Template.instance().state.get('rid') }, { sort, limit: Template.instance().state.get('limit') });
},
messageContext,
});
Template.threads.onCreated(async function() {
this.Threads = new Mongo.Collection(null);
const { rid, mid, msg } = this.data;
this.state = new ReactiveDict({
rid,
close: !!mid,
loading: true,
mid,
thread: msg,
});
this.incLimit = () => {
const { rid, limit } = Tracker.nonreactive(() => this.state.all());
const count = this.Threads.find({ rid }).count();
if (limit > count) {
return;
}
this.state.set('limit', this.state.get('limit') + LIST_SIZE);
this.loadMore();
};
this.loadMore = _.debounce(async () => {
const { rid, limit } = Tracker.nonreactive(() => this.state.all());
if (this.state.get('loading') === rid) {
return;
}
this.state.set('loading', rid);
const threads = await call('getThreadsList', { rid, limit: LIST_SIZE, skip: limit - LIST_SIZE });
upsert(this.Threads, threads);
// threads.forEach(({ _id, ...msg }) => this.Threads.upsert({ _id }, msg));
this.state.set('loading', false);
}, 500);
Tracker.afterFlush(() => {
this.autorun(async () => {
const { rid, mid } = Template.currentData();
this.state.set({
close: !!mid,
mid,
rid,
});
});
});
this.autorun(() => {
const rid = this.state.get('rid');
this.rid = rid;
this.state.set({
limit: LIST_SIZE,
});
this.loadMore();
});
this.autorun(() => {
const rid = this.state.get('rid');
this.threadsObserve && this.threadsObserve.stop();
this.threadsObserve = Messages.find({ rid, _updatedAt: { $gt: new Date() }, tcount: { $exists: true } }).observe({
added: ({ _id, ...message }) => {
this.Threads.upsert({ _id }, message);
}, // Update message to re-render DOM
changed: ({ _id, ...message }) => {
this.Threads.update({ _id }, message);
}, // Update message to re-render DOM
removed: ({ _id }) => {
this.Threads.remove(_id);
const { _id: mid } = this.mid.get() || {};
if (_id === mid) {
this.mid.set(null);
}
},
});
const alert = 'Unread';
this.subscriptionObserve && this.subscriptionObserve.stop();
this.subscriptionObserve = Subscriptions.find({ rid }, { fields: { tunread: 1 } }).observeChanges({
added: (_id, { tunread }) => {
tunread && tunread.length && this.Threads.update({ tmid: { $in: tunread } }, { $set: { alert } }, { multi: true });
},
changed: (id, { tunread = [] }) => {
this.Threads.update({ alert, _id: { $nin: tunread } }, { $unset: { alert: 1 } }, { multi: true });
tunread && tunread.length && this.Threads.update({ _id: { $in: tunread } }, { $set: { alert } }, { multi: true });
},
});
});
this.autorun(async () => {
const mid = this.state.get('mid');
return this.state.set('thread', mid && this.Threads.findOne({ _id: mid }, { fields: { tcount: 0, tlm: 0, replies: 0, _updatedAt: 0 } }));
});
});
Template.threads.onDestroyed(function() {
const { Threads, threadsObserve, subscriptionObserve } = this;
Threads.remove({});
threadsObserve && threadsObserve.stop();
subscriptionObserve && subscriptionObserve.stop();
});