EasyBot / static /script.js
NitinBot001's picture
Upload 10 files
f374654 verified
raw
history blame
11 kB
document.addEventListener('DOMContentLoaded', () => {
// --- DOM Elements ---
const chatArea = document.getElementById('chat-area');
const closeSidebarBtn = document.getElementById('close-sidebar-btn');
const messageInput = document.getElementById('message-input');
const sendBtn = document.getElementById('send-btn');
const newChatBtn = document.getElementById('new-chat-btn');
const chatMessages = document.getElementById('chat-messages');
const chatHistoryList = document.getElementById('chat-history-list');
const menuToggle = document.getElementById('menu-toggle');
const appContainer = document.getElementById('app-container');
const chatTitle = document.getElementById('chat-title');
const imageUploadBtn = document.getElementById('image-upload-btn');
const imageUploadInput = document.getElementById('image-upload-input');
const imagePreviewContainer = document.getElementById('image-preview-container');
const imagePreview = document.getElementById('image-preview');
const removeImageBtn = document.getElementById('remove-image-btn');
// --- State ---
let currentSessionId = null;
let conversationsCache = {};
let selectedImageFile = null;
let imgbbApiKey = '';
// --- Initialization ---
const init = async () => {
if (!messageInput || !sendBtn || !imageUploadBtn || !imagePreviewContainer) {
console.error("Critical UI elements not found. Check HTML IDs.");
return;
}
await fetchConfig();
loadCache();
await renderChatHistoryFromAPI();
// Event Listeners
sendBtn.addEventListener('click', sendMessage);
messageInput.addEventListener('keydown', e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); } });
imageUploadBtn.addEventListener('click', () => imageUploadInput.click());
imageUploadInput.addEventListener('change', handleImageSelect);
removeImageBtn.addEventListener('click', removeSelectedImage);
// Sidebar Listeners
newChatBtn.addEventListener('click', () => { startNewChat(); closeSidebar(); });
menuToggle.addEventListener('click', (event) => {
event.stopPropagation();
appContainer.classList.toggle('sidebar-visible');
});
closeSidebarBtn.addEventListener('click', (event) => {
event.stopPropagation();
closeSidebar();
});
chatArea.addEventListener('click', () => {
if (appContainer.classList.contains('sidebar-visible')) {
closeSidebar();
}
});
};
const fetchConfig = async () => {
try {
const response = await fetch('/config');
const config = await response.json();
imgbbApiKey = config.imgbb_api_key;
if (!imgbbApiKey) { console.error("ImgBB API Key is missing."); }
} catch (error) { console.error('Failed to fetch config:', error); }
};
// --- Core Chat Functions ---
const sendMessage = async () => {
const messageText = messageInput.value.trim();
if (!messageText && !selectedImageFile) return;
displayMessage({ role: 'user', content: messageText, imageUrl: selectedImageFile });
const loadingIndicator = displayMessage({ role: 'assistant', content: 'Thinking...', isLoading: true });
try {
let permanentImageUrl = null;
if (selectedImageFile) { permanentImageUrl = await uploadImageToImgBB(selectedImageFile); }
const formData = new FormData();
formData.append('message', messageText);
formData.append('session_id', currentSessionId);
if (permanentImageUrl) { formData.append('image_url', permanentImageUrl); }
const response = await fetch('/chat', { method: 'POST', body: formData });
if (!response.ok) throw new Error('Network response was not ok.');
const data = await response.json();
chatMessages.removeChild(loadingIndicator);
displayMessage({ role: 'assistant', content: data.response });
updateCache(data.session_id, { content: messageText, imageUrl: permanentImageUrl }, { content: data.response });
} catch (error) {
console.error('Error sending message:', error);
loadingIndicator.innerHTML = marked.parse("Sorry, something went wrong.");
loadingIndicator.classList.remove('loading');
} finally {
messageInput.value = ''; messageInput.style.height = 'auto'; removeSelectedImage();
}
};
const uploadImageToImgBB = async (imageFile) => {
if (!imgbbApiKey) throw new Error("ImgBB API Key not configured.");
const formData = new FormData();
formData.append('image', imageFile);
formData.append('key', imgbbApiKey);
const response = await fetch('https://api.imgbb.com/1/upload', { method: 'POST', body: formData });
const result = await response.json();
if (result.success) { return result.data.url; }
else { throw new Error(result.error.message || 'Image upload failed.'); }
};
// --- Caching and State Management ---
const startNewChat = () => {
currentSessionId = null;
chatMessages.innerHTML = `<div class="welcome-message"><h1>EasyFarms Assistant</h1></div>`;
chatTitle.textContent = "New Chat";
updateActiveChatItem();
};
const switchChat = async (sessionId) => {
currentSessionId = sessionId;
chatMessages.innerHTML = '';
if (conversationsCache[sessionId] && conversationsCache[sessionId].messages) {
conversationsCache[sessionId].messages.forEach(displayMessage);
} else {
const loading = displayMessage({ role: 'assistant', content: 'Loading chat history...', isLoading: true });
try {
const response = await fetch(`/history/messages/${sessionId}`);
const messages = await response.json();
if (!conversationsCache[sessionId]) conversationsCache[sessionId] = {};
conversationsCache[sessionId].messages = messages;
saveCache();
chatMessages.removeChild(loading);
messages.forEach(displayMessage);
} catch (error) {
loading.innerHTML = marked.parse("Failed to load chat history.");
}
}
chatTitle.textContent = conversationsCache[sessionId]?.title || "Chat";
updateActiveChatItem();
closeSidebar();
};
const updateCache = (sessionId, userTurn, assistantTurn) => {
const isNewChat = !currentSessionId;
currentSessionId = sessionId;
if (isNewChat) {
const title = (userTurn.content || "Image Query").substring(0, 30) + '...';
conversationsCache[sessionId] = { title, messages: [] };
const item = document.createElement('div');
item.className = 'chat-history-item';
item.textContent = title;
item.dataset.sessionId = sessionId;
item.addEventListener('click', () => switchChat(sessionId));
chatHistoryList.prepend(item);
}
const userMessage = { role: 'user', content: userTurn.content };
if (userTurn.imageUrl) userMessage.imageUrl = userTurn.imageUrl;
const assistantMessage = { role: 'assistant', content: assistantTurn.content };
conversationsCache[sessionId].messages.push(userMessage, assistantMessage);
saveCache();
updateActiveChatItem();
};
const displayMessage = (message) => {
const { role, content, imageUrl, isLoading } = message;
const sender = role || message.sender;
const messageDiv = document.createElement('div');
messageDiv.classList.add('message', `${sender}-message`);
let htmlContent = '';
const imageSrc = (typeof imageUrl === 'object' && imageUrl instanceof File) ? URL.createObjectURL(imageUrl) : imageUrl;
if (imageSrc) { htmlContent += `<img src="${imageSrc}" alt="User upload" class="user-upload">`; }
if (content) { htmlContent += marked.parse(content); }
messageDiv.innerHTML = htmlContent || (isLoading ? '...' : '');
if (isLoading) messageDiv.classList.add('loading');
chatMessages.appendChild(messageDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
return messageDiv;
};
// --- Image Preview Handling ---
const handleImageSelect = (event) => {
const file = event.target.files[0];
if (file) {
selectedImageFile = file;
imagePreview.src = URL.createObjectURL(file);
imagePreviewContainer.style.display = 'block';
}
};
const removeSelectedImage = () => {
selectedImageFile = null;
imageUploadInput.value = '';
imagePreviewContainer.style.display = 'none';
imagePreview.src = '#';
};
// --- LocalStorage Cache & Sidebar Rendering ---
const saveCache = () => localStorage.setItem('easyfarms_cache', JSON.stringify(conversationsCache));
const loadCache = () => {
const saved = localStorage.getItem('easyfarms_cache');
if (saved) conversationsCache = JSON.parse(saved);
};
const renderChatHistoryFromAPI = async () => {
try {
const response = await fetch('/history/sessions');
const sessions = await response.json();
chatHistoryList.innerHTML = '';
sessions.reverse().forEach(session => {
if (!conversationsCache[session.session_id]) conversationsCache[session.session_id] = {};
conversationsCache[session.session_id].title = session.title;
const item = document.createElement('div');
item.className = 'chat-history-item';
item.textContent = session.title;
item.dataset.sessionId = session.session_id;
item.addEventListener('click', () => switchChat(session.session_id));
chatHistoryList.appendChild(item);
});
saveCache();
updateActiveChatItem();
} catch (error) { console.error("Failed to render chat history from API:", error); }
};
const updateActiveChatItem = () => {
document.querySelectorAll('.chat-history-item').forEach(item => {
item.classList.toggle('active', item.dataset.sessionId === currentSessionId);
});
};
const closeSidebar = () => appContainer.classList.remove('sidebar-visible');
// --- Start the Application ---
init();
});