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/packages/rocketchat-livechat/.app/client/lib/fromApp/RoomHistoryManager.js

237 lines
6.9 KiB

/* globals readMessage UserRoles RoomRoles*/
import { Meteor } from 'meteor/meteor';
import { ReactiveVar } from 'meteor/reactive-var';
import { Blaze } from 'meteor/blaze';
import visitor from '../../../imports/client/visitor';
import _ from 'underscore';
export const RoomHistoryManager = new class {
constructor() {
this.defaultLimit = 50;
this.histories = {};
}
getRoom(rid) {
if ((this.histories[rid] == null)) {
this.histories[rid] = {
hasMore: new ReactiveVar(true),
hasMoreNext: new ReactiveVar(false),
isLoading: new ReactiveVar(false),
unreadNotLoaded: new ReactiveVar(0),
firstUnread: new ReactiveVar,
loaded: undefined,
};
}
return this.histories[rid];
}
getMore(rid, limit) {
if (limit == null) { limit = this.defaultLimit; }
const room = this.getRoom(rid);
if (room.hasMore.curValue !== true) {
return;
}
room.isLoading.set(true);
// $('.messages-box .wrapper').data('previous-height', $('.messages-box .wrapper').get(0)?.scrollHeight - $('.messages-box .wrapper').get(0)?.scrollTop)
// ScrollListener.setLoader true
const lastMessage = ChatMessage.findOne({ rid }, { fields: { ts: 1 }, sort: { ts: 1 } });
// lastMessage ?= ChatMessage.findOne({rid: rid}, {sort: {ts: 1}})
let ts;
if (lastMessage) {
ts = lastMessage.ts;
} else {
ts = new Date();
}
Meteor.call('livechat:loadHistory', { token: visitor.getToken(), rid, ts, limit }, (err, result) => {
if (err) {
return;
}
if (result && result.messages) {
result.messages.forEach((item) => {
if (item.t !== 'command') {
ChatMessage.upsert({ _id: item._id }, item);
}
});
room.isLoading.set(false);
room.loaded += result.messages.length;
if (result.messages.length < limit) {
room.hasMore.set(false);
}
}
});
}
getMoreNext(rid, limit) {
if (limit == null) { limit = this.defaultLimit; }
const room = this.getRoom(rid);
if (room.hasMoreNext.curValue !== true) {
return;
}
const instance = Blaze.getView($('.messages-box .wrapper')[0]).templateInstance();
instance.atBottom = false;
room.isLoading.set(true);
const lastMessage = ChatMessage.findOne({ rid }, { sort: { ts: -1 } });
let typeName = undefined;
const subscription = ChatSubscription.findOne({ rid });
if (subscription != null) {
// const { ls } = subscription;
typeName = subscription.t + subscription.name;
} else {
const curRoomDoc = ChatRoom.findOne({ _id: rid });
typeName = (curRoomDoc != null ? curRoomDoc.t : undefined) + (curRoomDoc != null ? curRoomDoc.name : undefined);
}
const { ts } = lastMessage;
if (ts) {
return Meteor.call('loadNextMessages', rid, ts, limit, function(err, result) {
for (const item of Array.from((result != null ? result.messages : undefined) || [])) {
if (item.t !== 'command') {
const roles = [
(item.u && item.u._id && UserRoles.findOne(item.u._id, { fields: { roles: 1 } })) || {},
(item.u && item.u._id && RoomRoles.findOne({ rid: item.rid, 'u._id': item.u._id })) || {},
].map((e) => e.roles);
item.roles = _.union.apply(_.union, roles);
ChatMessage.upsert({ _id: item._id }, item);
}
}
Meteor.defer(() => RoomManager.updateMentionsMarksOfRoom(typeName));
room.isLoading.set(false);
if (room.loaded == null) { room.loaded = 0; }
room.loaded += result.messages.length;
if (result.messages.length < limit) {
room.hasMoreNext.set(false);
}
});
}
}
getSurroundingMessages(message, limit) {
if (limit == null) { limit = this.defaultLimit; }
if (!(message != null ? message.rid : undefined)) {
return;
}
const instance = Blaze.getView($('.messages-box .wrapper')[0]).templateInstance();
if (ChatMessage.findOne(message._id)) {
const wrapper = $('.messages-box .wrapper');
const msgElement = $(`#${ message._id }`, wrapper);
const pos = (wrapper.scrollTop() + msgElement.offset().top) - (wrapper.height() / 2);
wrapper.animate({
scrollTop: pos,
}, 500);
msgElement.addClass('highlight');
setTimeout(function() {
const messages = wrapper[0];
return instance.atBottom = messages.scrollTop >= (messages.scrollHeight - messages.clientHeight);
});
return setTimeout(() => msgElement.removeClass('highlight'), 500);
} else {
const room = this.getRoom(message.rid);
room.isLoading.set(true);
ChatMessage.remove({ rid: message.rid });
let typeName = undefined;
const subscription = ChatSubscription.findOne({ rid: message.rid });
if (subscription) {
// const { ls } = subscription;
typeName = subscription.t + subscription.name;
} else {
const curRoomDoc = ChatRoom.findOne({ _id: message.rid });
typeName = (curRoomDoc != null ? curRoomDoc.t : undefined) + (curRoomDoc != null ? curRoomDoc.name : undefined);
}
return Meteor.call('loadSurroundingMessages', message, limit, function(err, result) {
for (const item of Array.from((result != null ? result.messages : undefined) || [])) {
if (item.t !== 'command') {
const roles = [
(item.u && item.u._id && UserRoles.findOne(item.u._id, { fields: { roles: 1 } })) || {},
(item.u && item.u._id && RoomRoles.findOne({ rid: item.rid, 'u._id': item.u._id })) || {},
].map((e) => e.roles);
item.roles = _.union.apply(_.union, roles);
ChatMessage.upsert({ _id: item._id }, item);
}
}
Meteor.defer(function() {
readMessage.refreshUnreadMark(message.rid, true);
RoomManager.updateMentionsMarksOfRoom(typeName);
const wrapper = $('.messages-box .wrapper');
const msgElement = $(`#${ message._id }`, wrapper);
const pos = (wrapper.scrollTop() + msgElement.offset().top) - (wrapper.height() / 2);
wrapper.animate({
scrollTop: pos,
}, 500);
msgElement.addClass('highlight');
setTimeout(function() {
room.isLoading.set(false);
const messages = wrapper[0];
instance.atBottom = !result.moreAfter && (messages.scrollTop >= (messages.scrollHeight - messages.clientHeight));
return 500;
});
return setTimeout(() => msgElement.removeClass('highlight'), 500);
});
if (room.loaded == null) { room.loaded = 0; }
room.loaded += result.messages.length;
room.hasMore.set(result.moreBefore);
return room.hasMoreNext.set(result.moreAfter);
});
}
}
hasMore(rid) {
const room = this.getRoom(rid);
return room.hasMore.get();
}
hasMoreNext(rid) {
const room = this.getRoom(rid);
return room.hasMoreNext.get();
}
getMoreIfIsEmpty(rid) {
const room = this.getRoom(rid);
if (room.loaded === undefined) {
return this.getMore(rid);
}
}
isLoading(rid) {
const room = this.getRoom(rid);
return room.isLoading.get();
}
clear(rid) {
ChatMessage.remove({ rid });
if (this.histories[rid] != null) {
this.histories[rid].hasMore.set(true);
this.histories[rid].isLoading.set(false);
return this.histories[rid].loaded = undefined;
}
}
};
this.RoomHistoryManager = RoomHistoryManager;