You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
348 lines
13 KiB
JavaScript
348 lines
13 KiB
JavaScript
|
|
let osichatSocket;
|
|
let isOpen = false;
|
|
let chatLoaded = false;
|
|
let newMessageCount = 0;
|
|
let atBottom = true;
|
|
|
|
|
|
function scrollBottom() {
|
|
const conversationContainer = document.getElementById('conversation');
|
|
|
|
if (conversationContainer) {
|
|
conversationContainer.scrollTo({
|
|
top: conversationContainer.scrollHeight,
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
function isScrolledToBottom(element) {
|
|
return element && (element.scrollHeight - element.scrollTop <= element.clientHeight + 200);
|
|
}
|
|
|
|
|
|
|
|
function setupScrollEventListener() {
|
|
const conversationContainer = document.getElementById('conversation');
|
|
|
|
if (conversationContainer) {
|
|
conversationContainer.addEventListener('scroll', () => {
|
|
if (isScrolledToBottom(conversationContainer)) {
|
|
if (!atBottom) {
|
|
hideNewMessageNotification();
|
|
atBottom = true; // Update flag when user scrolls to the bottom
|
|
}
|
|
} else {
|
|
atBottom = false; // Update flag if user is not at the bottom
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function showNewMessageNotification(count) {
|
|
const newMessagesPopMessage = document.getElementById('newMessagesPopMessage');
|
|
const newMessagesCounter = document.getElementById('newMessagesCounter');
|
|
if (newMessagesPopMessage && newMessagesCounter) {
|
|
newMessagesCounter.textContent = count;
|
|
newMessagesPopMessage.classList.remove('hidden');
|
|
}
|
|
}
|
|
|
|
function hideNewMessageNotification() {
|
|
const newMessagesPopMessage = document.getElementById('newMessagesPopMessage');
|
|
if (newMessagesPopMessage) {
|
|
newMessagesPopMessage.classList.add('hidden');
|
|
newMessageCount = 0;
|
|
const newMessagesCounter = document.getElementById('newMessagesCounter');
|
|
if (newMessagesCounter) {
|
|
newMessagesCounter.textContent = newMessageCount;
|
|
}
|
|
scrollBottom()
|
|
}
|
|
}
|
|
|
|
|
|
function newMessageNotification() {
|
|
const notificationSound = document.getElementById('notification-sound');
|
|
notificationSound.play();
|
|
|
|
const conversationContainer = document.getElementById('conversation');
|
|
|
|
if (!isScrolledToBottom(conversationContainer)) {
|
|
let count = newMessageCount + 1;
|
|
newMessageCount = count;
|
|
showNewMessageNotification(count);
|
|
} else {
|
|
scrollBottom();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// FUNCTION TO FETCH THE SESSION ID
|
|
async function fetchSessionID() {
|
|
let session_id = 'Unknown';
|
|
while (session_id === 'Unknown') {
|
|
try {
|
|
const response = await fetch(`${protocol}://${ositcomDomain}/get-client-session/`);
|
|
const data = await response.json();
|
|
if (data.session_id) {
|
|
session_id = data.session_id;
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fetching session ID:', error);
|
|
}
|
|
}
|
|
return session_id;
|
|
}
|
|
|
|
// FUNCTIONS TO SHOW & HIDE THE LOADER
|
|
function showLoader() {
|
|
const osichatLoader = document.getElementById('osichatLoader');
|
|
if (osichatLoader) {
|
|
osichatLoader.classList.remove('hidden');
|
|
}
|
|
}
|
|
|
|
function hideLoader() {
|
|
const osichatLoader = document.getElementById('osichatLoader');
|
|
if (osichatLoader) {
|
|
osichatLoader.classList.add('hidden');
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// FUNCTION TO APPEND THE TEXTAREA SCRIPT
|
|
function appendTextAreaScript(domain, chatDiv) {
|
|
const textareaScript = document.createElement('script');
|
|
textareaScript.type = 'text/javascript';
|
|
textareaScript.src = `${protocol}://${domain}/static/js/osichat/textarea.js`;
|
|
chatDiv.appendChild(textareaScript);
|
|
}
|
|
|
|
// FUNCTION TO HANDLE FORM SUBMISSION
|
|
function handleFormSubmission(form, eventType, osichatSocket) {
|
|
form.addEventListener('submit', function (event) {
|
|
event.preventDefault();
|
|
|
|
const formData = new FormData(form);
|
|
const eventMessage = { 'event_type': eventType };
|
|
|
|
formData.forEach((value, key) => {
|
|
eventMessage[key] = value;
|
|
});
|
|
if (eventType === 'start_conversation') {
|
|
showLoader();
|
|
}
|
|
osichatSocket.send(JSON.stringify(eventMessage));
|
|
form.reset();
|
|
});
|
|
}
|
|
|
|
// FUNCTION TO HANDLE LOAD CHAT EVENT
|
|
function handleLoadChatEvent(data, osichatSocket) {
|
|
chatLoaded = true;
|
|
hideLoader();
|
|
let chatDiv = document.getElementById('roomContainer'); // CASE WHERE WIDGET IS ALREADY LOADED, DISPLAY THE CHAT PAGES(START/CONVERSATION) IN ROOM CONTAINER
|
|
if (!chatDiv) {
|
|
chatDiv = document.getElementById('osichat'); // CASE WHERE WIDGET IS NOT LOADED, DISPLAY THE WHOLE CHATWIDGET IN OSICHAT
|
|
}
|
|
|
|
chatDiv.innerHTML = data.html;
|
|
scrollBottom();
|
|
|
|
|
|
if (isOpen) { // If chat widget isOpen mark all messages as read by guest else just return number of unread messages
|
|
osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'open' }));
|
|
} else {
|
|
osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'closed' }));
|
|
}
|
|
|
|
|
|
if (!document.querySelector(`script[src="${protocol}://${osinaDomain}/static/js/osichat/chat-toggle.js"]`)) {
|
|
const script = document.createElement('script');
|
|
script.type = 'text/javascript';
|
|
script.src = `${protocol}://${osinaDomain}/static/js/osichat/chat-toggle.js`;
|
|
chatDiv.appendChild(script);
|
|
}
|
|
|
|
const startChatContainer = document.getElementById('startChat'); //Case where returned is start-conversation.html
|
|
if (startChatContainer) {
|
|
handleFormSubmission(startChatContainer, 'start_conversation', osichatSocket);
|
|
}
|
|
|
|
const sendMessageContainer = document.getElementById('sendMessage'); //Case where returned is chat-room.html
|
|
if (sendMessageContainer) {
|
|
appendTextAreaScript(osinaDomain, chatDiv);
|
|
handleFormSubmission(sendMessageContainer, 'send_message', osichatSocket);
|
|
|
|
const uploadScript = document.createElement('script');
|
|
uploadScript.type = 'text/javascript';
|
|
uploadScript.src = `${protocol}://${osinaDomain}/static/js/osichat/upload-file.js`;
|
|
chatDiv.appendChild(uploadScript);
|
|
|
|
const endChatScript = document.createElement('script');
|
|
endChatScript.type = 'text/javascript';
|
|
endChatScript.src = `${protocol}://${osinaDomain}/static/js/osichat/end-chat.js`;
|
|
chatDiv.appendChild(endChatScript);
|
|
|
|
const endChatButton = document.getElementById('endChat');
|
|
endChatButton.classList.remove('hidden')
|
|
}
|
|
|
|
const sendReviewContainer = document.getElementById('reviewContainer'); //Case where returned is ended-chat.html
|
|
if (sendReviewContainer) {
|
|
const sendReviewScript = document.createElement('script');
|
|
sendReviewScript.type = 'text/javascript';
|
|
sendReviewScript.src = `${protocol}://${osinaDomain}/static/js/osichat/send-review.js`;
|
|
chatDiv.appendChild(sendReviewScript);
|
|
}
|
|
}
|
|
|
|
|
|
// FUNCTION TO INITIALIZE WEB SOCKET CONNECTION
|
|
async function initializeChatWebSocket() {
|
|
const session_id = await fetchSessionID();
|
|
let osichatSocketUrl = `${wsScheme}://${osinaDomain}/ws/osichat/${session_id}/`;
|
|
osichatSocket = new WebSocket(osichatSocketUrl);
|
|
|
|
osichatSocket.onopen = () => {
|
|
if(!chatLoaded){
|
|
osichatSocket.send(JSON.stringify({ 'event_type': 'load_chat', 'client_type': 'website_guest', 'reconnecting': 'False'}));
|
|
}else{
|
|
osichatSocket.send(JSON.stringify({ 'event_type': 'load_chat', 'client_type': 'website_guest', 'reconnecting': 'True'}));
|
|
}
|
|
};
|
|
|
|
osichatSocket.onmessage = function (e) {
|
|
const data = JSON.parse(e.data);
|
|
const typingDiv = document.getElementById('typing');
|
|
const messagesDiv = document.getElementById('messages');
|
|
switch (data.event_type) {
|
|
case 'load_chat':
|
|
handleLoadChatEvent(data, osichatSocket);
|
|
break;
|
|
case 'start_conversation':
|
|
handleLoadChatEvent(data, osichatSocket);
|
|
break;
|
|
case 'typing':
|
|
if(!typingDiv && data.user){
|
|
messagesDiv.insertAdjacentHTML('beforeend', data.html);
|
|
}
|
|
break;
|
|
case 'stopped_typing':
|
|
if (typingDiv) {
|
|
typingDiv.remove();
|
|
}
|
|
break;
|
|
case 'send_message':
|
|
if (isOpen) { // If chat widget isOpen (declared in chat-toggle.js) mark all messages as read by guest else just return number of unread messages
|
|
osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'open' }));
|
|
} else {
|
|
osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'closed' }));
|
|
}
|
|
messagesDiv.insertAdjacentHTML('beforeend', data.html);
|
|
|
|
const newMessagesPopMessage = document.getElementById('newMessagesPopMessage');
|
|
newMessagesPopMessage.addEventListener('click', hideNewMessageNotification);
|
|
|
|
if (data.user) { // If it is sent by an Osina user play a notification sound for the guest
|
|
if (typingDiv) {
|
|
typingDiv.remove();
|
|
}
|
|
newMessageNotification();
|
|
setupScrollEventListener();
|
|
}
|
|
break;
|
|
case 'uploaded_file':
|
|
if (isOpen) {
|
|
osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'open' }));
|
|
} else {
|
|
osichatSocket.send(JSON.stringify({ 'event_type': 'update_read_messages', 'chat_state': 'closed' }));
|
|
}
|
|
const uploadingDiv = document.getElementById(`uploading-${data.file_name}`);
|
|
if (uploadingDiv) {
|
|
uploadingDiv.outerHTML = data.html;
|
|
if (!data.user) {
|
|
scrollBottom();
|
|
} else {
|
|
newMessageNotification();
|
|
}
|
|
}
|
|
else{
|
|
document.getElementById('messages').insertAdjacentHTML('beforeend', data.html);
|
|
if (!data.user) {
|
|
scrollBottom();
|
|
} else {
|
|
newMessageNotification();
|
|
}
|
|
}
|
|
break;
|
|
case 'update_read_messages':
|
|
const unreadMessages = document.getElementById(`unreadMessages`);
|
|
if (!isOpen) {
|
|
unreadMessages.classList.remove('hidden');
|
|
unreadMessages.innerHTML = data.html;
|
|
const script = document.createElement('script');
|
|
script.src = `${protocol}://${osinaDomain}/static/js/osichat/chat-toggle.js`;
|
|
document.body.appendChild(script);
|
|
} else {
|
|
unreadMessages.classList.add('hidden');
|
|
}
|
|
break;
|
|
case 'ended_chat':
|
|
const currentChat = document.getElementById(`roomContainer`);
|
|
if (currentChat) {
|
|
currentChat.innerHTML = data.html;
|
|
scrollBottom();
|
|
}
|
|
document.getElementById(`endChatConfirmationContainer`).classList.add('hidden');
|
|
document.getElementById(`endChat`).classList.add('hidden');
|
|
const sendReviewScript = document.createElement('script');
|
|
sendReviewScript.type = 'text/javascript';
|
|
sendReviewScript.src = `${protocol}://${osinaDomain}/static/js/osichat/send-review.js`;
|
|
currentChat.appendChild(sendReviewScript);
|
|
break;
|
|
case 'submit_review':
|
|
const submitReview = document.getElementById(`reviewContainer`);
|
|
if (submitReview) {
|
|
submitReview.innerHTML = data.html;
|
|
}
|
|
const reviewScript = document.createElement('script');
|
|
reviewScript.type = 'text/javascript';
|
|
reviewScript.src = `${protocol}://${osinaDomain}/static/js/osichat/send-review.js`;
|
|
submitReview.appendChild(reviewScript);
|
|
break;
|
|
default:
|
|
console.log('Unknown event type:', data.event_type);
|
|
}
|
|
};
|
|
|
|
osichatSocket.onclose = () => {
|
|
showLoader();
|
|
setTimeout(() => {
|
|
console.log('Attempting to reconnect to WebSocket...');
|
|
initializeChatWebSocket();
|
|
}, 2000);
|
|
};
|
|
|
|
osichatSocket.onerror = (error) => {
|
|
console.log('WebSocket error:', error);
|
|
showLoader();
|
|
};
|
|
}
|
|
|
|
|
|
window.addEventListener('offline', () => {
|
|
showLoader();
|
|
if (osichatSocket) {
|
|
osichatSocket.close();
|
|
}
|
|
});
|
|
|
|
// INITIALIZE CHAT WEB SOCKET
|
|
initializeChatWebSocket();
|