mirror of
https://github.com/khoj-ai/khoj.git
synced 2024-11-27 17:35:07 +01:00
Show latest msgs on chat session load. Fetch rest as they near viewport
- Reduces time to first render when loading long chat sessions - Limits size of first page load, when loading long chat sessions These performance improvements are maximally felt for large chat sessions with lots of images generated by Khoj Updated web and desktop app to support these changes for now
This commit is contained in:
parent
9e5585776c
commit
128829c477
2 changed files with 217 additions and 42 deletions
|
@ -130,7 +130,7 @@
|
||||||
return referenceButton;
|
return referenceButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMessage(message, by, dt=null, annotations=null, raw=false) {
|
function renderMessage(message, by, dt=null, annotations=null, raw=false, renderType="append") {
|
||||||
let message_time = formatDate(dt ?? new Date());
|
let message_time = formatDate(dt ?? new Date());
|
||||||
let by_name = by == "khoj" ? "🏮 Khoj" : "🤔 You";
|
let by_name = by == "khoj" ? "🏮 Khoj" : "🤔 You";
|
||||||
let formattedMessage = formatHTMLMessage(message, raw);
|
let formattedMessage = formatHTMLMessage(message, raw);
|
||||||
|
@ -153,10 +153,15 @@
|
||||||
|
|
||||||
// Append chat message div to chat body
|
// Append chat message div to chat body
|
||||||
let chatBody = document.getElementById("chat-body");
|
let chatBody = document.getElementById("chat-body");
|
||||||
|
if (renderType === "append") {
|
||||||
chatBody.appendChild(chatMessage);
|
chatBody.appendChild(chatMessage);
|
||||||
|
|
||||||
// Scroll to bottom of chat-body element
|
// Scroll to bottom of chat-body element
|
||||||
chatBody.scrollTop = chatBody.scrollHeight;
|
chatBody.scrollTop = chatBody.scrollHeight;
|
||||||
|
} else if (renderType === "prepend") {
|
||||||
|
chatBody.insertBefore(chatMessage, chatBody.firstChild);
|
||||||
|
} else if (renderType === "return") {
|
||||||
|
return chatMessage;
|
||||||
|
}
|
||||||
|
|
||||||
let chatBodyWrapper = document.getElementById("chat-body-wrapper");
|
let chatBodyWrapper = document.getElementById("chat-body-wrapper");
|
||||||
chatBodyWrapperHeight = chatBodyWrapper.clientHeight;
|
chatBodyWrapperHeight = chatBodyWrapper.clientHeight;
|
||||||
|
@ -207,6 +212,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMessageWithReference(message, by, context=null, dt=null, onlineContext=null, intentType=null, inferredQueries=null) {
|
function renderMessageWithReference(message, by, context=null, dt=null, onlineContext=null, intentType=null, inferredQueries=null) {
|
||||||
|
// If no document or online context is provided, render the message as is
|
||||||
if ((context == null || context.length == 0) && (onlineContext == null || (onlineContext && Object.keys(onlineContext).length == 0))) {
|
if ((context == null || context.length == 0) && (onlineContext == null || (onlineContext && Object.keys(onlineContext).length == 0))) {
|
||||||
if (intentType?.includes("text-to-image")) {
|
if (intentType?.includes("text-to-image")) {
|
||||||
let imageMarkdown;
|
let imageMarkdown;
|
||||||
|
@ -222,24 +228,21 @@
|
||||||
if (inferredQuery) {
|
if (inferredQuery) {
|
||||||
imageMarkdown += `\n\n**Inferred Query**:\n\n${inferredQuery}`;
|
imageMarkdown += `\n\n**Inferred Query**:\n\n${inferredQuery}`;
|
||||||
}
|
}
|
||||||
renderMessage(imageMarkdown, by, dt);
|
return renderMessage(imageMarkdown, by, dt, null, false, "return");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMessage(message, by, dt);
|
return renderMessage(message, by, dt, null, false, "return");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context == null && onlineContext == null) {
|
if (context == null && onlineContext == null) {
|
||||||
renderMessage(message, by, dt);
|
return renderMessage(message, by, dt, null, false, "return");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((context && context.length == 0) && (onlineContext == null || (onlineContext && Object.keys(onlineContext).length == 0))) {
|
if ((context && context.length == 0) && (onlineContext == null || (onlineContext && Object.keys(onlineContext).length == 0))) {
|
||||||
renderMessage(message, by, dt);
|
return renderMessage(message, by, dt, null, false, "return");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If document or online context is provided, render the message with its references
|
||||||
let references = document.createElement('div');
|
let references = document.createElement('div');
|
||||||
|
|
||||||
let referenceExpandButton = document.createElement('button');
|
let referenceExpandButton = document.createElement('button');
|
||||||
|
@ -297,11 +300,10 @@
|
||||||
if (inferredQuery) {
|
if (inferredQuery) {
|
||||||
imageMarkdown += `\n\n**Inferred Query**:\n\n${inferredQuery}`;
|
imageMarkdown += `\n\n**Inferred Query**:\n\n${inferredQuery}`;
|
||||||
}
|
}
|
||||||
renderMessage(imageMarkdown, by, dt, references);
|
return renderMessage(imageMarkdown, by, dt, references, false, "return");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMessage(message, by, dt, references);
|
return renderMessage(message, by, dt, references, false, "return");
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatHTMLMessage(htmlMessage, raw=false, willReplace=true) {
|
function formatHTMLMessage(htmlMessage, raw=false, willReplace=true) {
|
||||||
|
@ -677,7 +679,7 @@
|
||||||
let firstRunSetupMessageRendered = false;
|
let firstRunSetupMessageRendered = false;
|
||||||
let chatBody = document.getElementById("chat-body");
|
let chatBody = document.getElementById("chat-body");
|
||||||
chatBody.innerHTML = "";
|
chatBody.innerHTML = "";
|
||||||
let chatHistoryUrl = `/api/chat/history?client=desktop`;
|
let chatHistoryUrl = `${hostURL}/api/chat/history?client=desktop`;
|
||||||
if (chatBody.dataset.conversationId) {
|
if (chatBody.dataset.conversationId) {
|
||||||
chatHistoryUrl += `&conversation_id=${chatBody.dataset.conversationId}`;
|
chatHistoryUrl += `&conversation_id=${chatBody.dataset.conversationId}`;
|
||||||
}
|
}
|
||||||
|
@ -689,7 +691,8 @@
|
||||||
loadingScreen.appendChild(yellowOrb);
|
loadingScreen.appendChild(yellowOrb);
|
||||||
chatBody.appendChild(loadingScreen);
|
chatBody.appendChild(loadingScreen);
|
||||||
|
|
||||||
fetch(`${hostURL}${chatHistoryUrl}`, { headers })
|
// Get the most recent 10 chat messages from conversation history
|
||||||
|
fetch(`${chatHistoryUrl}&n=10`, { headers })
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.detail) {
|
if (data.detail) {
|
||||||
|
@ -709,11 +712,21 @@
|
||||||
chatBody.dataset.conversationId = response.conversation_id;
|
chatBody.dataset.conversationId = response.conversation_id;
|
||||||
chatBody.dataset.conversationTitle = response.slug || `New conversation 🌱`;
|
chatBody.dataset.conversationTitle = response.slug || `New conversation 🌱`;
|
||||||
|
|
||||||
const fullChatLog = response.chat || [];
|
// Create a new IntersectionObserver
|
||||||
|
let fetchRemainingMessagesObserver = new IntersectionObserver((entries, observer) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
// If the element is in the viewport, fetch the remaining message and unobserve the element
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
fetchRemainingChatMessages(chatHistoryUrl);
|
||||||
|
observer.unobserve(entry.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, {rootMargin: '0px 0px 0px 0px'});
|
||||||
|
|
||||||
fullChatLog.forEach(chat_log => {
|
const fullChatLog = response.chat || [];
|
||||||
|
fullChatLog.forEach((chat_log, index) => {
|
||||||
if (chat_log.message != null) {
|
if (chat_log.message != null) {
|
||||||
renderMessageWithReference(
|
let messageElement = renderMessageWithReference(
|
||||||
chat_log.message,
|
chat_log.message,
|
||||||
chat_log.by,
|
chat_log.by,
|
||||||
chat_log.context,
|
chat_log.context,
|
||||||
|
@ -721,10 +734,25 @@
|
||||||
chat_log.onlineContext,
|
chat_log.onlineContext,
|
||||||
chat_log.intent?.type,
|
chat_log.intent?.type,
|
||||||
chat_log.intent?.["inferred-queries"]);
|
chat_log.intent?.["inferred-queries"]);
|
||||||
|
chatBody.appendChild(messageElement);
|
||||||
|
|
||||||
|
// When the 4th oldest message is within viewing distance (~60% scrolled up)
|
||||||
|
// Fetch the remaining chat messages
|
||||||
|
if (index === 4) {
|
||||||
|
fetchRemainingMessagesObserver.observe(messageElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
loadingScreen.style.height = chatBody.scrollHeight + 'px';
|
loadingScreen.style.height = chatBody.scrollHeight + 'px';
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Scroll to bottom of chat-body element
|
||||||
|
chatBody.scrollTop = chatBody.scrollHeight;
|
||||||
|
|
||||||
|
// Set height of chat-body element to the height of the chat-body-wrapper
|
||||||
|
let chatBodyWrapper = document.getElementById("chat-body-wrapper");
|
||||||
|
let chatBodyWrapperHeight = chatBodyWrapper.clientHeight;
|
||||||
|
chatBody.style.height = chatBodyWrapperHeight;
|
||||||
|
|
||||||
// Add fade out animation to loading screen and remove it after the animation ends
|
// Add fade out animation to loading screen and remove it after the animation ends
|
||||||
fadeOutLoadingAnimation(loadingScreen);
|
fadeOutLoadingAnimation(loadingScreen);
|
||||||
})
|
})
|
||||||
|
@ -784,6 +812,65 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fetchRemainingChatMessages(chatHistoryUrl) {
|
||||||
|
// Create a new IntersectionObserver
|
||||||
|
let observer = new IntersectionObserver((entries, observer) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
// If the element is in the viewport, render the message and unobserve the element
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
let chat_log = entry.target.chat_log;
|
||||||
|
let messageElement = renderMessageWithReference(
|
||||||
|
chat_log.message,
|
||||||
|
chat_log.by,
|
||||||
|
chat_log.context,
|
||||||
|
new Date(chat_log.created),
|
||||||
|
chat_log.onlineContext,
|
||||||
|
chat_log.intent?.type,
|
||||||
|
chat_log.intent?.["inferred-queries"]
|
||||||
|
);
|
||||||
|
entry.target.replaceWith(messageElement);
|
||||||
|
|
||||||
|
// Remove the observer after the element has been rendered
|
||||||
|
observer.unobserve(entry.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, {rootMargin: '0px 0px 200px 0px'}); // Trigger when the element is within 200px of the viewport
|
||||||
|
|
||||||
|
// Fetch remaining chat messages from conversation history
|
||||||
|
fetch(`${chatHistoryUrl}&n=-10`, { method: "GET" })
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.status != "ok") {
|
||||||
|
throw new Error(data.message);
|
||||||
|
}
|
||||||
|
return data.response;
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
const fullChatLog = response.chat || [];
|
||||||
|
let chatBody = document.getElementById("chat-body");
|
||||||
|
fullChatLog
|
||||||
|
.reverse()
|
||||||
|
.forEach(chat_log => {
|
||||||
|
if (chat_log.message != null) {
|
||||||
|
// Create a new element for each chat log
|
||||||
|
let placeholder = document.createElement('div');
|
||||||
|
placeholder.chat_log = chat_log;
|
||||||
|
|
||||||
|
// Insert the message placeholder as the first child of chat body after the welcome message
|
||||||
|
chatBody.insertBefore(placeholder, chatBody.firstChild.nextSibling);
|
||||||
|
|
||||||
|
// Observe the element
|
||||||
|
placeholder.style.height = "20px";
|
||||||
|
observer.observe(placeholder);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function fadeOutLoadingAnimation(loadingScreen) {
|
function fadeOutLoadingAnimation(loadingScreen) {
|
||||||
let chatBody = document.getElementById("chat-body");
|
let chatBody = document.getElementById("chat-body");
|
||||||
let chatBodyWrapper = document.getElementById("chat-body-wrapper");
|
let chatBodyWrapper = document.getElementById("chat-body-wrapper");
|
||||||
|
|
|
@ -160,7 +160,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
||||||
return referenceButton;
|
return referenceButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMessage(message, by, dt=null, annotations=null, raw=false) {
|
function renderMessage(message, by, dt=null, annotations=null, raw=false, renderType="append") {
|
||||||
let message_time = formatDate(dt ?? new Date());
|
let message_time = formatDate(dt ?? new Date());
|
||||||
let by_name = by == "khoj" ? "🏮 Khoj" : "🤔 You";
|
let by_name = by == "khoj" ? "🏮 Khoj" : "🤔 You";
|
||||||
let formattedMessage = formatHTMLMessage(message, raw);
|
let formattedMessage = formatHTMLMessage(message, raw);
|
||||||
|
@ -183,10 +183,16 @@ To get started, just start typing below. You can also type / to see a list of co
|
||||||
|
|
||||||
// Append chat message div to chat body
|
// Append chat message div to chat body
|
||||||
let chatBody = document.getElementById("chat-body");
|
let chatBody = document.getElementById("chat-body");
|
||||||
|
if (renderType === "append") {
|
||||||
chatBody.appendChild(chatMessage);
|
chatBody.appendChild(chatMessage);
|
||||||
|
|
||||||
// Scroll to bottom of chat-body element
|
// Scroll to bottom of chat-body element
|
||||||
chatBody.scrollTop = chatBody.scrollHeight;
|
chatBody.scrollTop = chatBody.scrollHeight;
|
||||||
|
} else if (renderType === "prepend"){
|
||||||
|
let chatBody = document.getElementById("chat-body");
|
||||||
|
chatBody.insertBefore(chatMessage, chatBody.firstChild);
|
||||||
|
} else if (renderType === "return") {
|
||||||
|
return chatMessage;
|
||||||
|
}
|
||||||
|
|
||||||
let chatBodyWrapper = document.getElementById("chat-body-wrapper");
|
let chatBodyWrapper = document.getElementById("chat-body-wrapper");
|
||||||
chatBodyWrapperHeight = chatBodyWrapper.clientHeight;
|
chatBodyWrapperHeight = chatBodyWrapper.clientHeight;
|
||||||
|
@ -237,6 +243,7 @@ To get started, just start typing below. You can also type / to see a list of co
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderMessageWithReference(message, by, context=null, dt=null, onlineContext=null, intentType=null, inferredQueries=null) {
|
function renderMessageWithReference(message, by, context=null, dt=null, onlineContext=null, intentType=null, inferredQueries=null) {
|
||||||
|
// If no document or online context is provided, render the message as is
|
||||||
if ((context == null || context.length == 0) && (onlineContext == null || (onlineContext && Object.keys(onlineContext).length == 0))) {
|
if ((context == null || context.length == 0) && (onlineContext == null || (onlineContext && Object.keys(onlineContext).length == 0))) {
|
||||||
if (intentType?.includes("text-to-image")) {
|
if (intentType?.includes("text-to-image")) {
|
||||||
let imageMarkdown;
|
let imageMarkdown;
|
||||||
|
@ -251,19 +258,17 @@ To get started, just start typing below. You can also type / to see a list of co
|
||||||
if (inferredQuery) {
|
if (inferredQuery) {
|
||||||
imageMarkdown += `\n\n**Inferred Query**:\n\n${inferredQuery}`;
|
imageMarkdown += `\n\n**Inferred Query**:\n\n${inferredQuery}`;
|
||||||
}
|
}
|
||||||
renderMessage(imageMarkdown, by, dt);
|
return renderMessage(imageMarkdown, by, dt, null, false, "return");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMessage(message, by, dt);
|
return renderMessage(message, by, dt, null, false, "return");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((context && context.length == 0) && (onlineContext == null || (onlineContext && Object.keys(onlineContext).length == 0))) {
|
if ((context && context.length == 0) && (onlineContext == null || (onlineContext && Object.keys(onlineContext).length == 0))) {
|
||||||
renderMessage(message, by, dt);
|
return renderMessage(message, by, dt, null, false, "return");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If document or online context is provided, render the message with its references
|
||||||
let references = document.createElement('div');
|
let references = document.createElement('div');
|
||||||
|
|
||||||
let referenceExpandButton = document.createElement('button');
|
let referenceExpandButton = document.createElement('button');
|
||||||
|
@ -321,11 +326,10 @@ To get started, just start typing below. You can also type / to see a list of co
|
||||||
if (inferredQuery) {
|
if (inferredQuery) {
|
||||||
imageMarkdown += `\n\n**Inferred Query**:\n\n${inferredQuery}`;
|
imageMarkdown += `\n\n**Inferred Query**:\n\n${inferredQuery}`;
|
||||||
}
|
}
|
||||||
renderMessage(imageMarkdown, by, dt, references);
|
return renderMessage(imageMarkdown, by, dt, references, false, "return");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMessage(message, by, dt, references);
|
return renderMessage(message, by, dt, references, false, "return");
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatHTMLMessage(htmlMessage, raw=false, willReplace=true) {
|
function formatHTMLMessage(htmlMessage, raw=false, willReplace=true) {
|
||||||
|
@ -1068,7 +1072,8 @@ To get started, just start typing below. You can also type / to see a list of co
|
||||||
loadingScreen.appendChild(yellowOrb);
|
loadingScreen.appendChild(yellowOrb);
|
||||||
chatBody.appendChild(loadingScreen);
|
chatBody.appendChild(loadingScreen);
|
||||||
|
|
||||||
fetch(chatHistoryUrl, { method: "GET" })
|
// Get the most recent 10 chat messages from conversation history
|
||||||
|
fetch(`${chatHistoryUrl}&n=10`, { method: "GET" })
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.detail) {
|
if (data.detail) {
|
||||||
|
@ -1121,11 +1126,22 @@ To get started, just start typing below. You can also type / to see a list of co
|
||||||
agentMetadataElement.style.display = "none";
|
agentMetadataElement.style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
const fullChatLog = response.chat || [];
|
// Create a new IntersectionObserver
|
||||||
|
let fetchRemainingMessagesObserver = new IntersectionObserver((entries, observer) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
// If the element is in the viewport, fetch the remaining message and unobserve the element
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
fetchRemainingChatMessages(chatHistoryUrl);
|
||||||
|
observer.unobserve(entry.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, {rootMargin: '0px 0px 0px 0px'});
|
||||||
|
|
||||||
fullChatLog.forEach(chat_log => {
|
const fullChatLog = response.chat || [];
|
||||||
|
fullChatLog.forEach((chat_log, index) => {
|
||||||
|
// Render the last 10 messages immediately
|
||||||
if (chat_log.message != null) {
|
if (chat_log.message != null) {
|
||||||
renderMessageWithReference(
|
let messageElement = renderMessageWithReference(
|
||||||
chat_log.message,
|
chat_log.message,
|
||||||
chat_log.by,
|
chat_log.by,
|
||||||
chat_log.context,
|
chat_log.context,
|
||||||
|
@ -1133,14 +1149,26 @@ To get started, just start typing below. You can also type / to see a list of co
|
||||||
chat_log.onlineContext,
|
chat_log.onlineContext,
|
||||||
chat_log.intent?.type,
|
chat_log.intent?.type,
|
||||||
chat_log.intent?.["inferred-queries"]);
|
chat_log.intent?.["inferred-queries"]);
|
||||||
|
chatBody.appendChild(messageElement);
|
||||||
|
|
||||||
|
// When the 4th oldest message is within viewing distance (~60% scroll up)
|
||||||
|
// Fetch the remaining chat messages
|
||||||
|
if (index === 4) {
|
||||||
|
fetchRemainingMessagesObserver.observe(messageElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
loadingScreen.style.height = chatBody.scrollHeight + 'px';
|
loadingScreen.style.height = chatBody.scrollHeight + 'px';
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add fade out animation to loading screen and remove it after the animation ends
|
// Scroll to bottom of chat-body element
|
||||||
|
chatBody.scrollTop = chatBody.scrollHeight;
|
||||||
|
|
||||||
|
// Set height of chat-body element to the height of the chat-body-wrapper
|
||||||
let chatBodyWrapper = document.getElementById("chat-body-wrapper");
|
let chatBodyWrapper = document.getElementById("chat-body-wrapper");
|
||||||
chatBodyWrapperHeight = chatBodyWrapper.clientHeight;
|
let chatBodyWrapperHeight = chatBodyWrapper.clientHeight;
|
||||||
chatBody.style.height = chatBodyWrapperHeight;
|
chatBody.style.height = chatBodyWrapperHeight;
|
||||||
|
|
||||||
|
// Add fade out animation to loading screen and remove it after the animation ends
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loadingScreen.remove();
|
loadingScreen.remove();
|
||||||
chatBody.classList.remove("relative-position");
|
chatBody.classList.remove("relative-position");
|
||||||
|
@ -1198,6 +1226,66 @@ To get started, just start typing below. You can also type / to see a list of co
|
||||||
document.getElementById("chat-input").value = query_via_url;
|
document.getElementById("chat-input").value = query_via_url;
|
||||||
chat();
|
chat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchRemainingChatMessages(chatHistoryUrl) {
|
||||||
|
// Create a new IntersectionObserver
|
||||||
|
let observer = new IntersectionObserver((entries, observer) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
// If the element is in the viewport, render the message and unobserve the element
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
let chat_log = entry.target.chat_log;
|
||||||
|
let messageElement = renderMessageWithReference(
|
||||||
|
chat_log.message,
|
||||||
|
chat_log.by,
|
||||||
|
chat_log.context,
|
||||||
|
new Date(chat_log.created),
|
||||||
|
chat_log.onlineContext,
|
||||||
|
chat_log.intent?.type,
|
||||||
|
chat_log.intent?.["inferred-queries"]
|
||||||
|
);
|
||||||
|
entry.target.replaceWith(messageElement);
|
||||||
|
|
||||||
|
// Remove the observer after the element has been rendered
|
||||||
|
observer.unobserve(entry.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, {rootMargin: '0px 0px 200px 0px'}); // Trigger when the element is within 200px of the viewport
|
||||||
|
|
||||||
|
// Fetch remaining chat messages from conversation history
|
||||||
|
fetch(`${chatHistoryUrl}&n=-10`, { method: "GET" })
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.status != "ok") {
|
||||||
|
throw new Error(data.message);
|
||||||
|
}
|
||||||
|
return data.response;
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
const fullChatLog = response.chat || [];
|
||||||
|
let chatBody = document.getElementById("chat-body");
|
||||||
|
fullChatLog
|
||||||
|
.reverse()
|
||||||
|
.forEach(chat_log => {
|
||||||
|
if (chat_log.message != null) {
|
||||||
|
// Create a new element for each chat log
|
||||||
|
let placeholder = document.createElement('div');
|
||||||
|
placeholder.chat_log = chat_log;
|
||||||
|
|
||||||
|
// Insert the message placeholder as the first child of chat body after the welcome message
|
||||||
|
chatBody.insertBefore(placeholder, chatBody.firstChild.nextSibling);
|
||||||
|
|
||||||
|
// Observe the element
|
||||||
|
placeholder.style.height = "20px";
|
||||||
|
observer.observe(placeholder);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
return;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function flashStatusInChatInput(message) {
|
function flashStatusInChatInput(message) {
|
||||||
|
|
Loading…
Reference in a new issue