Spaces:
Running
Running
document.addEventListener('DOMContentLoaded', () => { | |
const convo = document.querySelector(".convo"); | |
const fileUpload = document.getElementById('file-upload'); | |
const imageUpload = document.getElementById('image-upload'); | |
const fileBtn = document.getElementById('file-btn'); | |
const imageBtn = document.getElementById('image-btn'); | |
const sendButtons = document.querySelectorAll('.sendingQA'); | |
const SummarizeInput = document.querySelector(".SummarizeInput"); | |
const CaptionInput = document.querySelector(".CaptionInput"); | |
let selectedFile = null; | |
let filePreviewBubble = null; | |
// Mode switching | |
document.querySelectorAll('.select-options input[name="mode"]').forEach(radio => { | |
radio.addEventListener('change', (e) => { | |
if (e.target.checked) { | |
const selectedValue = e.target.value; | |
if (selectedValue === "Summarize") { | |
SummarizeInput.classList.add("active"); | |
SummarizeInput.classList.remove("innactive"); | |
CaptionInput.classList.remove("active"); | |
CaptionInput.classList.add("innactive"); | |
} else { | |
SummarizeInput.classList.add("innactive"); | |
SummarizeInput.classList.remove("active"); | |
CaptionInput.classList.remove("innactive"); | |
CaptionInput.classList.add("active"); | |
} | |
} | |
}); | |
}); | |
// File upload handlers | |
fileBtn.addEventListener('click', () => fileUpload.click()); | |
imageBtn.addEventListener('click', () => imageUpload.click()); | |
fileUpload.addEventListener('change', (e) => { | |
if (e.target.files.length) { | |
selectedFile = e.target.files[0]; | |
displayFilePreview(selectedFile); | |
} | |
}); | |
imageUpload.addEventListener('change', (e) => { | |
if (e.target.files.length) { | |
selectedFile = e.target.files[0]; | |
displayFilePreview(selectedFile); | |
} | |
}); | |
// Drag and drop | |
convo.addEventListener('dragover', (e) => { | |
e.preventDefault(); | |
convo.classList.add('drag-over'); | |
}); | |
convo.addEventListener('dragleave', () => { | |
convo.classList.remove('drag-over'); | |
}); | |
convo.addEventListener('drop', (e) => { | |
e.preventDefault(); | |
convo.classList.remove('drag-over'); | |
if (e.dataTransfer.files.length) { | |
const file = e.dataTransfer.files[0]; | |
const dataTransfer = new DataTransfer(); | |
dataTransfer.items.add(file); | |
const isSummarizeMode = document.querySelector('input[name="mode"]:checked').value === 'Summarize'; | |
if (isSummarizeMode) { | |
fileUpload.files = dataTransfer.files; | |
} else { | |
imageUpload.files = dataTransfer.files; | |
} | |
selectedFile = file; | |
displayFilePreview(file); | |
} | |
}); | |
// Send button handlers | |
sendButtons.forEach(button => { | |
button.addEventListener('click', handleSubmit); | |
}); | |
function displayFilePreview(file) { | |
if (filePreviewBubble) filePreviewBubble.remove(); | |
filePreviewBubble = createMessageBubble( | |
`๐ Selected ${file.type.startsWith('image/') ? 'image' : 'document'}: ${file.name}`, | |
"You" | |
); | |
} | |
function createMessageBubble(text, sender = "You", audioSrc = null) { | |
const bubble = document.createElement('div'); | |
bubble.className = `bubble ${sender === "You" ? "right" : "left"}`; | |
const label = document.createElement('div'); | |
label.className = "label"; | |
label.textContent = sender; | |
const message = document.createElement('div'); | |
message.className = "text"; | |
if (sender === "You") { | |
message.textContent = text; | |
} else { | |
message.innerHTML = typeof text === 'string' ? text : 'Processing...'; | |
if (audioSrc) { | |
const audioContainer = document.createElement('div'); | |
audioContainer.style.display = 'flex'; | |
audioContainer.style.alignItems = 'center'; | |
audioContainer.style.gap = '10px'; | |
audioContainer.style.marginTop = '8px'; | |
const audio = new Audio(audioSrc); | |
const audioIcon = document.createElement('i'); | |
audioIcon.className = 'fa-solid fa-volume-high audio-toggle'; | |
audioIcon.style.cursor = 'pointer'; | |
audioIcon.addEventListener('click', () => { | |
if (audio.paused) { | |
audio.play(); | |
audioIcon.classList.replace('fa-volume-xmark', 'fa-volume-high'); | |
audioIcon.title = "Click to mute"; | |
} else { | |
audio.pause(); | |
audioIcon.classList.replace('fa-volume-high', 'fa-volume-xmark'); | |
audioIcon.title = "Click to unmute"; | |
} | |
}); | |
audioContainer.appendChild(audioIcon); | |
audioContainer.appendChild(document.createTextNode('Listen')); | |
message.appendChild(audioContainer); | |
} | |
} | |
bubble.appendChild(label); | |
bubble.appendChild(message); | |
convo.appendChild(bubble); | |
convo.scrollTop = convo.scrollHeight; | |
return bubble; | |
} | |
async function handleSubmit() { | |
if (!selectedFile) { | |
alert("Please upload a file first"); | |
return; | |
} | |
const isSummarizeMode = document.querySelector('input[name="mode"]:checked').value === 'Summarize'; | |
const endpoint = isSummarizeMode ? '/summarize/' : '/imagecaption/'; | |
const thinkingText = isSummarizeMode ? 'Processing document...' : "Generating caption... <div class='loader'></div>"; | |
const senderName = isSummarizeMode ? 'Assistant' : 'Aidan'; | |
const thinkingBubble = createMessageBubble(thinkingText, senderName); | |
const formData = new FormData(); | |
formData.append('file', selectedFile); | |
if (isSummarizeMode) formData.append('length', 'medium'); | |
try { | |
const response = await fetch(endpoint, { | |
method: 'POST', | |
body: formData | |
}); | |
if (!response.ok) { | |
const error = await response.json(); | |
throw new Error(error.detail || 'Request failed'); | |
} | |
const result = await response.json(); | |
thinkingBubble.remove(); | |
if (isSummarizeMode) { | |
createMessageBubble(result.summary || "No summary generated.", "Assistant"); | |
if (result.audioUrl) { | |
const audio = document.createElement('audio'); | |
audio.src = result.audioUrl; | |
audio.controls = true; | |
convo.appendChild(audio); | |
} | |
if (result.pdfUrl) { | |
const link = document.createElement('a'); | |
link.href = result.pdfUrl; | |
link.textContent = 'Download Summary PDF'; | |
link.className = 'download-link'; | |
link.target = "_blank"; | |
convo.appendChild(link); | |
} | |
} else { | |
createMessageBubble( | |
`<strong>Caption:</strong><br><br>${result.answer || result.caption} | |
${result.audio ? `<br><audio controls src="${result.audio}"></audio>` : ''}`, | |
"Aidan", | |
result.audio | |
); | |
} | |
} catch (error) { | |
thinkingBubble.remove(); | |
createMessageBubble(`โ ๏ธ Error: ${error.message}`, senderName); | |
} finally { | |
resetFileInputs(); | |
} | |
} | |
function resetFileInputs() { | |
selectedFile = null; | |
fileUpload.value = ''; | |
imageUpload.value = ''; | |
if (filePreviewBubble) { | |
filePreviewBubble.remove(); | |
filePreviewBubble = null; | |
} | |
} | |
// Loader CSS | |
const style = document.createElement('style'); | |
style.textContent = ` | |
.loader { | |
display: inline-block; | |
border: 2px solid #f3f3f3; | |
border-top: 2px solid #3b82f6; | |
border-radius: 50%; | |
width: 16px; | |
height: 16px; | |
animation: spin 1s linear infinite; | |
} | |
@keyframes spin { | |
0% { transform: rotate(0deg); } | |
100% { transform: rotate(360deg); } | |
} | |
.download-link { | |
display: inline-block; | |
margin-top: 10px; | |
padding: 5px 10px; | |
background: #3b82f6; | |
color: white; | |
border-radius: 5px; | |
text-decoration: none; | |
} | |
.download-link:hover { | |
background: #2563eb; | |
} | |
.audio-toggle { | |
cursor: pointer; | |
transition: all 0.2s; | |
} | |
`; | |
document.head.appendChild(style); | |
}); | |