Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Screenshot Gallery</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <style> | |
| /* Ensure html and body take full height */ | |
| html, body { | |
| height: 100%; | |
| margin: 0; | |
| padding: 0; | |
| background-color: #1a202c; /* Dark background */ | |
| } | |
| /* Ensure the grid container takes full height */ | |
| #screenshot-grid { | |
| min-height: calc(100vh - 80px); | |
| } | |
| /* Style for individual grid items */ | |
| .grid-item { | |
| border-radius: 12px; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .grid-item:hover { | |
| filter: brightness(1.2); | |
| } | |
| .preview-modal { | |
| position: fixed; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 90vw; | |
| height: 90vh; | |
| background: #1a202c; | |
| z-index: 1000; | |
| border-radius: 12px; | |
| box-shadow: 0 0 20px rgba(0,0,0,0.5); | |
| display: none; | |
| flex-direction: column; | |
| overflow: hidden; | |
| } | |
| .modal-header { | |
| padding: 1rem; | |
| background: #2d3748; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| border-bottom: 1px solid #4a5568; | |
| } | |
| .modal-content { | |
| flex: 1; | |
| position: relative; | |
| overflow: hidden; | |
| background: #1a202c; | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| .modal-content iframe { | |
| width: 100%; | |
| height: 100%; | |
| border: none; | |
| } | |
| .preview-image { | |
| max-width: 95%; | |
| max-height: 95%; | |
| object-fit: contain; | |
| border-radius: 8px; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| } | |
| .loading-message { | |
| color: #fff; | |
| text-align: center; | |
| font-size: 1.2em; | |
| } | |
| .modal-overlay { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: rgba(0,0,0,0.75); | |
| z-index: 999; | |
| display: none; | |
| } | |
| .preview-controls { | |
| position: absolute; | |
| top: 1rem; | |
| right: 1rem; | |
| display: flex; | |
| gap: 0.5rem; | |
| z-index: 1001; | |
| } | |
| .preview-button { | |
| padding: 0.5rem 1rem; | |
| border-radius: 0.375rem; | |
| background: #3182ce; | |
| color: white; | |
| text-decoration: none; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| font-size: 0.875rem; | |
| transition: background-color 0.2s; | |
| } | |
| .preview-button:hover { | |
| background: #2c5282; | |
| } | |
| .footer-reference { | |
| position: fixed; | |
| bottom: 10px; | |
| left: 10px; | |
| z-index: 1000; | |
| font-size: 14px; | |
| color: white; | |
| text-decoration: none; | |
| display: flex; | |
| align-items: center; | |
| gap: 4px; | |
| background-color: rgba(0, 0, 0, 0.5); | |
| padding: 4px 8px; | |
| border-radius: 4px; | |
| } | |
| .footer-reference:hover { | |
| background-color: rgba(0, 0, 0, 0.7); | |
| } | |
| .error-message { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| text-align: center; | |
| color: #666; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-900 text-gray-100"> | |
| <header class="p-4 flex justify-between items-center border-b border-gray-700"> | |
| <h1 class="text-2xl font-bold"><span class="font-normal">Made with</span> IAsite</h1> | |
| <p class="max-sm:text-xs max-sm:w-40">⚠️ Do not share personal information. User-submitted apps may contain malicious code.</p> | |
| <a href="https://huggingface.co/spaces/luandutra021/IAsites" target="_blank" rel="noopener noreferrer" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> | |
| Open IAsite | |
| </a> | |
| </header> | |
| <div id="screenshot-grid" class="grid grid-cols-2 sm:grid-cols-3 2xl:grid-cols-4 gap-2 p-4"> | |
| <!-- Screenshots will be loaded here --> | |
| </div> | |
| <a href="https://huggingface.co/spaces/luandutra021/IAsites" class="footer-reference" target="_blank" rel="noopener noreferrer"> | |
| Made with IAsite - 🔄 Remix | |
| </a> | |
| <div class="modal-overlay" id="modalOverlay"></div> | |
| <div class="preview-modal" id="previewModal"> | |
| <div class="modal-header"> | |
| <button class="bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded" onclick="closePreview()">Fechar</button> | |
| <a id="remixButton" class="preview-button" target="_blank"> | |
| 🔄 Remix no IAsite | |
| </a> | |
| </div> | |
| <div class="modal-content"> | |
| <img id="previewImage" class="preview-image" alt="Preview" style="display: none"> | |
| <div id="loadingMessage" class="loading-message">Carregando...</div> | |
| </div> | |
| </div> | |
| <script> | |
| const modal = document.getElementById('previewModal'); | |
| const overlay = document.getElementById('modalOverlay'); | |
| const previewImage = document.getElementById('previewImage'); | |
| const loadingMessage = document.getElementById('loadingMessage'); | |
| const remixBtn = document.getElementById('remixButton'); | |
| function openPreview(screenshotUrl, remixUrl) { | |
| modal.style.display = 'flex'; | |
| overlay.style.display = 'block'; | |
| loadingMessage.style.display = 'block'; | |
| previewImage.style.display = 'none'; | |
| // Carregar a imagem | |
| previewImage.src = screenshotUrl; | |
| previewImage.onload = () => { | |
| loadingMessage.style.display = 'none'; | |
| previewImage.style.display = 'block'; | |
| }; | |
| remixBtn.href = remixUrl; | |
| document.body.style.overflow = 'hidden'; | |
| } | |
| function closePreview() { | |
| modal.style.display = 'none'; | |
| overlay.style.display = 'none'; | |
| previewImage.src = ''; | |
| document.body.style.overflow = ''; | |
| } | |
| overlay.addEventListener('click', closePreview); | |
| async function loadScreenshots() { | |
| try { | |
| const response = await fetch('screenshots.json'); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const screenshotsData = await response.json(); | |
| const grid = document.getElementById('screenshot-grid'); | |
| grid.innerHTML = ''; | |
| const fragment = document.createDocumentFragment(); | |
| if (!Array.isArray(screenshotsData)) { | |
| throw new Error("screenshots.json is not a valid array."); | |
| } | |
| screenshotsData.forEach(item => { | |
| if (!item || typeof item.filename !== 'string' || !item.filename.endsWith('.png')) { | |
| console.warn("Skipping invalid item in screenshots.json:", item); | |
| return; | |
| } | |
| if (typeof item.rating !== 'number' || item.rating < 50) { | |
| return; | |
| } | |
| const filename = item.filename; | |
| const gridItem = document.createElement('div'); | |
| gridItem.className = 'grid-item relative'; | |
| const img = document.createElement('img'); | |
| img.src = `screenshots/${filename}`; | |
| img.alt = `Screenshot of ${filename.replace(/^space-|-/g, ' ').replace('.png', '')}`; | |
| img.loading = 'lazy'; | |
| img.decoding = 'async'; | |
| img.className = 'w-full h-auto object-cover rounded-lg shadow-md'; | |
| try { | |
| const namePart = filename.replace(/^space-/, '').replace(/\.png$/, ''); | |
| const parts = namePart.split(/-(.+)/); | |
| if (parts.length >= 2 && parts[0] && parts[1]) { | |
| const username = parts[0]; | |
| const spacename = parts[1]; | |
| const screenshotUrl = `screenshots/${filename}`; | |
| const remixUrl = `https://huggingface.co/spaces/luandutra021/IAsites/?remix=${encodeURIComponent(username)}/${encodeURIComponent(spacename)}`; | |
| gridItem.onclick = () => { | |
| openPreview(screenshotUrl, remixUrl); | |
| }; | |
| gridItem.style.cursor = 'pointer'; | |
| const footer = document.createElement('div'); | |
| footer.className = 'absolute bottom-2 left-2 flex items-center gap-2 bg-black bg-opacity-50 p-2 rounded text-xs text-white'; | |
| const madeWith = document.createElement('span'); | |
| madeWith.textContent = 'Made with IAsite'; | |
| const separator = document.createTextNode(' - '); | |
| const remix = document.createElement('a'); | |
| remix.href = remixUrl; | |
| remix.className = 'hover:text-blue-400 flex items-center gap-1'; | |
| remix.target = '_blank'; | |
| remix.rel = 'noopener noreferrer'; | |
| remix.innerHTML = '🔄 Remix'; | |
| remix.onclick = (e) => e.stopPropagation(); | |
| footer.appendChild(madeWith); | |
| footer.appendChild(separator); | |
| footer.appendChild(remix); | |
| gridItem.appendChild(footer); | |
| } | |
| } catch (e) { | |
| console.error(`Error parsing filename: ${filename}`, e); | |
| } | |
| gridItem.appendChild(img); | |
| fragment.appendChild(gridItem); | |
| }); | |
| grid.appendChild(fragment); | |
| } catch (error) { | |
| console.error('Failed to load screenshots:', error); | |
| const grid = document.getElementById('screenshot-grid'); | |
| grid.innerHTML = '<p class="text-red-500 text-center col-span-3">Failed to load screenshots. Check console for details.</p>'; | |
| } | |
| } | |
| document.addEventListener('DOMContentLoaded', loadScreenshots); | |
| </script> | |
| </body> | |
| </html> | |