Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>Upload Images for Generative AI</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <!-- Marked library to render markdown results --> | |
| <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
| </head> | |
| <body class="bg-gray-100"> | |
| <div class="container mx-auto p-4"> | |
| <h1 class="text-3xl font-bold text-center mb-6">Upload Images</h1> | |
| <div class="flex flex-col items-center"> | |
| <!-- Upload/Paste Area --> | |
| <div id="upload-area" class="border-2 border-dashed border-gray-400 p-8 rounded w-full sm:w-11/12 md:w-3/4 lg:w-1/2 bg-white"> | |
| <p class="mb-4 text-center"> | |
| Paste images with <strong>Ctrl + V</strong> or click "Add Image". | |
| </p> | |
| <input type="file" id="fileInput" name="files" accept="image/*" multiple class="hidden" /> | |
| <button id="addImageBtn" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mb-4"> | |
| Add Image | |
| </button> | |
| <!-- Thumbnails container --> | |
| <div id="thumbnails" class="flex flex-wrap gap-4"></div> | |
| </div> | |
| <!-- Send Button --> | |
| <div class="mt-6"> | |
| <button id="sendBtn" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded"> | |
| Send | |
| </button> | |
| </div> | |
| <!-- Result Display --> | |
| <div id="resultArea" class="mt-6 w-full sm:w-11/12 md:w-3/4 lg:w-1/2 overflow-x-auto"></div> | |
| </div> | |
| </div> | |
| <!-- Popup Card for First Time --> | |
| <div id="popupCard" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"> | |
| <div class="bg-white rounded-lg p-6 w-11/12 sm:max-w-md mx-auto shadow-2xl transform transition-all duration-300"> | |
| <div class="mb-4"> | |
| <h2 class="text-2xl font-bold">π Hey, I'm Aditya Devarshi</h2> | |
| <p class="mt-2 text-gray-700">I'm an AI Engineer π€, here to help with your assignments π, support multiple images π·, and provide keyboard shortcuts β¨οΈ.</p> | |
| <p class="mt-2 text-gray-700">Connect with me:</p> | |
| <ul class="list-disc list-inside mt-2 text-blue-600"> | |
| <li><a href="https://www.adityadevarshi.online/" target="_blank">π Website</a></li> | |
| <li><a href="https://www.linkedin.com/in/aditya-devarshi/" target="_blank">π LinkedIn</a></li> | |
| <li><a href="https://github.com/devarshiadi" target="_blank">π GitHub</a></li> | |
| <li><a href="https://medium.com/@devarshia5" target="_blank">βοΈ Medium</a></li> | |
| </ul> | |
| </div> | |
| <div class="text-right"> | |
| <button id="closePopup" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> | |
| Close | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| const fileInput = document.getElementById('fileInput'); | |
| const addImageBtn = document.getElementById('addImageBtn'); | |
| const thumbnails = document.getElementById('thumbnails'); | |
| const sendBtn = document.getElementById('sendBtn'); | |
| const resultArea = document.getElementById('resultArea'); | |
| // Array to hold selected image files. | |
| let selectedFiles = []; | |
| // Trigger file input when Add Image button is clicked. | |
| addImageBtn.addEventListener('click', () => { | |
| fileInput.click(); | |
| }); | |
| // Handle file selection. | |
| fileInput.addEventListener('change', () => { | |
| for (let file of fileInput.files) { | |
| selectedFiles.push(file); | |
| addThumbnail(file); | |
| } | |
| fileInput.value = ""; // reset input | |
| }); | |
| // Function to add image thumbnail. | |
| function addThumbnail(file) { | |
| const reader = new FileReader(); | |
| reader.onload = function(e) { | |
| const thumbContainer = document.createElement('div'); | |
| thumbContainer.classList.add('relative'); | |
| thumbContainer.innerHTML = ` | |
| <img src="${e.target.result}" alt="${file.name}" class="w-24 h-24 object-cover rounded border" /> | |
| <button class="removeBtn absolute -top-2 -right-2 bg-red-500 text-white rounded-full px-1 text-xs">x</button> | |
| `; | |
| thumbnails.appendChild(thumbContainer); | |
| // Remove image on click. | |
| thumbContainer.querySelector('.removeBtn').addEventListener('click', () => { | |
| selectedFiles = selectedFiles.filter(f => f !== file); | |
| thumbContainer.remove(); | |
| }); | |
| } | |
| reader.readAsDataURL(file); | |
| } | |
| // Listen for paste events (Ctrl+V) to add images. | |
| window.addEventListener('paste', (event) => { | |
| const items = event.clipboardData.items; | |
| for (let item of items) { | |
| if (item.type.indexOf("image") !== -1) { | |
| const file = item.getAsFile(); | |
| selectedFiles.push(file); | |
| addThumbnail(file); | |
| } | |
| } | |
| }); | |
| // Handle Send button click. | |
| sendBtn.addEventListener('click', async () => { | |
| if (selectedFiles.length === 0) { | |
| alert("Please add at least one image."); | |
| return; | |
| } | |
| const formData = new FormData(); | |
| selectedFiles.forEach(file => { | |
| formData.append('files', file); | |
| }); | |
| resultArea.innerHTML = `<p class="text-gray-500">Processing...</p>`; | |
| try { | |
| const response = await fetch('/upload', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const data = await response.json(); | |
| if (response.ok && data.result) { | |
| // Convert markdown result to HTML using marked.parse | |
| resultArea.innerHTML = `<div class="bg-gray-200 p-4 rounded whitespace-pre-wrap">${marked.parse(data.result)}</div>`; | |
| // Reset the UI. | |
| selectedFiles = []; | |
| thumbnails.innerHTML = ""; | |
| } else { | |
| resultArea.innerHTML = `<p class="text-red-500">${data.detail || 'No result received.'}</p>`; | |
| } | |
| } catch (error) { | |
| resultArea.innerHTML = `<p class="text-red-500">Error processing the images: ${error.message}</p>`; | |
| } | |
| }); | |
| // Show popup only if it hasn't been shown before | |
| if (!localStorage.getItem('popupShown')) { | |
| document.getElementById('popupCard').style.display = 'flex'; | |
| } else { | |
| document.getElementById('popupCard').style.display = 'none'; | |
| } | |
| document.getElementById('closePopup').addEventListener('click', function() { | |
| document.getElementById('popupCard').style.display = 'none'; | |
| localStorage.setItem('popupShown', 'true'); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |