Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Simple Image Gallery</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<!-- Firebase SDK --> | |
<script src="https://www.gstatic.com/firebasejs/9.6.0/firebase-app-compat.js"></script> | |
<script src="https://www.gstatic.com/firebasejs/9.6.0/firebase-storage-compat.js"></script> | |
<style> | |
.gallery-item { | |
transition: all 0.3s ease; | |
} | |
.gallery-item:hover { | |
transform: scale(1.02); | |
} | |
#drop-area { | |
border: 2px dashed #ccc; | |
transition: all 0.3s; | |
} | |
#drop-area.highlight { | |
border-color: #6b46c1; | |
background-color: #f5f3ff; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-100 min-h-screen"> | |
<div class="container mx-auto px-4 py-8"> | |
<h1 class="text-3xl font-bold text-center mb-8 text-purple-700">Simple Image Gallery</h1> | |
<!-- Upload Section --> | |
<div class="bg-white rounded-lg shadow-md p-6 mb-8"> | |
<h2 class="text-xl font-semibold mb-4">Upload Images</h2> | |
<div id="drop-area" class="rounded-lg p-8 text-center mb-4"> | |
<p class="mb-4">Drag & drop images here or</p> | |
<input type="file" id="fileElem" multiple accept="image/*" class="hidden"> | |
<button id="browseBtn" class="bg-purple-600 text-white px-4 py-2 rounded hover:bg-purple-700"> | |
Browse Files | |
</button> | |
</div> | |
<div class="progress-container hidden"> | |
<div class="w-full bg-gray-200 rounded-full h-2.5"> | |
<div id="progress-bar" class="bg-purple-600 h-2.5 rounded-full" style="width: 0%"></div> | |
</div> | |
<p id="progress-text" class="text-sm text-gray-600 mt-1">Uploading: 0%</p> | |
</div> | |
</div> | |
<!-- Gallery Grid --> | |
<div id="gallery-grid" class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"> | |
<!-- Images will be loaded here --> | |
</div> | |
</div> | |
<script> | |
// Firebase configuration | |
const firebaseConfig = { | |
apiKey: "AIzaSyD3JgJvV8X9X9X9X9X9X9X9X9X9X9X9X9X9X9", | |
authDomain: "your-project-id.firebaseapp.com", | |
projectId: "your-project-id", | |
storageBucket: "your-project-id.appspot.com", | |
messagingSenderId: "123456789012", | |
appId: "1:123456789012:web:9X9X9X9X9X9X9X9X9X9X9" | |
}; | |
// Initialize Firebase | |
firebase.initializeApp(firebaseConfig); | |
const storage = firebase.storage(); | |
// DOM elements | |
const dropArea = document.getElementById('drop-area'); | |
const fileElem = document.getElementById('fileElem'); | |
const browseBtn = document.getElementById('browseBtn'); | |
const galleryGrid = document.getElementById('gallery-grid'); | |
const progressContainer = document.querySelector('.progress-container'); | |
const progressBar = document.getElementById('progress-bar'); | |
const progressText = document.getElementById('progress-text'); | |
// Load existing images when page loads | |
window.addEventListener('load', loadImages); | |
// Prevent default drag behaviors | |
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
dropArea.addEventListener(eventName, preventDefaults, false); | |
}); | |
function preventDefaults(e) { | |
e.preventDefault(); | |
e.stopPropagation(); | |
} | |
// Highlight drop area when item is dragged over it | |
['dragenter', 'dragover'].forEach(eventName => { | |
dropArea.addEventListener(eventName, highlight, false); | |
}); | |
['dragleave', 'drop'].forEach(eventName => { | |
dropArea.addEventListener(eventName, unhighlight, false); | |
}); | |
function highlight() { | |
dropArea.classList.add('highlight'); | |
} | |
function unhighlight() { | |
dropArea.classList.remove('highlight'); | |
} | |
// Handle dropped files | |
dropArea.addEventListener('drop', handleDrop, false); | |
function handleDrop(e) { | |
const dt = e.dataTransfer; | |
const files = dt.files; | |
handleFiles(files); | |
} | |
// Browse button click | |
browseBtn.addEventListener('click', () => { | |
fileElem.click(); | |
}); | |
// Handle selected files | |
fileElem.addEventListener('change', function() { | |
handleFiles(this.files); | |
}); | |
// Load existing images from Firebase Storage | |
async function loadImages() { | |
try { | |
const storageRef = storage.ref(); | |
const result = await storageRef.listAll(); | |
result.items.forEach(async (itemRef) => { | |
const url = await itemRef.getDownloadURL(); | |
addImageToGallery(url, new Date().toLocaleString()); | |
}); | |
} catch (error) { | |
console.error("Error loading images:", error); | |
} | |
} | |
// Process files and upload to Firebase | |
function handleFiles(files) { | |
if (files.length === 0) return; | |
progressContainer.classList.remove('hidden'); | |
for (let i = 0; i < files.length; i++) { | |
const file = files[i]; | |
if (!file.type.match('image.*')) continue; | |
// Create unique filename | |
const filename = Date.now() + '_' + file.name; | |
const storageRef = storage.ref().child(filename); | |
const uploadTask = storageRef.put(file); | |
uploadTask.on('state_changed', | |
(snapshot) => { | |
// Progress tracking | |
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; | |
progressBar.style.width = `${progress}%`; | |
progressText.textContent = `Uploading: ${Math.round(progress)}%`; | |
}, | |
(error) => { | |
console.error("Upload error:", error); | |
progressContainer.classList.add('hidden'); | |
}, | |
() => { | |
// Upload complete | |
uploadTask.snapshot.ref.getDownloadURL().then((downloadURL) => { | |
progressContainer.classList.add('hidden'); | |
progressBar.style.width = '0%'; | |
progressText.textContent = 'Uploading: 0%'; | |
// Add to gallery | |
addImageToGallery(downloadURL, new Date().toLocaleString()); | |
}); | |
} | |
); | |
} | |
} | |
// Add image to gallery | |
function addImageToGallery(url, timestamp) { | |
const galleryItem = document.createElement('div'); | |
galleryItem.className = 'gallery-item bg-white rounded-lg overflow-hidden shadow'; | |
galleryItem.innerHTML = ` | |
<img src="${url}" alt="Gallery image" class="w-full h-48 object-cover"> | |
<div class="p-3"> | |
<p class="text-sm text-gray-600">Uploaded: ${timestamp}</p> | |
</div> | |
`; | |
galleryGrid.insertBefore(galleryItem, galleryGrid.firstChild); | |
} | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=vorstcavry/simple-galery" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |