diff --git a/package-lock.json b/package-lock.json index 20c461a4..02530c34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,7 @@ "svelte-link": "^1.4.0", "svelte-select": "^5.7.0", "svelte-splitpanes": "^0.8.0", + "svelte-viewport-info": "^1.0.1", "svelvet": "^9.0.0", "sweetalert2": "^11.6.13", "swiper": "^10.3.1" @@ -3967,6 +3968,14 @@ "svelte": "^4.0.2" } }, + "node_modules/svelte-viewport-info": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/svelte-viewport-info/-/svelte-viewport-info-1.0.1.tgz", + "integrity": "sha512-+cGb246a8I4RTqS/qWLbfMavXUI3RXkQQfcaJvOpFLjPH41S3xwdW8qazX1Y+ISnBO0VP6EBR6aH3VQmwh6AOw==", + "dependencies": { + "tslib": "^2.6.2" + } + }, "node_modules/svelvet": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/svelvet/-/svelvet-9.0.0.tgz", diff --git a/package.json b/package.json index 069ac42a..d2231c1f 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "svelte-link": "^1.4.0", "svelte-select": "^5.7.0", "svelte-splitpanes": "^0.8.0", + "svelte-viewport-info": "^1.0.1", "svelvet": "^9.0.0", "sweetalert2": "^11.6.13", "swiper": "^10.3.1" diff --git a/src/lib/common/LiveChatEntry.svelte b/src/lib/common/LiveChatEntry.svelte index b7ef0f35..82b0d3dc 100644 --- a/src/lib/common/LiveChatEntry.svelte +++ b/src/lib/common/LiveChatEntry.svelte @@ -10,7 +10,7 @@ onMount(async () => { const agentSettings = await getSettingDetail("Agent"); - chatUrl = `${PUBLIC_LIVECHAT_HOST}chat/${agentSettings.hostAgentId}?isLite=true`; + chatUrl = `${PUBLIC_LIVECHAT_HOST}chat/${agentSettings.hostAgentId}?isFrame=true`; showChatIcon = true; }); diff --git a/src/lib/scss/custom/pages/_chat.scss b/src/lib/scss/custom/pages/_chat.scss index 87d1e2fc..6d207b5b 100644 --- a/src/lib/scss/custom/pages/_chat.scss +++ b/src/lib/scss/custom/pages/_chat.scss @@ -102,14 +102,6 @@ .dropdown-menu { box-shadow: $box-shadow; border: 1px solid var(--#{$prefix}border-color); - - li { - &:nth-child(-n+2) { - @media (max-width: 1024px) { - display: none; - } - } - } } } } @@ -217,9 +209,6 @@ padding: 4px; cursor: pointer; color: var(--#{$prefix}secondary-color); - @media (max-width: 575.98px) { - display: none; - } } .dropdown-menu { @@ -282,7 +271,7 @@ .chat-input-section { border-top: 1px solid var(--#{$prefix}border-color); - padding: 2vmin 2% 2vmin 2%; + padding: 2vmin 2%; } .chat-input { @@ -307,12 +296,6 @@ } } -.chat-send { - @media (max-width: 575.98px) { - min-width: auto; - } -} - .chat-log { height: 100vh; diff --git a/src/routes/chat/[agentId]/+page.svelte b/src/routes/chat/[agentId]/+page.svelte index feab7ad8..4c3f84ed 100644 --- a/src/routes/chat/[agentId]/+page.svelte +++ b/src/routes/chat/[agentId]/+page.svelte @@ -39,9 +39,9 @@ conversationId = conversation.id; let chatUrl = `chat/${agentId}/${conversationId}`; - const isLite = $page.url.searchParams.get('isLite'); - if (isLite === 'true') { - chatUrl = `${chatUrl}?isLite=true` + const isFrame = $page.url.searchParams.get('isFrame'); + if (isFrame === 'true') { + chatUrl = `${chatUrl}?isFrame=true` } window.location.href = chatUrl; }); diff --git a/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte b/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte index e39a689c..7ec63e88 100644 --- a/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte +++ b/src/routes/chat/[agentId]/[conversationId]/chat-box.svelte @@ -10,7 +10,9 @@ import { page } from '$app/stores'; import { onMount, tick } from 'svelte'; import Link from 'svelte-link'; + import Viewport from 'svelte-viewport-info' import { PUBLIC_LIVECHAT_ENTRY_ICON } from '$env/static/public'; + import { USER_SENDERS } from '$lib/helpers/constants'; import { signalr } from '$lib/services/signalr-service.js'; import { webSpeech } from '$lib/services/web-speech.js'; import { sendMessageToHub, GetDialogs, deleteConversationMessage } from '$lib/services/conversation-service.js'; @@ -32,7 +34,6 @@ import Swal from 'sweetalert2/dist/sweetalert2.js'; import "sweetalert2/src/sweetalert2.scss"; import moment from 'moment'; - import { USER_SENDERS } from '$lib/helpers/constants'; const options = { scrollbars: { @@ -47,6 +48,7 @@ }; const params = $page.params; const messageLimit = 100; + const screenWidthThreshold = 1024; /** @type {string} */ let text = ""; @@ -82,16 +84,20 @@ /** @type {boolean} */ let isLoadContentLog = false; let isLoadStateLog = false; + let isContentLogClosed = false; + let isStateLogClosed = false; let isOpenEditMsgModal = false; let isOpenAddStateModal = false; let isSendingMsg = false; let isThinking = false; let isLite = false; + let isFrame = false; + onMount(async () => { dialogs = await GetDialogs(params.conversationId); initUserSentMessages(dialogs); - initLogView(); + initChatView(); signalr.onMessageReceivedFromClient = onMessageReceivedFromClient; signalr.onMessageReceivedFromCsr = onMessageReceivedFromCsr; @@ -106,6 +112,25 @@ refresh(); }); + function resizeChatWindow() { + isLite = Viewport.Width <= screenWidthThreshold; + if (!isLite) { + if (isContentLogClosed) { + isLoadContentLog = false; + } else { + isLoadContentLog = true; + } + if (isStateLogClosed) { + isLoadStateLog = false; + } else { + isLoadStateLog = true; + } + } else { + isLoadContentLog = false; + isLoadStateLog = false; + } + } + /** @param {import('$types').ChatResponseModel[]} dialogs */ function initUserSentMessages(dialogs) { const curConvMessages = dialogs?.filter(x => x.sender?.role != UserRole.Assistant).map(x => { @@ -118,13 +143,13 @@ const savedMessages = conversationUserMessageStore.get(); const otherConvMessages = savedMessages?.messages?.filter(x => x.conversationId !== params.conversationId) || []; const allMessages = [...otherConvMessages, ...curConvMessages]; - const truncateMessages = trimUserSentMessages(allMessages); + const trimmedMessages = trimUserSentMessages(allMessages); - prevSentMsgs = truncateMessages.map(x => x.text || ''); + prevSentMsgs = trimmedMessages.map(x => x.text || ''); sentMsgIdx = prevSentMsgs.length; conversationUserMessageStore.put({ pointer: sentMsgIdx, - messages: truncateMessages + messages: trimmedMessages }); } @@ -132,23 +157,21 @@ function renewUserSentMessages(msg) { const savedMessages = conversationUserMessageStore.get(); const allMessages = [...savedMessages?.messages || [], { conversationId: params.conversationId, text: msg || '' }]; - const truncateMessages = trimUserSentMessages(allMessages); - if (allMessages.length > truncateMessages.length) { - sentMsgIdx -= allMessages.length - truncateMessages.length; + const trimmedMessages = trimUserSentMessages(allMessages); + if (allMessages.length > trimmedMessages.length) { + sentMsgIdx -= allMessages.length - trimmedMessages.length; } - prevSentMsgs = truncateMessages.map(x => x.text); - if (sentMsgIdx - 1 < 0) { + if (sentMsgIdx < 0) { sentMsgIdx = 0; + } else if (sentMsgIdx > trimmedMessages.length) { + sentMsgIdx = trimmedMessages.length; } - if (sentMsgIdx + 1 > truncateMessages.length) { - sentMsgIdx = truncateMessages.length; - } - + prevSentMsgs = trimmedMessages.map(x => x.text); conversationUserMessageStore.put({ pointer: sentMsgIdx, - messages: truncateMessages + messages: trimmedMessages }); } @@ -157,10 +180,9 @@ return messages?.slice(-messageLimit) || []; } - function initLogView() { - isLite = $page.url.searchParams.get('isLite') === 'true'; - isLoadContentLog = !isLite; - isLoadStateLog = !isLite; + function initChatView() { + isFrame = $page.url.searchParams.get('isFrame') === 'true'; + resizeChatWindow(); } /** @param {import('$types').ChatResponseModel[]} dialogs */ @@ -374,6 +396,9 @@ isLoadContentLog = !isLoadContentLog; if (!isLoadContentLog) { contentLogs = []; + isContentLogClosed = true; + } else { + isContentLogClosed = false; } } @@ -385,6 +410,9 @@ isLoadStateLog = !isLoadStateLog; if (!isLoadStateLog) { stateLogs = []; + isStateLogClosed = true; + } else { + isStateLogClosed = false; } } @@ -510,6 +538,7 @@ function directToLog(messageId) { if (!!!messageId || isLite) return; + highlightChatMessage(messageId); const elements = []; const contentLogElm = document.querySelector(`#content-log-${messageId}`); if (!!contentLogElm) { @@ -535,11 +564,25 @@ }); } + /** @param {string} messageId */ + function highlightChatMessage(messageId) { + const targets = document.querySelectorAll('.user-msg'); + targets.forEach(elm => { + if (elm.id === `user-msg-${messageId}`) { + elm.classList.add('bg-primary', 'text-white'); + } else { + elm.classList.remove('bg-primary', 'text-white'); + } + }); + } + function openFullScreen() { window.open($page.url.pathname); } + resizeChatWindow()}/> +