From 5ae4f7fd7be1c8f4eb92f7c198203e02b54f7e84 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 22 Feb 2018 16:18:11 -0300 Subject: [PATCH 01/17] test for improve performance --- client/routes/router.js | 2 +- .../client/lib/cachedCollection.js | 21 +++--- .../rocketchat-lib/lib/getUserPreference.js | 4 +- packages/rocketchat-ui-master/client/main.js | 2 +- .../client/chatRoomItem.js | 58 +++++++++------ .../rocketchat-ui-sidenav/client/roomList.js | 55 ++++++-------- .../rocketchat-ui-sidenav/client/sideNav.js | 4 +- .../client/sidebarHeader.js | 22 +++--- .../client/sidebarItem.html | 15 ++-- .../client/sidebarItem.js | 74 ++++++++++--------- .../rocketchat-ui-sidenav/client/sortlist.js | 2 +- 11 files changed, 137 insertions(+), 122 deletions(-) diff --git a/client/routes/router.js b/client/routes/router.js index d75f07595f0bf..56e01b2fab9dd 100644 --- a/client/routes/router.js +++ b/client/routes/router.js @@ -24,7 +24,7 @@ FlowRouter.route('/', { if (!Meteor.userId()) { return FlowRouter.go('home'); } - + // gazzo sidenav line 65; Tracker.autorun(function(c) { if (FlowRouter.subsReady() === true) { Meteor.defer(function() { diff --git a/packages/rocketchat-lib/client/lib/cachedCollection.js b/packages/rocketchat-lib/client/lib/cachedCollection.js index 08ed0c357dd41..fb33922a4fe22 100644 --- a/packages/rocketchat-lib/client/lib/cachedCollection.js +++ b/packages/rocketchat-lib/client/lib/cachedCollection.js @@ -86,6 +86,13 @@ class CachedCollectionManager { RocketChat.CachedCollectionManager = new CachedCollectionManager; +const debug = false; + +const nullLog = function() {}; + +const log = function(...args) { + console.log(`CachedCollection ${ this.name } =>`, ...args); +}; class CachedCollection { constructor({ @@ -98,7 +105,6 @@ class CachedCollection { userRelated = true, useSync = true, useCache = true, - debug = false, version = 6, maxCacheTime = 60*60*24*30, onSyncData = (/* action, record */) => {} @@ -119,7 +125,7 @@ class CachedCollection { this.updatedAt = new Date(0); this.maxCacheTime = maxCacheTime; this.onSyncData = onSyncData; - + this.log = debug ? log : nullLog; RocketChat.CachedCollectionManager.register(this); if (userRelated === true) { @@ -137,12 +143,6 @@ class CachedCollection { } } - log(...args) { - if (this.debug === true) { - console.log(`CachedCollection ${ this.name } =>`, ...args); - } - } - countQueries() { this.log(`${ Object.keys(this.collection._collection.queries).length } queries`); } @@ -184,6 +184,7 @@ class CachedCollection { if (data && data.records && data.records.length > 0) { this.log(`${ data.records.length } records loaded from cache`); data.records.forEach((record) => { + RocketChat.callbacks.run(`cachedCollection-loadFromCache-${ this.name }`, record); record.__cache__ = true; this.collection.upsert({ _id: record._id }, _.omit(record, '_id')); @@ -207,6 +208,7 @@ class CachedCollection { this.log(`${ data.length } records loaded from server`); data.forEach((record) => { delete record.$loki; + RocketChat.callbacks.run(`cachedCollection-loadFromServer-${ this.name }`, record, 'changed'); this.collection.upsert({ _id: record._id }, _.omit(record, '_id')); this.onSyncData('changed', record); @@ -269,7 +271,7 @@ class CachedCollection { for (const record of changes) { delete record.$loki; - + RocketChat.callbacks.run(`cachedCollection-sync-${ this.name }`, record, record._deletedAt? 'removed' : 'changed'); if (record._deletedAt) { this.collection.remove({ _id: record._id }); @@ -329,6 +331,7 @@ class CachedCollection { setupListener(eventType, eventName) { RocketChat.Notifications[eventType || this.eventType](eventName || this.eventName, (t, record) => { this.log('record received', t, record); + RocketChat.callbacks.run(`cachedCollection-received-${ this.name }`, record, t); if (t === 'removed') { this.collection.remove(record._id); RoomManager.close(record.t+record.name); diff --git a/packages/rocketchat-lib/lib/getUserPreference.js b/packages/rocketchat-lib/lib/getUserPreference.js index 1d516996784de..3e07d76bf5b88 100644 --- a/packages/rocketchat-lib/lib/getUserPreference.js +++ b/packages/rocketchat-lib/lib/getUserPreference.js @@ -4,7 +4,9 @@ */ RocketChat.getUserPreference = function(user, key, defaultValue=undefined) { let preference; - + if (typeof user === typeof '') { + user = RocketChat.models.Users.findOne(user, {fields: {[`settings.preferences.${ key }`]: 1}}); + } if (user && user.settings && user.settings.preferences && user.settings.preferences.hasOwnProperty(key)) { preference = user.settings.preferences[key]; diff --git a/packages/rocketchat-ui-master/client/main.js b/packages/rocketchat-ui-master/client/main.js index 74a41c42339d0..17b1d48713d60 100644 --- a/packages/rocketchat-ui-master/client/main.js +++ b/packages/rocketchat-ui-master/client/main.js @@ -190,7 +190,7 @@ Template.main.onRendered(function() { }, 100); }); return Tracker.autorun(function() { - const user = Meteor.user(); + const user = Meteor.userId(); if (RocketChat.getUserPreference(user, 'hideUsernames')) { $(document.body).on('mouseleave', 'button.thumb', function() { return RocketChat.tooltip.hide(); diff --git a/packages/rocketchat-ui-sidenav/client/chatRoomItem.js b/packages/rocketchat-ui-sidenav/client/chatRoomItem.js index 50f22bdc25e24..a75ceea80ad78 100644 --- a/packages/rocketchat-ui-sidenav/client/chatRoomItem.js +++ b/packages/rocketchat-ui-sidenav/client/chatRoomItem.js @@ -1,25 +1,27 @@ Template.chatRoomItem.helpers({ roomData() { + console.time(this.rid); + const hasFocus = document.hasFocus(); let {name} = this; - const realNameForDirectMessages = RocketChat.settings.get('UI_Use_Real_Name') && this.t === 'd'; - const realNameForChannel = RocketChat.settings.get('UI_Allow_room_names_with_special_chars') && this.t !== 'd'; - if ((realNameForDirectMessages || realNameForChannel) && this.fname) { - name = this.fname; + if (this.fname) { + const realNameForDirectMessages = this.t === 'd' && RocketChat.settings.get('UI_Use_Real_Name'); + const realNameForChannel = this.t !== 'd' && RocketChat.settings.get('UI_Allow_room_names_with_special_chars'); + if (realNameForDirectMessages || realNameForChannel) { + name = this.fname; + } } - let unread = false; - if (((FlowRouter.getParam('_id') !== this.rid) || !document.hasFocus()) && (this.unread > 0)) { - unread = this.unread; - } + const openedRomm = Tracker.nonreactive(() => Session.get('openedRoom')); + const unread = this.unread > 0 ? this.unread : false; + // if (this.unread > 0 && (!hasFocus || openedRomm !== this.rid)) { + // unread = this.unread; + // } - let active = false; - if ([this.rid, this._id].find(id => id === Session.get('openedRoom'))) { - active = true; - } + const active = [this.rid, this._id].includes(id => id === openedRomm); const archivedClass = this.archived ? 'archived' : false; - this.alert = !this.hideUnreadStatus && (FlowRouter.getParam('_id') !== this.rid || !document.hasFocus()) && this.alert; + this.alert = !this.hideUnreadStatus && this.alert; //&& (!hasFocus || FlowRouter.getParam('_id') !== this.rid); const icon = RocketChat.roomTypes.getIcon(this.t); const avatar = !icon; @@ -32,20 +34,30 @@ Template.chatRoomItem.helpers({ route: RocketChat.roomTypes.getRouteLink(this.t, this), name, unread, - active, + // active, archivedClass, - statusClass: this.t === 'd' ? Session.get(`user_${ this.name }_status`) || 'offline' : this.t === 'l' ? RocketChat.roomTypes.getUserStatus(this.t, this.rid) || 'offline' : false + status: this.t === 'd' || this.t == 'l' }; - if (RocketChat.settings.get('Store_Last_Message')) { - if (this.lastMessage) { - roomData.lastMessage = this.lastMessage; - } else { - const room = RocketChat.models.Rooms.findOne(this.rid || this._id, { fields: { lastMessage: 1 } }); - roomData.lastMessage = room && room.lastMessage || { msg: t('No_messages_yet') }; - } + if (!this.lastMessage && RocketChat.settings.get('Store_Last_Message')) { + const room = RocketChat.models.Rooms.findOne(this.rid || this._id, { fields: { lastMessage: 1 } }); + roomData.lastMessage = room && room.lastMessage || { msg: t('No_messages_yet') }; } - + console.timeEnd(this.rid); return roomData; } }); + +RocketChat.callbacks.add('enter-room', (sub) => { + const items = $('.rooms-list .sidebar-item'); + items.filter('.sidebar-item--active').removeClass('sidebar-item--active'); + items.filter(`[data-id=${ sub.rid }]`).addClass('sidebar-item--active'); + return sub; +}); + +Template.sidebarItemStatus.helpers({ + statusClass() { + const instance = Template.instance(); + return instance.data.t === 'd' ? Session.get(`user_${ instance.data.name }_status`) || 'offline' : instance.data.t === 'l' ? RocketChat.roomTypes.getUserStatus('l', instance.data.rid) || 'offline' : false; + } +}); diff --git a/packages/rocketchat-ui-sidenav/client/roomList.js b/packages/rocketchat-ui-sidenav/client/roomList.js index 1887999a5b485..59183dbda15bb 100644 --- a/packages/rocketchat-ui-sidenav/client/roomList.js +++ b/packages/rocketchat-ui-sidenav/client/roomList.js @@ -2,7 +2,7 @@ import _ from 'underscore'; import { UiTextContext } from 'meteor/rocketchat:lib'; - +const counter = 0; Template.roomList.helpers({ rooms() { /* @@ -12,11 +12,10 @@ Template.roomList.helpers({ show favorites show unread */ - if (this.anonymous) { return RocketChat.models.Rooms.find({t: 'c'}, {sort: {name: 1}}); } - const user = Meteor.user(); + const user = Meteor.userId(); const sortBy = RocketChat.getUserPreference(user, 'sidebarSortby') || 'alphabetical'; const query = { open: true @@ -25,7 +24,7 @@ Template.roomList.helpers({ const sort = {}; if (sortBy === 'activity') { - sort.t = 1; + sort.lm = -1; } else { // alphabetical sort[this.identifier === 'd' && RocketChat.settings.get('UI_Use_Real_Name') ? 'fname' : 'name'] = /descending/.test(sortBy) ? -1 : 1; } @@ -33,6 +32,7 @@ Template.roomList.helpers({ if (this.identifier === 'unread') { query.alert = true; query.hideUnreadStatus = {$ne: true}; + return ChatSubscription.find(query, {sort}); } @@ -69,29 +69,6 @@ Template.roomList.helpers({ query.f = {$ne: favoritesEnabled}; } } - - if (sortBy === 'activity') { - const list = ChatSubscription.find(query, {sort: {rid : 1}}).fetch(); - const ids = list.map(sub => sub.rid); - const rooms = RocketChat.models.Rooms.find({ - _id: { $in : ids} - }, - { - sort : { - _id: 1 - }, - fields: {_updatedAt: 1} - }).fetch(); - - - return _.sortBy(list.map((sub, i) => { - const lm = rooms[i]._updatedAt; - return { - lm: lm && lm.toISOString(), - ...sub - }; - }), 'lm').reverse(); - } return ChatSubscription.find(query, {sort}); }, @@ -122,13 +99,29 @@ Template.roomList.helpers({ }, showRoomCounter() { - return RocketChat.getUserPreference(Meteor.user(), 'roomCounterSidebar'); + return RocketChat.getUserPreference(Meteor.userId(), 'roomCounterSidebar'); } }); -// Template.roomList.onRendered(function() { -// $(this.firstNode.parentElement).perfectScrollbar(); -// }); +RocketChat.Notifications['onUser']('rooms-changed', (t, room) => { + console.log('record received', t, room); + const $set = {lastMessage : room.lastMessage, lm: room._updatedAt}; + RocketChat.models.Subscriptions.update({ rid: room._id }, {$set}); +}); + +const mergeSubRoom = (record, t) => { + const room = Tracker.nonreactive(() => RocketChat.models.Rooms.findOne({ _id: record.rid })); + if (!room) { + return record; + } + record.lastMessage = room.lastMessage; + record.lm = room._updatedAt; + return record; +}; + +RocketChat.callbacks.add('cachedCollection-received-subscriptions', mergeSubRoom); +RocketChat.callbacks.add('cachedCollection-sync-subscriptions', mergeSubRoom); +RocketChat.callbacks.add('cachedCollection-loadFromServer-subscriptions', mergeSubRoom); Template.roomList.events({ 'click .more'(e, t) { diff --git a/packages/rocketchat-ui-sidenav/client/sideNav.js b/packages/rocketchat-ui-sidenav/client/sideNav.js index f360e188322ec..9192166299fb9 100644 --- a/packages/rocketchat-ui-sidenav/client/sideNav.js +++ b/packages/rocketchat-ui-sidenav/client/sideNav.js @@ -32,7 +32,7 @@ Template.sideNav.helpers({ }, sidebarViewMode() { - const viewMode = RocketChat.getUserPreference(Meteor.user(), 'sidebarViewMode'); + const viewMode = RocketChat.getUserPreference(Meteor.userId(), 'sidebarViewMode'); return viewMode ? viewMode : 'condensed'; }, @@ -62,7 +62,7 @@ Template.sideNav.events({ Template.sideNav.onRendered(function() { SideNav.init(); menu.init(); - + // GAZZO router line 27; const first_channel_login = RocketChat.settings.get('First_Channel_After_Login'); const room = RocketChat.roomTypes.findRoom('c', first_channel_login, Meteor.userId()); if (room !== undefined && room._id !== '') { diff --git a/packages/rocketchat-ui-sidenav/client/sidebarHeader.js b/packages/rocketchat-ui-sidenav/client/sidebarHeader.js index d633e6403a51f..6b627361fbc89 100644 --- a/packages/rocketchat-ui-sidenav/client/sidebarHeader.js +++ b/packages/rocketchat-ui-sidenav/client/sidebarHeader.js @@ -51,7 +51,7 @@ const toolbarButtons = (user) => { }, { name: t('View_mode'), - icon: () => RocketChat.getUserPreference(user, 'sidebarViewMode') ? viewModeIcon[RocketChat.getUserPreference(user, 'sidebarViewMode')] : viewModeIcon.condensed, + icon: () => viewModeIcon[RocketChat.getUserPreference(user, 'sidebarViewMode') || 'condensed'], action: (e) => { const hideAvatarSetting = RocketChat.getUserPreference(user, 'sidebarHideAvatar'); const config = { @@ -153,7 +153,7 @@ const toolbarButtons = (user) => { { name: t('Options'), icon: 'menu', - condition: () => !(Meteor.userId() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')), + condition: () => !(user == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')), action: () => { let adminOption; if (RocketChat.authz.hasAtLeastOnePermission(['view-statistics', 'view-room-administration', 'view-user-administration', 'view-privileged-setting' ]) || (RocketChat.AdminBox.getOptions().length > 0)) { @@ -286,24 +286,20 @@ const toolbarButtons = (user) => { }; Template.sidebarHeader.helpers({ myUserInfo() { - if (Meteor.user() == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')) { + const id = Meteor.userId(); + + if (id == null && RocketChat.settings.get('Accounts_AllowAnonymousRead')) { return { username: 'anonymous', status: 'online' }; } - - const user = Meteor.user() || {}; - const { username } = user; - const userStatus = Session.get(`user_${ username }_status`); - - return { - username, - status: userStatus - }; + return id && Meteor.users.findOne(id, {fields: { + username: 1, status: 1 + }}); }, toolbarButtons() { - return toolbarButtons(Meteor.user()).filter(button => !button.condition || button.condition()); + return toolbarButtons(Meteor.userId()).filter(button => !button.condition || button.condition()); } }); diff --git a/packages/rocketchat-ui-sidenav/client/sidebarItem.html b/packages/rocketchat-ui-sidenav/client/sidebarItem.html index 6c975328cfb75..42227245307e1 100644 --- a/packages/rocketchat-ui-sidenav/client/sidebarItem.html +++ b/packages/rocketchat-ui-sidenav/client/sidebarItem.html @@ -1,5 +1,8 @@ + diff --git a/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.html b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.html index 04bb8832d1ff9..119d0f7859dad 100644 --- a/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.html +++ b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.html @@ -32,6 +32,18 @@

{{_ "Webhooks"}}

{{_ "Send_request_on_offline_messages"}} +
+ +
+
+ +
diff --git a/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.js b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.js index 2a56023283642..cc373fb2f4427 100644 --- a/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.js +++ b/packages/rocketchat-livechat/client/views/app/integrations/livechatIntegrationWebhook.js @@ -22,6 +22,14 @@ Template.livechatIntegrationWebhook.helpers({ sendOnOfflineChecked() { const setting = LivechatIntegration.findOne('Livechat_webhook_on_offline_msg'); return setting && setting.value; + }, + sendOnVisitorMessageChecked() { + const setting = LivechatIntegration.findOne('Livechat_webhook_on_visitor_message'); + return setting && setting.value; + }, + sendOnAgentMessageChecked() { + const setting = LivechatIntegration.findOne('Livechat_webhook_on_agent_message'); + return setting && setting.value; } }); @@ -62,11 +70,15 @@ Template.livechatIntegrationWebhook.events({ const secretToken = LivechatIntegration.findOne('Livechat_secret_token'); const webhookOnClose = LivechatIntegration.findOne('Livechat_webhook_on_close'); const webhookOnOfflineMsg = LivechatIntegration.findOne('Livechat_webhook_on_offline_msg'); + const webhookOnVisitorMessage = LivechatIntegration.findOne('Livechat_webhook_on_visitor_message'); + const webhookOnAgentMessage = LivechatIntegration.findOne('Livechat_webhook_on_agent_message'); instance.$('#webhookUrl').val(webhookUrl && webhookUrl.value); instance.$('#secretToken').val(secretToken && secretToken.value); instance.$('#sendOnClose').get(0).checked = webhookOnClose && webhookOnClose.value; instance.$('#sendOnOffline').get(0).checked = webhookOnOfflineMsg && webhookOnOfflineMsg.value; + instance.$('#sendOnVisitorMessage').get(0).checked = webhookOnVisitorMessage && webhookOnVisitorMessage.value; + instance.$('#sendOnAgentMessage').get(0).checked = webhookOnAgentMessage && webhookOnAgentMessage.value; instance.disableTest.set(!webhookUrl || _.isEmpty(webhookUrl.value)); }, @@ -77,7 +89,9 @@ Template.livechatIntegrationWebhook.events({ 'Livechat_webhookUrl': s.trim(instance.$('#webhookUrl').val()), 'Livechat_secret_token': s.trim(instance.$('#secretToken').val()), 'Livechat_webhook_on_close': instance.$('#sendOnClose').get(0).checked, - 'Livechat_webhook_on_offline_msg': instance.$('#sendOnOffline').get(0).checked + 'Livechat_webhook_on_offline_msg': instance.$('#sendOnOffline').get(0).checked, + 'Livechat_webhook_on_visitor_message': instance.$('#sendOnVisitorMessage').get(0).checked, + 'Livechat_webhook_on_agent_message': instance.$('#sendOnAgentMessage').get(0).checked }; Meteor.call('livechat:saveIntegration', settings, (err) => { if (err) { diff --git a/packages/rocketchat-livechat/client/views/app/livechatIntegrations.html b/packages/rocketchat-livechat/client/views/app/livechatIntegrations.html index 61670e4cad509..3fdc69550387b 100644 --- a/packages/rocketchat-livechat/client/views/app/livechatIntegrations.html +++ b/packages/rocketchat-livechat/client/views/app/livechatIntegrations.html @@ -32,6 +32,18 @@

{{_ "Webhooks"}}

{{_ "Send_request_on_offline_messages"}}
+
+ +
+
+ +
diff --git a/packages/rocketchat-livechat/config.js b/packages/rocketchat-livechat/config.js index 3a7815a4d6e86..c69df7adcea93 100644 --- a/packages/rocketchat-livechat/config.js +++ b/packages/rocketchat-livechat/config.js @@ -131,6 +131,20 @@ Meteor.startup(function() { i18nLabel: 'Send_request_on_offline_messages' }); + RocketChat.settings.add('Livechat_webhook_on_visitor_message', false, { + type: 'boolean', + group: 'Livechat', + section: 'CRM_Integration', + i18nLabel: 'Send_request_on_visitor_message' + }); + + RocketChat.settings.add('Livechat_webhook_on_agent_message', false, { + type: 'boolean', + group: 'Livechat', + section: 'CRM_Integration', + i18nLabel: 'Send_request_on_agent_message' + }); + RocketChat.settings.add('Livechat_webhook_on_capture', false, { type: 'boolean', group: 'Livechat', diff --git a/packages/rocketchat-livechat/server/hooks/sendToCRM.js b/packages/rocketchat-livechat/server/hooks/sendToCRM.js index 8ae0073ff27bf..46e48dcc70fe7 100644 --- a/packages/rocketchat-livechat/server/hooks/sendToCRM.js +++ b/packages/rocketchat-livechat/server/hooks/sendToCRM.js @@ -5,15 +5,24 @@ function sendToCRM(type, room, includeMessages = true) { postData.messages = []; - if (includeMessages) { - RocketChat.models.Messages.findVisibleByRoomId(room._id, { sort: { ts: 1 } }).forEach((message) => { + let messages; + if (typeof includeMessages === 'boolean' && includeMessages) { + messages = RocketChat.models.Messages.findVisibleByRoomId(room._id, { sort: { ts: 1 } }); + } else if (includeMessages instanceof Array) { + messages = includeMessages; + } + + if (messages) { + messages.forEach((message) => { if (message.t) { return; } const msg = { + _id: message._id, username: message.u.username, msg: message.msg, - ts: message.ts + ts: message.ts, + editedAt: message.editedAt }; if (message.u.username !== postData.visitor.username) { @@ -49,6 +58,31 @@ RocketChat.callbacks.add('livechat.saveInfo', (room) => { return sendToCRM('LivechatEdit', room); }, RocketChat.callbacks.priority.MEDIUM, 'livechat-send-crm-save-info'); +RocketChat.callbacks.add('afterSaveMessage', function(message, room) { + // only call webhook if it is a livechat room + if (room.t !== 'l' || room.v == null || room.v.token == null) { + return message; + } + + // if the message has a token, it was sent from the visitor + // if not, it was sent from the agent + if (message.token) { + if (!RocketChat.settings.get('Livechat_webhook_on_visitor_message')) { + return message; + } + } else if (!RocketChat.settings.get('Livechat_webhook_on_agent_message')) { + return message; + } + + // if the message has a type means it is a special message (like the closing comment), so skips + if (message.t) { + return message; + } + + sendToCRM('Message', room, [message]); + return message; +}, RocketChat.callbacks.priority.MEDIUM, 'livechat-send-crm-message'); + RocketChat.callbacks.add('livechat.leadCapture', (room) => { if (!RocketChat.settings.get('Livechat_webhook_on_capture')) { return room; diff --git a/packages/rocketchat-livechat/server/lib/Livechat.js b/packages/rocketchat-livechat/server/lib/Livechat.js index 99079cb7f6b9f..b614a7096bba4 100644 --- a/packages/rocketchat-livechat/server/lib/Livechat.js +++ b/packages/rocketchat-livechat/server/lib/Livechat.js @@ -415,6 +415,7 @@ RocketChat.Livechat = { customFields: room.livechatData, visitor: { _id: visitor._id, + token: visitor.token, name: visitor.name, username: visitor.username, email: null, diff --git a/packages/rocketchat-livechat/server/methods/saveIntegration.js b/packages/rocketchat-livechat/server/methods/saveIntegration.js index f839f8adbe65e..023d4ce95c1e6 100644 --- a/packages/rocketchat-livechat/server/methods/saveIntegration.js +++ b/packages/rocketchat-livechat/server/methods/saveIntegration.js @@ -22,6 +22,14 @@ Meteor.methods({ RocketChat.settings.updateById('Livechat_webhook_on_offline_msg', !!values['Livechat_webhook_on_offline_msg']); } + if (typeof values['Livechat_webhook_on_visitor_message'] !== 'undefined') { + RocketChat.settings.updateById('Livechat_webhook_on_visitor_message', !!values['Livechat_webhook_on_visitor_message']); + } + + if (typeof values['Livechat_webhook_on_agent_message'] !== 'undefined') { + RocketChat.settings.updateById('Livechat_webhook_on_agent_message', !!values['Livechat_webhook_on_agent_message']); + } + return; } }); diff --git a/packages/rocketchat-livechat/server/publications/livechatIntegration.js b/packages/rocketchat-livechat/server/publications/livechatIntegration.js index 656ea19712d45..455c5388c715e 100644 --- a/packages/rocketchat-livechat/server/publications/livechatIntegration.js +++ b/packages/rocketchat-livechat/server/publications/livechatIntegration.js @@ -9,7 +9,7 @@ Meteor.publish('livechat:integration', function() { const self = this; - const handle = RocketChat.models.Settings.findByIds(['Livechat_webhookUrl', 'Livechat_secret_token', 'Livechat_webhook_on_close', 'Livechat_webhook_on_offline_msg']).observeChanges({ + const handle = RocketChat.models.Settings.findByIds(['Livechat_webhookUrl', 'Livechat_secret_token', 'Livechat_webhook_on_close', 'Livechat_webhook_on_offline_msg', 'Livechat_webhook_on_visitor_message', 'Livechat_webhook_on_agent_message']).observeChanges({ added(id, fields) { self.added('livechatIntegration', id, fields); }, diff --git a/packages/rocketchat-message-attachments/client/messageAttachment.js b/packages/rocketchat-message-attachments/client/messageAttachment.js index 8da6606bca341..d0df4d8f3b5f2 100644 --- a/packages/rocketchat-message-attachments/client/messageAttachment.js +++ b/packages/rocketchat-message-attachments/client/messageAttachment.js @@ -22,7 +22,7 @@ const fixCordova = function(url) { } else if (navigator.userAgent.indexOf('Electron') > -1) { return __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url; } else { - return Meteor.absoluteUrl().replace(/\/$/, '') + __meteor_runtime_config__.ROOT_URL_PATH_PREFIX + url; + return Meteor.absoluteUrl().replace(/\/$/, '') + url; } }; /*globals renderMessageBody*/ diff --git a/packages/rocketchat-reactions/client/methods/setReaction.js b/packages/rocketchat-reactions/client/methods/setReaction.js index 59d05ae71dc7e..ec1188f5e4017 100644 --- a/packages/rocketchat-reactions/client/methods/setReaction.js +++ b/packages/rocketchat-reactions/client/methods/setReaction.js @@ -17,6 +17,8 @@ Meteor.methods({ return false; } else if (message.private) { return false; + } else if (!RocketChat.emoji.list[reaction] && RocketChat.models.EmojiCustom.findByNameOrAlias(reaction).count() === 0) { + return false; } if (message.reactions && message.reactions[reaction] && message.reactions[reaction].usernames.indexOf(user.username) !== -1) { diff --git a/packages/rocketchat-reactions/setReaction.js b/packages/rocketchat-reactions/setReaction.js index 4027ffcf3bd6c..9d1b5949405b1 100644 --- a/packages/rocketchat-reactions/setReaction.js +++ b/packages/rocketchat-reactions/setReaction.js @@ -19,6 +19,10 @@ Meteor.methods({ throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setReaction' }); } + if (!RocketChat.emoji.list[reaction] && RocketChat.models.EmojiCustom.findByNameOrAlias(reaction).count() === 0) { + throw new Meteor.Error('error-not-allowed', 'Invalid emoji provided.', { method: 'setReaction' }); + } + const user = Meteor.user(); if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1 && !room.reactWhenReadOnly) { diff --git a/packages/rocketchat-theme/client/imports/components/main-content.css b/packages/rocketchat-theme/client/imports/components/main-content.css index 87ba3157fcf22..ede6f5a121f33 100644 --- a/packages/rocketchat-theme/client/imports/components/main-content.css +++ b/packages/rocketchat-theme/client/imports/components/main-content.css @@ -4,6 +4,8 @@ width: 1vw; height: 100%; + + position: relative; } .messages-container .room-icon { diff --git a/packages/rocketchat-theme/client/imports/components/message-box.css b/packages/rocketchat-theme/client/imports/components/message-box.css index 5cb83c9ac6c2e..df01615e11d04 100644 --- a/packages/rocketchat-theme/client/imports/components/message-box.css +++ b/packages/rocketchat-theme/client/imports/components/message-box.css @@ -138,6 +138,26 @@ & .rc-input__icon-svg--plus { transition: transform 0.1s linear; } + + &.cross { + color: red; + } + + &.loading { + cursor: pointer; + display: none; + &.active { + display: flex; + } + } + + &.mic { + display: none; + &.active { + display: flex; + } + } + } &__action-menu { @@ -151,6 +171,33 @@ & [data-small] { display: none; } + + &__audio-recording { + display: none; + position: relative; + z-index: -1; + &.active{ + display: flex; + z-index: 2; + } + } + + &__audio-message{ + &.hidden{ + z-index: -1; + } + } + + &__timer-box{ + display: flex; + width: 50px; + } + + &__timer-dot{ + font-size: 1.5em; + color: #d60000; + line-height: 0.8em; + } } @media (width <= 500px) { diff --git a/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-item.css b/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-item.css index a723aaab68b04..13096bca1c1e6 100644 --- a/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-item.css +++ b/packages/rocketchat-theme/client/imports/components/sidebar/sidebar-item.css @@ -18,22 +18,6 @@ display: none; } -.sidebar--medium .sidebar-item { - height: var(--sidebar-item-height-medium); - - &__picture { - flex: 0 0 var(--sidebar-item-thumb-size-medium); - - width: var(--sidebar-item-thumb-size-medium); - height: var(--sidebar-item-thumb-size-medium); - } - - &__user-thumb { - width: var(--sidebar-item-thumb-size-medium); - height: var(--sidebar-item-thumb-size-medium); - } -} - .sidebar--extended .sidebar-item { height: var(--sidebar-item-height-extended); @@ -64,6 +48,22 @@ } } +.sidebar--medium .sidebar-item { + height: var(--sidebar-item-height-medium); + + &__picture { + flex: 0 0 var(--sidebar-item-thumb-size-medium); + + width: var(--sidebar-item-thumb-size-medium); + height: var(--sidebar-item-thumb-size-medium); + } + + &__user-thumb { + width: var(--sidebar-item-thumb-size-medium); + height: var(--sidebar-item-thumb-size-medium); + } +} + .sidebar-item { position: relative; @@ -192,7 +192,7 @@ &__message { display: flex; overflow: hidden; - flex-direction: row; + flex-direction: row !important; flex: 1; margin: 0 -3px; diff --git a/packages/rocketchat-theme/client/imports/general/base.css b/packages/rocketchat-theme/client/imports/general/base.css index 28a4e73427698..f4a7f3adcdab5 100644 --- a/packages/rocketchat-theme/client/imports/general/base.css +++ b/packages/rocketchat-theme/client/imports/general/base.css @@ -30,6 +30,8 @@ body { font-size: var(--text-small-size); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + + background-color: var(--rc-color-primary) } :focus { @@ -205,3 +207,52 @@ button { .hidden { display: none; } + +.loading-animation { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + + display: flex; + + text-align: center; + align-items: center; + justify-content: center; +} + +.loading-animation > .bounce { + display: inline-block; + + width: 10px; + height: 10px; + margin: 2px; + + animation: loading-bouncedelay 1.4s infinite ease-in-out both; + + border-radius: 100%; + background-color: rgba(255, 255, 255, 0.6); +} + +.loading-animation .bounce1 { + -webkit-animation-delay: -0.32s; + animation-delay: -0.32s; +} + +.loading-animation .bounce2 { + -webkit-animation-delay: -0.16s; + animation-delay: -0.16s; +} + +@keyframes loading-bouncedelay { + 0%, + 80%, + 100% { + transform: scale(0); + } + + 40% { + transform: scale(1); + } +} diff --git a/packages/rocketchat-theme/client/imports/general/base_old.css b/packages/rocketchat-theme/client/imports/general/base_old.css index c6bf0c91c3e4a..50df7449b4c65 100644 --- a/packages/rocketchat-theme/client/imports/general/base_old.css +++ b/packages/rocketchat-theme/client/imports/general/base_old.css @@ -1702,8 +1702,7 @@ white-space: nowrap; text-overflow: ellipsis; - color: white; - background-color: #04436a; + color: var(--rc-color-content); font-size: 1.2em; line-height: 40px; @@ -4558,8 +4557,6 @@ body:not(.is-cordova) { } .rc-old.full-page { - z-index: 101; - display: flex; width: 100%; diff --git a/packages/rocketchat-theme/server/colors.less b/packages/rocketchat-theme/server/colors.less index 89bfaa2391ac1..1f7df2e7b369d 100755 --- a/packages/rocketchat-theme/server/colors.less +++ b/packages/rocketchat-theme/server/colors.less @@ -947,3 +947,7 @@ label.required::after { .range-slider-range::-moz-range-track { background-color: @tertiary-background-color; } + +.announcement { + background-color: @primary-background-color; +} diff --git a/packages/rocketchat-ui-account/client/accountPreferences.html b/packages/rocketchat-ui-account/client/accountPreferences.html index f58cd39c98845..8b493c562a4f7 100644 --- a/packages/rocketchat-ui-account/client/accountPreferences.html +++ b/packages/rocketchat-ui-account/client/accountPreferences.html @@ -202,17 +202,6 @@

{{_ "Messages"}}

{{_ "Enter_Behaviour_Description"}}
-
- -
- -
{{_ "View_mode_info"}}
-
-
diff --git a/packages/rocketchat-ui-account/client/accountPreferences.js b/packages/rocketchat-ui-account/client/accountPreferences.js index 8bc65c6e16c95..4e00e3b262475 100644 --- a/packages/rocketchat-ui-account/client/accountPreferences.js +++ b/packages/rocketchat-ui-account/client/accountPreferences.js @@ -133,9 +133,7 @@ Template.accountPreferences.onCreated(function() { data.saveMobileBandwidth = JSON.parse($('input[name=saveMobileBandwidth]:checked').val()); data.collapseMediaByDefault = JSON.parse($('input[name=collapseMediaByDefault]:checked').val()); data.muteFocusedConversations = JSON.parse($('#muteFocusedConversations').find('input:checked').val()); - data.viewMode = parseInt($('#viewMode').find('select').val()); data.hideUsernames = JSON.parse($('#hideUsernames').find('input:checked').val()); - data.hideRoles = JSON.parse($('#hideRoles').find('input:checked').val()); data.hideFlexTab = JSON.parse($('#hideFlexTab').find('input:checked').val()); data.hideAvatars = JSON.parse($('#hideAvatars').find('input:checked').val()); data.sendOnEnter = $('#sendOnEnter').find('select').val(); @@ -153,6 +151,10 @@ Template.accountPreferences.onCreated(function() { let reload = false; + if (RocketChat.settings.get('UI_DisplayRoles')) { + data.hideRoles = JSON.parse($('#hideRoles').find('input:checked').val()); + } + // if highlights changed we need page reload const highlights = RocketChat.getUserPreference(Meteor.user(), 'highlights'); if (highlights && highlights.join('\n') !== data.highlights.join('\n')) { diff --git a/packages/rocketchat-ui-account/client/accountProfile.html b/packages/rocketchat-ui-account/client/accountProfile.html index f1a2581b44de4..d8300889e5c4d 100644 --- a/packages/rocketchat-ui-account/client/accountProfile.html +++ b/packages/rocketchat-ui-account/client/accountProfile.html @@ -42,7 +42,7 @@ - +
+ +