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();
 |