Fix threads rendering performance (#14059)

Fix threads rendering performance
pull/14086/head^2
Guilherme Gazzo 6 years ago committed by Tasso Evangelista
parent 9dffb8e458
commit f8bde388ea
  1. 8
      app/authorization/client/hasPermission.js
  2. 2
      app/models/client/models/Subscriptions.js
  3. 4
      app/threads/client/flextab/thread.html
  4. 2
      app/threads/client/flextab/thread.js
  5. 51
      app/threads/client/flextab/threads.html
  6. 36
      app/threads/client/flextab/threads.js
  7. 39
      app/ui-message/client/message.js
  8. 3
      app/ui/client/views/app/room.js

@ -5,11 +5,11 @@ import { ChatPermissions } from './lib/ChatPermissions';
function atLeastOne(permissions = [], scope) {
return permissions.some((permissionId) => {
const permission = ChatPermissions.findOne(permissionId);
const permission = ChatPermissions.findOne(permissionId, { fields: { roles: 1 } });
const roles = (permission && permission.roles) || [];
return roles.some((roleName) => {
const role = Models.Roles.findOne(roleName);
const role = Models.Roles.findOne(roleName, { fields: { scope: 1 } });
const roleScope = role && role.scope;
const model = Models[roleScope];
@ -20,11 +20,11 @@ function atLeastOne(permissions = [], scope) {
function all(permissions = [], scope) {
return permissions.every((permissionId) => {
const permission = ChatPermissions.findOne(permissionId);
const permission = ChatPermissions.findOne(permissionId, { fields: { roles: 1 } });
const roles = (permission && permission.roles) || [];
return roles.some((roleName) => {
const role = Models.Roles.findOne(roleName);
const role = Models.Roles.findOne(roleName, { fields: { scope: 1 } });
const roleScope = role && role.scope;
const model = Models[roleScope];

@ -14,7 +14,7 @@ Object.assign(Subscriptions, {
rid: roomId,
};
const subscription = this.findOne(query);
const subscription = this.findOne(query, { fields: { roles: 1 } });
return subscription && Array.isArray(subscription.roles) && subscription.roles.includes(roleName);
}, { maxAge: 1000 }),

@ -14,9 +14,9 @@
<div class="thread-list js-scroll-thread">
<ul class="thread">
{{# with messageContext}}
{{> nrr nrrargs 'message' msg=mainMessage room=room subscription=subscription settings=settings customClass="thread-message" templatePrefix='thread-' customClass="thread-main" u=u}}
{{> nrr nrrargs 'message' hideRoles=true msg=mainMessage room=room subscription=subscription settings=settings customClass="thread-message" templatePrefix='thread-' customClass="thread-main" u=u}}
{{#each msg in messages}}
{{> nrr nrrargs 'message' msg=msg room=room subscription=subscription settings=settings templatePrefix='thread-' u=u}}
{{> nrr nrrargs 'message' hideRoles=true msg=msg room=room subscription=subscription settings=settings templatePrefix='thread-' u=u}}
{{/each}}
{{/with}}
</ul>

@ -95,7 +95,7 @@ Template.thread.onRendered(function() {
const tmid = this.state.get('tmid');
this.threadsObserve && this.threadsObserve.stop();
this.threadsObserve = Messages.find({ tmid }).observe({
this.threadsObserve = Messages.find({ tmid, _updatedAt: { $gt: new Date() } }).observe({
added: ({ _id, ...message }) => {
const { atBottom } = this;
this.Threads.upsert({ _id }, message);

@ -1,30 +1,35 @@
<template name="threads">
{{#unless hasThreads}}
{{#if hasNoThreads}}
<h2 class="thread-empty">{{_ "No_Threads"}}</h2>
{{/unless}}
{{/if}}
{{# with messageContext}}
<div class="thread-list js-scroll-threads">
<ul class="thread">
{{#each thread in threads}}
{{> nrr nrrargs 'message'
groupable=false
msg=thread
room=room
subscription=subscription
customClass="thread-message"
settings=settings
templatePrefix='threads-'
u=u
noDate=true
context="threads"
timeAgo=true
}}
{{/each}}
</ul>
</div>
<div class="rc-user-info-container flex-nav animated{{#unless message}} animated-hidden{{/unless}}">
{{#if message}} {{> thread mainMessage=message room=room subscription=subscription settings=settings close=close}} {{/if}}
{{#unless doDotLoadThreads}}
<div class="thread-list js-scroll-threads">
<ul class="thread">
{{#each thread in threads}}
{{> nrr nrrargs 'message'
groupable=false
msg=thread
room=room
hideRoles=true
subscription=subscription
customClass="thread-message"
settings=settings
templatePrefix='threads-'
u=u
noDate=true
context="threads"
timeAgo=true
}}
{{/each}}
</ul>
</div>
{{/unless}}
{{#if message}}
<div class="rc-user-info-container flex-nav">
{{> thread mainMessage=message room=room subscription=subscription settings=settings close=close}}
</div>
{{/if}}
{{/with}}
{{#if isLoading}}
<div class="load-more">

@ -35,10 +35,13 @@ Template.threads.events({
});
Template.threads.helpers({
doDotLoadThreads() {
return Template.instance().state.get('close');
},
close() {
const instance = Template.instance();
const { tabBar } = instance.data;
return () => (instance.close ? tabBar.close() : instance.state.set('mid', null));
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');
@ -46,8 +49,8 @@ Template.threads.helpers({
isLoading() {
return Template.instance().state.get('loading');
},
hasThreads() {
return Template.instance().Threads.find({ rid: Template.instance().state.get('rid') }, { sort }).count();
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') });
@ -56,17 +59,19 @@ Template.threads.helpers({
});
Template.threads.onCreated(async function() {
this.Threads = new Mongo.Collection(null);
const { rid, mid, msg } = this.data;
this.state = new ReactiveDict({
rid: this.data.rid,
rid,
close: !!mid,
loading: true,
mid,
thread: msg,
});
this.Threads = new Mongo.Collection(null);
this.incLimit = () => {
if (this.state.get('loading')) {
return;
}
const { rid, limit } = Tracker.nonreactive(() => this.state.all());
const count = this.Threads.find({ rid }).count();
@ -80,13 +85,13 @@ Template.threads.onCreated(async function() {
};
this.loadMore = _.debounce(async () => {
if (this.state.get('loading')) {
const { rid, limit } = Tracker.nonreactive(() => this.state.all());
if (this.state.get('loading') === rid) {
return;
}
const { rid, limit } = Tracker.nonreactive(() => this.state.all());
this.state.set('loading', true);
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));
@ -97,9 +102,9 @@ Template.threads.onCreated(async function() {
Tracker.afterFlush(() => {
this.autorun(async () => {
const { rid, mid } = Template.currentData();
this.close = !!mid;
this.state.set({
close: !!mid,
mid,
rid,
});
@ -111,7 +116,6 @@ Template.threads.onCreated(async function() {
this.rid = rid;
this.state.set({
limit: LIST_SIZE,
loading: false,
});
this.loadMore();
});
@ -119,7 +123,7 @@ Template.threads.onCreated(async function() {
this.autorun(() => {
const rid = this.state.get('rid');
this.threadsObserve && this.threadsObserve.stop();
this.threadsObserve = Messages.find({ rid, tcount: { $exists: true } }).observe({
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

@ -14,6 +14,7 @@ import { AutoTranslate } from '../../autotranslate/client';
import { callbacks } from '../../callbacks/client';
import { Markdown } from '../../markdown/client';
import { t, roomTypes, getURL } from '../../utils';
import { messageArgs } from '../../ui-utils/client/lib/messageArgs';
async function renderPdfToCanvas(canvasId, pdfLink) {
const isSafari = /constructor/i.test(window.HTMLElement) ||
@ -90,8 +91,8 @@ Template.message.helpers({
return encodeURI(text);
},
broadcast() {
const { msg, room = {} } = this;
return !msg.private && !msg.t && msg.u._id !== Meteor.userId() && room && room.broadcast;
const { msg, room = {}, u } = this;
return !msg.private && !msg.t && msg.u._id !== u._id && room && room.broadcast;
},
isIgnored() {
const { msg } = this;
@ -145,8 +146,8 @@ Template.message.helpers({
}
},
sequentialClass() {
const { msg } = this;
return msg.groupable !== false && 'sequential';
const { msg, groupable } = this;
return groupable !== false && msg.groupable !== false && 'sequential';
},
avatarFromUsername() {
const { msg } = this;
@ -217,8 +218,8 @@ Template.message.helpers({
}
},
showTranslated() {
const { msg, subscription, settings } = this;
if (settings.AutoTranslate_Enabled && msg.u && msg.u._id !== Meteor.userId() && !MessageTypes.isSystemMessage(msg)) {
const { msg, subscription, settings, u } = this;
if (settings.AutoTranslate_Enabled && msg.u && msg.u._id !== u._id && !MessageTypes.isSystemMessage(msg)) {
const language = AutoTranslate.getLanguage(msg.rid);
const autoTranslate = subscription && subscription.autoTranslate;
return msg.autoTranslateFetching || (!!autoTranslate !== !!msg.autoTranslateShowInverse && msg.translations && msg.translations[language]);
@ -266,8 +267,7 @@ Template.message.helpers({
return true;
},
reactions() {
const { username: myUsername, name: myName } = Meteor.user() || {};
const { msg: { reactions = {} } } = this;
const { msg: { reactions = {} }, u: { username: myUsername, name: myName } } = this;
return Object.entries(reactions)
.map(([emoji, reaction]) => {
@ -473,11 +473,8 @@ const getPreviousSentMessage = (currentNode) => {
};
const setNewDayAndGroup = (currentNode, previousNode, forceDate, period, noDate) => {
const { classList } = currentNode;
// const $nextNode = $(nextNode);
if (previousNode == null) {
classList.remove('sequential');
@ -493,7 +490,6 @@ const setNewDayAndGroup = (currentNode, previousNode, forceDate, period, noDate)
classList.add('new-day');
}
if (previousDataset.tmid !== currentDataset.tmid) {
return classList.remove('sequential');
}
@ -508,15 +504,16 @@ const setNewDayAndGroup = (currentNode, previousNode, forceDate, period, noDate)
};
Template.message.onViewRendered = function(context) {
const [, currentData] = Template.currentData()._arguments;
const { settings, forceDate, noDate, msg } = currentData.hash;
if (msg.tmid && !msg.threadMsg) {
findParentMessage(msg.tmid);
Template.message.onViewRendered = function() {
const { settings, forceDate, noDate, groupable, msg } = messageArgs(Template.currentData());
if (noDate && !groupable) {
return;
}
return this._domrange.onAttached((domRange) => {
if (context.file && context.file.type === 'application/pdf') {
Meteor.defer(() => { renderPdfToCanvas(context.file._id, context.attachments[0].title_link); });
if (msg.file && msg.file.type === 'application/pdf') {
Meteor.defer(() => { renderPdfToCanvas(msg.file._id, msg.attachments[0].title_link); });
}
const currentNode = domRange.lastNode();
const currentDataset = currentNode.dataset;
@ -541,7 +538,7 @@ Template.message.onViewRendered = function(context) {
}
}
} else {
const [el] = $(`#chat-window-${ context.rid }`);
const [el] = $(`#chat-window-${ msg.rid }`);
const view = el && Blaze.getView(el);
const templateInstance = view && view.templateInstance();
if (!templateInstance) {
@ -553,7 +550,5 @@ Template.message.onViewRendered = function(context) {
}
templateInstance.sendToBottomIfNecessary();
}
});
};

@ -513,11 +513,12 @@ Template.room.events({
'click .js-open-thread'() {
const { tabBar } = Template.instance();
const { msg: { rid, _id, tmid } } = messageArgs(this);
const { msg, msg: { rid, _id, tmid } } = messageArgs(this);
const $flexTab = $('.flex-tab-container .flex-tab');
$flexTab.attr('template', 'thread');
tabBar.setData({
msg,
rid,
mid: tmid || _id,
label: 'Threads',

Loading…
Cancel
Save