diff --git a/config/helloApi.ts b/config/helloApi.ts index 0a30c2c0..c360ac02 100644 --- a/config/helloApi.ts +++ b/config/helloApi.ts @@ -95,7 +95,38 @@ export async function getAllChannels(): Promise { // For anonymous users (msg not sent), use a_clientId if available authorization = `${widgetId}:${aClientId}`; } - + // Determine if we should send anon_client_uuid for merging + const lastUniqueIdKey = `${widgetId}_last_unique_id`; + const lastUniqueId = localStorage.getItem(lastUniqueIdKey); + + let anonClientUuidToSend = null; + + if (!unique_id) { + console.log("ANONYMOUS CASE"); + // LOGOUT CASE + if (lastUniqueId) { + console.log("pehle login tha") + // last_unique_id exists → user logged in before → get uuid from last login + const lastLoginClientIdKey = `${widgetId}_${lastUniqueId}_k_clientId`; + const lastLoginUuid = localStorage.getItem(lastLoginClientIdKey); + anonClientUuidToSend = lastLoginUuid; + console.log("anonClientUuidToSend", anonClientUuidToSend); + } + } else { + console.log("LOGIN CASE"); + // LOGIN CASE (has unique_id) + if (!lastUniqueId) { + console.log("pehle logout tha") + // No last_unique_id → first login → send k/a clientId to merge logout chat + // No last_unique_id → first login → send logout user's k/a clientId to merge + const logoutKClientIdKey = `${widgetId}_k_clientId`; + const logoutAClientIdKey = `${widgetId}_a_clientId`; + const logoutKClientId = localStorage.getItem(logoutKClientIdKey); + const logoutAClientId = localStorage.getItem(logoutAClientIdKey); + anonClientUuidToSend = logoutKClientId || logoutAClientId; + console.log("anonClientUuidToSend", anonClientUuidToSend); + } + } const response = await axios.post( `${HELLO_HOST_URL}/pubnub-channels/list/`, { @@ -104,6 +135,7 @@ export async function getAllChannels(): Promise { number, unique_id, user_data: getUserData(), + ...(anonClientUuidToSend ? { anon_client_uuid: anonClientUuidToSend } : {}) // is_anon: isAnon, // ...(isAnon ? { anonymous_client_uuid: aClientId, uuid: aClientId } : {}) }, @@ -117,6 +149,18 @@ export async function getAllChannels(): Promise { // Set the appropriate client ID based on user type if (response?.data?.uuid) { if (hasUserIdentity) { + if (unique_id) { + const widgetId = getLocalStorage('WidgetId'); + console.log("widgetId", widgetId); + const lastUniqueIdKey = `${widgetId}_last_unique_id`; + console.log("lastunique id", lastUniqueIdKey); + const lastUniqueId = localStorage.getItem(lastUniqueIdKey); + if (unique_id && unique_id !== lastUniqueId) { + localStorage.setItem(lastUniqueIdKey, unique_id); + } + localStorage.setItem(`${widgetId}_k_clientId`, response.data.uuid); + localStorage.setItem(`${widgetId}_a_clientId`, response.data.uuid); + } setLocalStorage('k_clientId', response.data.uuid); } else if (isAnon) { setLocalStorage('a_clientId', response.data.uuid); diff --git a/hooks/HELLO/eventHandlers/embeddingScript/embeddingScriptEventHandler.ts b/hooks/HELLO/eventHandlers/embeddingScript/embeddingScriptEventHandler.ts index fcff95d9..3f8892d5 100644 --- a/hooks/HELLO/eventHandlers/embeddingScript/embeddingScriptEventHandler.ts +++ b/hooks/HELLO/eventHandlers/embeddingScript/embeddingScriptEventHandler.ts @@ -11,7 +11,7 @@ import { setDataInInterfaceRedux } from "@/store/interface/interfaceSlice"; import { GetSessionStorageData, SetSessionStorage } from "@/utils/ChatbotUtility"; import { useCustomSelector } from "@/utils/deepCheckSelector"; import { emitEventToParent } from "@/utils/emitEventsToParent/emitEventsToParent"; -import { cleanObject, removeFromLocalStorage, setLocalStorage } from "@/utils/utilities"; +import { cleanObject, getLocalStorage, removeFromLocalStorage, setLocalStorage } from "@/utils/utilities"; import isPlainObject from "lodash.isplainobject"; import { useContext, useEffect, useRef } from "react"; import { useDispatch } from "react-redux"; @@ -123,8 +123,9 @@ const useHandleHelloEmbeddingScriptEvents = (eventHandler: EmbeddingScriptEventR dispatch(setDataInAppInfoReducer({ subThreadId: '', currentChannelId: '', currentChatId: '', currentTeamId: '' })); }; - // Reset if widget token changed - if (fullWidgetToken !== prevWidgetId) { + const isWidgetTokenChanged = fullWidgetToken !== prevWidgetId; + // Reset if widget token changed (clears OLD tabSessionId's state) + if (isWidgetTokenChanged) { resetKeys(); } @@ -154,6 +155,13 @@ const useHandleHelloEmbeddingScriptEvents = (eventHandler: EmbeddingScriptEventR isHelloUser: true, })); + // After updating chatSessionId (which changes the tabSessionId key used by appInfo), + // reset appInfo again for the NEW tabSessionId to clear any stale data + // from previous sessions that reused the same key (e.g., anon → known → anon) + if (isWidgetTokenChanged) { + resetKeys(); + } + SetSessionStorage('helloConfig', JSON.stringify(event.data.data)); dispatch(setHelloConfig(event.data.data)); @@ -254,6 +262,33 @@ const useHandleHelloEmbeddingScriptEvents = (eventHandler: EmbeddingScriptEventR } } + function handleShutdownChatbot() { + const widgetId = getLocalStorage('WidgetId'); + if (widgetId) { + const lastUniqueIdKey = `${widgetId}_last_unique_id`; + const lastUniqueId = localStorage.getItem(lastUniqueIdKey); + + // Clear the last_unique_id so anon users won't be treated as known + localStorage.removeItem(lastUniqueIdKey); + + // Clear per-user client ID mappings + if (lastUniqueId) { + localStorage.removeItem(`${widgetId}_${lastUniqueId}_k_clientId`); + } + + // Clear widget-level client ID mappings + localStorage.removeItem(`${widgetId}_k_clientId`); + localStorage.removeItem(`${widgetId}_a_clientId`); + } + + // Clear session client IDs + removeFromLocalStorage('k_clientId'); + removeFromLocalStorage('a_clientId'); + + // Reset appInfo state to clear stale channel data + dispatch(setDataInAppInfoReducer({ subThreadId: '', currentChannelId: '', currentChatId: '', currentTeamId: '' })); + } + useEffect(() => { eventHandler.addEventHandler('parent-route-changed', handleParentRouteChanged) @@ -280,6 +315,8 @@ const useHandleHelloEmbeddingScriptEvents = (eventHandler: EmbeddingScriptEventR eventHandler.addEventHandler('GET_TICKET_UNREAD_COUNT', handleGetTicketUnreadCount) + eventHandler.addEventHandler('SHUTDOWN_CHATBOT', handleShutdownChatbot) + }, []) return null diff --git a/public/chat-widget-dev.js b/public/chat-widget-dev.js index a3d54fa4..51a08f44 100644 --- a/public/chat-widget-dev.js +++ b/public/chat-widget-dev.js @@ -1431,6 +1431,9 @@ sendMessageToChatbot({ type: "GET_TICKET_UNREAD_COUNT", data: { id } }); }); }, + shutdown() { + sendMessageToChatbot({ type: "SHUTDOWN_CHATBOT" }) + } }; helloChatbotManager.initializeChatbot(); diff --git a/public/chat-widget-local.js b/public/chat-widget-local.js index 4f4222bd..fbdb2402 100644 --- a/public/chat-widget-local.js +++ b/public/chat-widget-local.js @@ -1419,6 +1419,9 @@ sendMessageToChatbot({ type: "GET_TICKET_UNREAD_COUNT", data: { id } }); }); }, + shutdown() { + sendMessageToChatbot({ type: "SHUTDOWN_CHATBOT" }) + } }; helloChatbotManager.initializeChatbot(); diff --git a/public/chat-widget.js b/public/chat-widget.js index fbe9711c..bc74fa68 100644 --- a/public/chat-widget.js +++ b/public/chat-widget.js @@ -1426,6 +1426,9 @@ sendMessageToChatbot({ type: "GET_TICKET_UNREAD_COUNT", data: { id } }); }); }, + shutdown() { + sendMessageToChatbot({ type: "SHUTDOWN_CHATBOT" }) + } }; helloChatbotManager.initializeChatbot();