diff --git a/app/livechat/server/api/lib/livechat.js b/app/livechat/server/api/lib/livechat.js index 63a940094a53c..11aaddc5f6e70 100644 --- a/app/livechat/server/api/lib/livechat.js +++ b/app/livechat/server/api/lib/livechat.js @@ -173,6 +173,7 @@ export async function settings(url) { livechat_kill_switch_message: initSettings.Livechat_kill_switch_message, livechat_friendly_chat: initSettings.Livechat_friendly_chat, livechat_enable_avatar: initSettings.Livechat_enable_avatar, + Livechat_close_room_on_user_disconnect: initSettings.Livechat_close_room_on_user_disconnect, livechat_enable_elastic_search_logs: initSettings.Livechat_enable_elastic_search_logs, livechat_elastic_search_url: initSettings.Livechat_elastic_search_url, livechat_elastic_search_index: initSettings.Livechat_elastic_search_index, diff --git a/app/livechat/server/config.ts b/app/livechat/server/config.ts index 942381c8dd6af..808dacecb2ed5 100644 --- a/app/livechat/server/config.ts +++ b/app/livechat/server/config.ts @@ -66,6 +66,14 @@ Meteor.startup(function() { i18nDescription: 'Livechat_enable_avatar_description', }); + this.add('Livechat_close_room_on_user_disconnect', true, { + type: 'boolean', + group: 'Omnichannel', + section: 'Livechat', + public: true, + i18nDescription: 'Livechat_close_room_on_user_disconnect_description', + }); + this.add('Livechat_title', 'Rocket.Chat', { type: 'string', group: 'Omnichannel', diff --git a/app/livechat/server/lib/Livechat.js b/app/livechat/server/lib/Livechat.js index c46877150a82b..d0903ff625270 100644 --- a/app/livechat/server/lib/Livechat.js +++ b/app/livechat/server/lib/Livechat.js @@ -537,6 +537,7 @@ export const Livechat = { const rcSettings = {}; Settings.findNotHiddenPublic([ + 'Livechat_close_room_on_user_disconnect', 'Livechat_friendly_chat', 'Livechat_enable_avatar', 'Livechat_title', diff --git a/app/livechat/server/methods/getInitialData.js b/app/livechat/server/methods/getInitialData.js index 063c1dcdd9f41..c5735cd3b060e 100644 --- a/app/livechat/server/methods/getInitialData.js +++ b/app/livechat/server/methods/getInitialData.js @@ -97,6 +97,7 @@ Meteor.methods({ info.livechat_kill_switch_message = initSettings.Livechat_kill_switch_message; info.livechat_friendly_chat = initSettings.Livechat_friendly_chat; info.livechat_enable_avatar = initSettings.Livechat_enable_avatar; + info.Livechat_close_room_on_user_disconnect = initSettings.Livechat_close_room_on_user_disconnect; info.livechat_enable_elastic_search_logs = initSettings.Livechat_enable_elastic_search_logs; info.livechat_elastic_search_url = initSettings.Livechat_elastic_search_url; info.livechat_elastic_search_index = initSettings.Livechat_elastic_search_index; diff --git a/app/livechat/server/methods/setUpConnection.js b/app/livechat/server/methods/setUpConnection.js index 21dd64263ef9b..2121b271a6285 100644 --- a/app/livechat/server/methods/setUpConnection.js +++ b/app/livechat/server/methods/setUpConnection.js @@ -1,20 +1,54 @@ import { Meteor } from 'meteor/meteor'; import { check } from 'meteor/check'; +import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; +import { settings } from '../../../settings'; +import { LivechatRooms, LivechatVisitors, LivechatDepartment } from '../../../models/server/index'; import { Livechat } from '../lib/Livechat'; +const clients = {}; + Meteor.methods({ 'livechat:setUpConnection'(data) { check(data, { token: String, + isMobile: Boolean, }); - const { token } = data; + const { token, isMobile } = data; + clients[token] = clients[token] ? clients[token] + 1 : 1; if (!this.connection.livechatToken) { this.connection.livechatToken = token; + this.connection.isMobile = isMobile; this.connection.onClose(() => { - Livechat.notifyGuestStatusChanged(token, 'offline'); + clients[token] && (clients[token] -= 1); + + const visitor = LivechatVisitors.getVisitorByToken(token); + const room = LivechatRooms.findOneOpenByVisitorToken(token); + const department = LivechatDepartment.findOneByIdOrName(room.departmentId); + const comment = TAPi18n.__('Closed_by_visitor', { lng: (visitor && visitor.language) || settings.get('Language') || 'en' }); + const logOutput = { + rid: room._id, + currentBot: room.servedBy, + currentDepartment: { + id: department._id, + name: department.name, + email: department.email, + }, + isHandedOverFromDialogFlow: !!room?.customFields?.isHandedOverFromDialogFlow, + agentAssigned: !!room?.customFields?.agentAssigned, + }; + console.error('Browser closed by user :', JSON.stringify(logOutput)); + + if (this?.connection?.isMobile) { + return; + } + if (clients[token] === 0 && settings.get('Livechat_close_room_on_user_disconnect')) { + delete clients[token]; + Livechat.notifyGuestStatusChanged(token, 'offline'); + return Livechat.closeRoom({ visitor, room, comment }); + } }); } }, diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index eb0384af494bc..a430e2935c50d 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -2638,6 +2638,8 @@ "Livechat": "Livechat", "Livechat_friendly_chat": "Enable Friendly Chat", "Livechat_friendly_chat_description": "Enables friendly chat UI in Livechat widget", + "Livechat_close_room_on_user_disconnect": "Close room when user disconnects", + "Livechat_close_room_on_user_disconnect_description": "Close room when user closes browser or is disconnected", "Livechat_enable_avatar": "Show Avatar", "Livechat_enable_avatar_description": "Show Avatars in Livechat widget", "Livechat_enable_elastic_search_logs": "Enable sending logs to Elastic Search",