Mark-Lasfar
commited on
Commit
·
e018b86
1
Parent(s):
8fa53e0
add chat
Browse files- static/js/chat.js +79 -32
static/js/chat.js
CHANGED
|
@@ -33,33 +33,52 @@ const uiElements = {
|
|
| 33 |
settingsModal: document.getElementById('settingsModal'),
|
| 34 |
closeSettingsBtn: document.getElementById('closeSettingsBtn'),
|
| 35 |
settingsForm: document.getElementById('settingsForm'),
|
| 36 |
-
historyToggle: document.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
duration: 800,
|
| 38 |
easing: 'ease-out-cubic',
|
| 39 |
once: true,
|
| 40 |
offset: 50,
|
| 41 |
});
|
| 42 |
-
|
|
|
|
| 43 |
console.log('Loading conversation with ID:', currentConversationId);
|
| 44 |
-
await loadConversation(currentConversationId);
|
| 45 |
} else if (conversationHistory.length > 0) {
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
} else {
|
| 53 |
-
|
| 54 |
-
}
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
}
|
| 62 |
-
|
|
|
|
| 63 |
});
|
| 64 |
|
| 65 |
// Check authentication token
|
|
@@ -114,6 +133,13 @@ function renderMarkdown(el) {
|
|
| 114 |
});
|
| 115 |
wrapper.querySelectorAll('hr').forEach(h => h.classList.add('styled-hr'));
|
| 116 |
Prism.highlightAllUnder(wrapper);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
}
|
| 118 |
|
| 119 |
// Toggle chat view
|
|
@@ -149,8 +175,6 @@ function addMsg(who, text) {
|
|
| 149 |
if (uiElements.chatBox) {
|
| 150 |
uiElements.chatBox.appendChild(div);
|
| 151 |
uiElements.chatBox.classList.remove('hidden');
|
| 152 |
-
uiElements.chatBox.scrollTop = uiElements.chatBox.scrollHeight;
|
| 153 |
-
console.log('Message added to chatBox:', div);
|
| 154 |
} else {
|
| 155 |
console.error('chatBox is null');
|
| 156 |
}
|
|
@@ -334,6 +358,9 @@ async function sendRequest(endpoint, body, headers = {}) {
|
|
| 334 |
return response;
|
| 335 |
} catch (error) {
|
| 336 |
console.error('Send request error:', error);
|
|
|
|
|
|
|
|
|
|
| 337 |
throw error;
|
| 338 |
}
|
| 339 |
}
|
|
@@ -526,7 +553,10 @@ async function createNewConversation() {
|
|
| 526 |
console.error('Error creating conversation:', error);
|
| 527 |
alert('Failed to create new conversation. Please try again.');
|
| 528 |
}
|
| 529 |
-
if (uiElements.chatBox) uiElements.chatBox.
|
|
|
|
|
|
|
|
|
|
| 530 |
}
|
| 531 |
|
| 532 |
// Update conversation title
|
|
@@ -585,9 +615,10 @@ function setupTouchGestures() {
|
|
| 585 |
if (!isSidebarOpen) return;
|
| 586 |
let translateX = Math.max(-uiElements.sidebar.offsetWidth, Math.min(0, e.deltaX));
|
| 587 |
uiElements.sidebar.style.transform = `translateX(${translateX}px)`;
|
|
|
|
| 588 |
});
|
| 589 |
hammer.on('panend', e => {
|
| 590 |
-
|
| 591 |
if (e.deltaX < -50) {
|
| 592 |
toggleSidebar(false);
|
| 593 |
} else {
|
|
@@ -726,7 +757,6 @@ async function submitMessage() {
|
|
| 726 |
currentAssistantText = buffer;
|
| 727 |
streamMsg.querySelector('.loading')?.remove();
|
| 728 |
renderMarkdown(streamMsg);
|
| 729 |
-
if (uiElements.chatBox) uiElements.chatBox.scrollTop = uiElements.chatBox.scrollHeight;
|
| 730 |
}
|
| 731 |
}
|
| 732 |
responseText = buffer;
|
|
@@ -744,7 +774,7 @@ async function submitMessage() {
|
|
| 744 |
await saveMessageToConversation(currentConversationId, 'assistant', responseText);
|
| 745 |
}
|
| 746 |
if (checkAuth()) {
|
| 747 |
-
await loadConversations();
|
| 748 |
}
|
| 749 |
finalizeRequest();
|
| 750 |
} catch (error) {
|
|
@@ -798,8 +828,6 @@ if (logoutBtn) {
|
|
| 798 |
});
|
| 799 |
}
|
| 800 |
|
| 801 |
-
|
| 802 |
-
|
| 803 |
// Settings Modal
|
| 804 |
if (uiElements.settingsBtn) {
|
| 805 |
uiElements.settingsBtn.addEventListener('click', async () => {
|
|
@@ -989,16 +1017,21 @@ if (uiElements.form) {
|
|
| 989 |
}
|
| 990 |
|
| 991 |
if (uiElements.input) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 992 |
uiElements.input.addEventListener('keydown', (e) => {
|
| 993 |
if (e.key === 'Enter' && !e.shiftKey) {
|
| 994 |
e.preventDefault();
|
| 995 |
if (!isRecording && !uiElements.sendBtn.disabled) submitMessage();
|
| 996 |
}
|
| 997 |
});
|
| 998 |
-
uiElements.input.addEventListener('input', () => {
|
| 999 |
-
autoResizeTextarea();
|
| 1000 |
-
updateSendButtonState();
|
| 1001 |
-
});
|
| 1002 |
}
|
| 1003 |
|
| 1004 |
if (uiElements.stopBtn) {
|
|
@@ -1034,3 +1067,17 @@ localStorage.removeItem = function (key) {
|
|
| 1034 |
console.log('Removing from localStorage:', key);
|
| 1035 |
originalRemoveItem.apply(this, arguments);
|
| 1036 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
settingsModal: document.getElementById('settingsModal'),
|
| 34 |
closeSettingsBtn: document.getElementById('closeSettingsBtn'),
|
| 35 |
settingsForm: document.getElementById('settingsForm'),
|
| 36 |
+
historyToggle: document.getElementById('historyToggle'),
|
| 37 |
+
};
|
| 38 |
+
|
| 39 |
+
// State variables
|
| 40 |
+
let conversationHistory = JSON.parse(sessionStorage.getItem('conversationHistory') || '[]');
|
| 41 |
+
let currentConversationId = window.conversationId || null;
|
| 42 |
+
let currentConversationTitle = window.conversationTitle || null;
|
| 43 |
+
let isRequestActive = false;
|
| 44 |
+
let isRecording = false;
|
| 45 |
+
let mediaRecorder = null;
|
| 46 |
+
let audioChunks = [];
|
| 47 |
+
let streamMsg = null;
|
| 48 |
+
let currentAssistantText = '';
|
| 49 |
+
let isSidebarOpen = window.innerWidth >= 768;
|
| 50 |
+
|
| 51 |
+
// Initialize AOS and load initial conversation
|
| 52 |
+
document.addEventListener('DOMContentLoaded', async () => {
|
| 53 |
+
AOS.init({
|
| 54 |
duration: 800,
|
| 55 |
easing: 'ease-out-cubic',
|
| 56 |
once: true,
|
| 57 |
offset: 50,
|
| 58 |
});
|
| 59 |
+
|
| 60 |
+
if (currentConversationId && checkAuth()) {
|
| 61 |
console.log('Loading conversation with ID:', currentConversationId);
|
| 62 |
+
await loadConversation(currentConversationId);
|
| 63 |
} else if (conversationHistory.length > 0) {
|
| 64 |
+
console.log('Restoring conversation history from sessionStorage:', conversationHistory);
|
| 65 |
+
enterChatView();
|
| 66 |
+
conversationHistory.forEach(msg => {
|
| 67 |
+
console.log('Adding message from history:', msg);
|
| 68 |
+
addMsg(msg.role, msg.content);
|
| 69 |
+
});
|
| 70 |
+
} else {
|
| 71 |
+
console.log('No conversation history or ID, starting fresh');
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
autoResizeTextarea();
|
| 75 |
+
updateSendButtonState();
|
| 76 |
+
if (uiElements.swipeHint) {
|
| 77 |
+
setTimeout(() => {
|
| 78 |
+
uiElements.swipeHint.style.display = 'none';
|
| 79 |
+
}, 3000);
|
| 80 |
+
}
|
| 81 |
+
setupTouchGestures();
|
| 82 |
});
|
| 83 |
|
| 84 |
// Check authentication token
|
|
|
|
| 133 |
});
|
| 134 |
wrapper.querySelectorAll('hr').forEach(h => h.classList.add('styled-hr'));
|
| 135 |
Prism.highlightAllUnder(wrapper);
|
| 136 |
+
// Smooth scroll to bottom
|
| 137 |
+
if (uiElements.chatBox) {
|
| 138 |
+
uiElements.chatBox.scrollTo({
|
| 139 |
+
top: uiElements.chatBox.scrollHeight,
|
| 140 |
+
behavior: 'smooth',
|
| 141 |
+
});
|
| 142 |
+
}
|
| 143 |
}
|
| 144 |
|
| 145 |
// Toggle chat view
|
|
|
|
| 175 |
if (uiElements.chatBox) {
|
| 176 |
uiElements.chatBox.appendChild(div);
|
| 177 |
uiElements.chatBox.classList.remove('hidden');
|
|
|
|
|
|
|
| 178 |
} else {
|
| 179 |
console.error('chatBox is null');
|
| 180 |
}
|
|
|
|
| 358 |
return response;
|
| 359 |
} catch (error) {
|
| 360 |
console.error('Send request error:', error);
|
| 361 |
+
if (error.name === 'AbortError') {
|
| 362 |
+
throw new Error('Request was aborted');
|
| 363 |
+
}
|
| 364 |
throw error;
|
| 365 |
}
|
| 366 |
}
|
|
|
|
| 553 |
console.error('Error creating conversation:', error);
|
| 554 |
alert('Failed to create new conversation. Please try again.');
|
| 555 |
}
|
| 556 |
+
if (uiElements.chatBox) uiElements.chatBox.scrollTo({
|
| 557 |
+
top: uiElements.chatBox.scrollHeight,
|
| 558 |
+
behavior: 'smooth',
|
| 559 |
+
});
|
| 560 |
}
|
| 561 |
|
| 562 |
// Update conversation title
|
|
|
|
| 615 |
if (!isSidebarOpen) return;
|
| 616 |
let translateX = Math.max(-uiElements.sidebar.offsetWidth, Math.min(0, e.deltaX));
|
| 617 |
uiElements.sidebar.style.transform = `translateX(${translateX}px)`;
|
| 618 |
+
uiElements.sidebar.style.transition = 'none';
|
| 619 |
});
|
| 620 |
hammer.on('panend', e => {
|
| 621 |
+
uiElements.sidebar.style.transition = 'transform 0.3s ease-in-out';
|
| 622 |
if (e.deltaX < -50) {
|
| 623 |
toggleSidebar(false);
|
| 624 |
} else {
|
|
|
|
| 757 |
currentAssistantText = buffer;
|
| 758 |
streamMsg.querySelector('.loading')?.remove();
|
| 759 |
renderMarkdown(streamMsg);
|
|
|
|
| 760 |
}
|
| 761 |
}
|
| 762 |
responseText = buffer;
|
|
|
|
| 774 |
await saveMessageToConversation(currentConversationId, 'assistant', responseText);
|
| 775 |
}
|
| 776 |
if (checkAuth()) {
|
| 777 |
+
await loadConversations();
|
| 778 |
}
|
| 779 |
finalizeRequest();
|
| 780 |
} catch (error) {
|
|
|
|
| 828 |
});
|
| 829 |
}
|
| 830 |
|
|
|
|
|
|
|
| 831 |
// Settings Modal
|
| 832 |
if (uiElements.settingsBtn) {
|
| 833 |
uiElements.settingsBtn.addEventListener('click', async () => {
|
|
|
|
| 1017 |
}
|
| 1018 |
|
| 1019 |
if (uiElements.input) {
|
| 1020 |
+
// Add debounce to input event
|
| 1021 |
+
let debounceTimer;
|
| 1022 |
+
uiElements.input.addEventListener('input', () => {
|
| 1023 |
+
clearTimeout(debounceTimer);
|
| 1024 |
+
debounceTimer = setTimeout(() => {
|
| 1025 |
+
autoResizeTextarea();
|
| 1026 |
+
updateSendButtonState();
|
| 1027 |
+
}, 100);
|
| 1028 |
+
});
|
| 1029 |
uiElements.input.addEventListener('keydown', (e) => {
|
| 1030 |
if (e.key === 'Enter' && !e.shiftKey) {
|
| 1031 |
e.preventDefault();
|
| 1032 |
if (!isRecording && !uiElements.sendBtn.disabled) submitMessage();
|
| 1033 |
}
|
| 1034 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1035 |
}
|
| 1036 |
|
| 1037 |
if (uiElements.stopBtn) {
|
|
|
|
| 1067 |
console.log('Removing from localStorage:', key);
|
| 1068 |
originalRemoveItem.apply(this, arguments);
|
| 1069 |
};
|
| 1070 |
+
|
| 1071 |
+
// Offline mode detection
|
| 1072 |
+
window.addEventListener('offline', () => {
|
| 1073 |
+
if (uiElements.messageLimitWarning) {
|
| 1074 |
+
uiElements.messageLimitWarning.classList.remove('hidden');
|
| 1075 |
+
uiElements.messageLimitWarning.textContent = 'You are offline. Some features may be limited.';
|
| 1076 |
+
}
|
| 1077 |
+
});
|
| 1078 |
+
|
| 1079 |
+
window.addEventListener('online', () => {
|
| 1080 |
+
if (uiElements.messageLimitWarning) {
|
| 1081 |
+
uiElements.messageLimitWarning.classList.add('hidden');
|
| 1082 |
+
}
|
| 1083 |
+
});
|