Download index.html from PierreH/test: direct link, hf CLI and curl.
- Browser
- Download file 26.4 kB
-
https://huggingface.co/spaces/PierreH/test/resolve/main/index.html
- Command line
-
hf download hf://spaces/PierreH/test/index.html
-
curl -L -o index.html https://huggingface.co/spaces/PierreH/test/resolve/main/index.html
26.4 kB
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>HypnoMap Live</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .map-container { | |
| background-image: url('https://maps.googleapis.com/maps/api/staticmap?center=48.8566,2.3522&zoom=13&size=800x600&scale=2'); | |
| background-size: cover; | |
| background-position: center; | |
| } | |
| .bubble { | |
| position: absolute; | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| } | |
| .bubble:hover { | |
| transform: scale(1.05); | |
| } | |
| .message-banner { | |
| animation: slideIn 0.5s forwards, fadeOut 0.5s 5s forwards; | |
| } | |
| @keyframes slideIn { | |
| from { transform: translateY(100px); opacity: 0; } | |
| to { transform: translateY(0); opacity: 1; } | |
| } | |
| @keyframes fadeOut { | |
| from { opacity: 1; } | |
| to { opacity: 0; } | |
| } | |
| .range-slider::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background: #4f46e5; | |
| cursor: pointer; | |
| } | |
| .participant-marker { | |
| position: absolute; | |
| width: 24px; | |
| height: 24px; | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-weight: bold; | |
| color: white; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-900 text-white min-h-screen"> | |
| <!-- Home Screen --> | |
| <div id="home-screen" class="flex flex-col items-center justify-center min-h-screen p-4"> | |
| <div class="text-center mb-12"> | |
| <h1 class="text-5xl font-bold mb-4 text-purple-500">HypnoMap Live</h1> | |
| <p class="text-xl text-gray-300">Expérience sonore géolocalisée</p> | |
| </div> | |
| <div class="w-full max-w-md space-y-6"> | |
| <button id="join-btn" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-4 px-6 rounded-lg text-xl transition flex items-center justify-center"> | |
| <i class="fas fa-user-friends mr-3"></i> Rejoindre une session | |
| </button> | |
| <button id="create-btn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-4 px-6 rounded-lg text-xl transition flex items-center justify-center"> | |
| <i class="fas fa-music mr-3"></i> Créer une session (DJ) | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Join Session Modal --> | |
| <div id="join-modal" class="fixed inset-0 bg-black bg-opacity-80 flex items-center justify-center z-50 hidden"> | |
| <div class="bg-gray-800 rounded-xl p-6 w-full max-w-md"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h2 class="text-2xl font-bold">Rejoindre une session</h2> | |
| <button id="close-join-modal" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="mb-6"> | |
| <label class="block text-gray-300 mb-2">Code de session</label> | |
| <input type="text" id="session-code" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Entrez le code"> | |
| </div> | |
| <div class="mb-6"> | |
| <label class="block text-gray-300 mb-2">Votre pseudo</label> | |
| <input type="text" id="participant-name" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Optionnel"> | |
| </div> | |
| <button id="confirm-join" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-6 rounded-lg transition"> | |
| Rejoindre | |
| </button> | |
| </div> | |
| </div> | |
| <!-- DJ Mode --> | |
| <div id="dj-screen" class="hidden min-h-screen flex flex-col"> | |
| <div class="bg-gray-800 p-4 flex justify-between items-center"> | |
| <div> | |
| <h2 class="text-xl font-bold">Mode DJ</h2> | |
| <p class="text-sm text-gray-400">Session: <span id="dj-session-code" class="font-mono">XXXXXX</span></p> | |
| </div> | |
| <div class="flex space-x-2"> | |
| <button id="dj-settings" class="p-2 rounded-full hover:bg-gray-700"> | |
| <i class="fas fa-cog"></i> | |
| </button> | |
| <button id="leave-dj" class="p-2 rounded-full hover:bg-gray-700"> | |
| <i class="fas fa-sign-out-alt"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="relative flex-1"> | |
| <div id="dj-map" class="map-container w-full h-full relative overflow-hidden"> | |
| <!-- Map will be rendered here --> | |
| <div id="dj-bubbles-container"></div> | |
| <div id="dj-participants-container"></div> | |
| </div> | |
| <div class="absolute bottom-4 left-0 right-0 flex justify-center"> | |
| <button id="create-bubble-btn" class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-6 rounded-full shadow-lg flex items-center"> | |
| <i class="fas fa-plus-circle mr-2"></i> Créer une bulle | |
| </button> | |
| </div> | |
| <div id="dj-controls" class="absolute top-4 right-4 bg-gray-800 bg-opacity-80 rounded-lg p-3 space-y-3"> | |
| <button id="play-all" class="p-2 bg-green-600 hover:bg-green-700 rounded-full"> | |
| <i class="fas fa-play"></i> | |
| </button> | |
| <button id="pause-all" class="p-2 bg-yellow-600 hover:bg-yellow-700 rounded-full"> | |
| <i class="fas fa-pause"></i> | |
| </button> | |
| <button id="global-message" class="p-2 bg-blue-600 hover:bg-blue-700 rounded-full"> | |
| <i class="fas fa-bullhorn"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Participant Mode --> | |
| <div id="participant-screen" class="hidden min-h-screen flex flex-col"> | |
| <div class="bg-gray-800 p-4 flex justify-between items-center"> | |
| <div> | |
| <h2 class="text-xl font-bold">Mode Participant</h2> | |
| <p class="text-sm text-gray-400">Session: <span id="participant-session-code" class="font-mono">XXXXXX</span></p> | |
| </div> | |
| <div class="flex space-x-2"> | |
| <button id="leave-participant" class="p-2 rounded-full hover:bg-gray-700"> | |
| <i class="fas fa-sign-out-alt"></i> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="relative flex-1"> | |
| <div id="participant-map" class="map-container w-full h-full relative overflow-hidden"> | |
| <!-- Map will be rendered here --> | |
| <div id="participant-bubbles-container"></div> | |
| <div id="participant-participants-container"></div> | |
| </div> | |
| <div id="message-banner" class="message-banner absolute bottom-20 left-0 right-0 mx-auto bg-purple-600 bg-opacity-90 rounded-lg p-4 max-w-md text-center hidden"> | |
| <p id="message-content" class="font-medium"></p> | |
| </div> | |
| <div class="absolute bottom-4 left-0 right-0 flex justify-center px-4"> | |
| <div class="flex w-full max-w-md bg-gray-800 bg-opacity-80 rounded-full p-2"> | |
| <input type="text" id="participant-message" class="flex-1 bg-transparent px-4 py-2 focus:outline-none" placeholder="Envoyer un message..." maxlength="140"> | |
| <button id="send-message" class="bg-purple-600 hover:bg-purple-700 rounded-full px-4"> | |
| <i class="fas fa-paper-plane"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Create Bubble Modal --> | |
| <div id="bubble-modal" class="fixed inset-0 bg-black bg-opacity-80 flex items-center justify-center z-50 hidden"> | |
| <div class="bg-gray-800 rounded-xl p-6 w-full max-w-md"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h2 class="text-2xl font-bold">Nouvelle bulle sonore</h2> | |
| <button id="close-bubble-modal" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="mb-4"> | |
| <label class="block text-gray-300 mb-2">Nom de la bulle</label> | |
| <input type="text" id="bubble-name" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Ma bulle sonore"> | |
| </div> | |
| <div class="mb-4"> | |
| <label class="block text-gray-300 mb-2">Fichier audio</label> | |
| <div class="flex items-center"> | |
| <label for="audio-upload" class="bg-gray-700 hover:bg-gray-600 border border-gray-600 rounded-lg px-4 py-3 cursor-pointer flex-1"> | |
| <span id="audio-file-name" class="text-gray-300">Sélectionner un fichier...</span> | |
| </label> | |
| <input type="file" id="audio-upload" class="hidden" accept="audio/*"> | |
| </div> | |
| </div> | |
| <div class="mb-6"> | |
| <label class="block text-gray-300 mb-2">Rayon d'activation: <span id="radius-value">25</span>m</label> | |
| <input type="range" id="bubble-radius" min="5" max="50" value="25" class="w-full range-slider"> | |
| </div> | |
| <button id="confirm-bubble" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-6 rounded-lg transition"> | |
| Créer la bulle | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Global Message Modal --> | |
| <div id="global-message-modal" class="fixed inset-0 bg-black bg-opacity-80 flex items-center justify-center z-50 hidden"> | |
| <div class="bg-gray-800 rounded-xl p-6 w-full max-w-md"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h2 class="text-2xl font-bold">Message global</h2> | |
| <button id="close-global-message-modal" class="text-gray-400 hover:text-white"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| </div> | |
| <div class="mb-6"> | |
| <label class="block text-gray-300 mb-2">Message</label> | |
| <textarea id="global-message-text" class="w-full bg-gray-700 border border-gray-600 rounded-lg px-4 py-3 h-32 focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="Écrivez un message pour tous les participants..." maxlength="140"></textarea> | |
| </div> | |
| <button id="send-global-message" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-6 rounded-lg transition"> | |
| Envoyer | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| // State management | |
| const appState = { | |
| currentScreen: 'home', | |
| isDJ: false, | |
| sessionCode: '', | |
| bubbles: [], | |
| participants: [], | |
| messages: [], | |
| currentUser: { | |
| id: Math.random().toString(36).substring(2, 10), | |
| name: 'Participant ' + Math.floor(Math.random() * 1000), | |
| position: { x: 50, y: 50 } | |
| } | |
| }; | |
| // DOM elements | |
| const homeScreen = document.getElementById('home-screen'); | |
| const joinModal = document.getElementById('join-modal'); | |
| const djScreen = document.getElementById('dj-screen'); | |
| const participantScreen = document.getElementById('participant-screen'); | |
| const bubbleModal = document.getElementById('bubble-modal'); | |
| const globalMessageModal = document.getElementById('global-message-modal'); | |
| // Event listeners | |
| document.getElementById('join-btn').addEventListener('click', () => { | |
| joinModal.classList.remove('hidden'); | |
| }); | |
| document.getElementById('create-btn').addEventListener('click', () => { | |
| createSession(true); | |
| }); | |
| document.getElementById('close-join-modal').addEventListener('click', () => { | |
| joinModal.classList.add('hidden'); | |
| }); | |
| document.getElementById('confirm-join').addEventListener('click', () => { | |
| const code = document.getElementById('session-code').value; | |
| const name = document.getElementById('participant-name').value; | |
| if (code) { | |
| if (name) appState.currentUser.name = name; | |
| joinSession(code); | |
| joinModal.classList.add('hidden'); | |
| } else { | |
| alert('Veuillez entrer un code de session'); | |
| } | |
| }); | |
| document.getElementById('leave-dj').addEventListener('click', () => { | |
| showScreen('home'); | |
| }); | |
| document.getElementById('leave-participant').addEventListener('click', () => { | |
| showScreen('home'); | |
| }); | |
| document.getElementById('create-bubble-btn').addEventListener('click', () => { | |
| bubbleModal.classList.remove('hidden'); | |
| }); | |
| document.getElementById('close-bubble-modal').addEventListener('click', () => { | |
| bubbleModal.classList.add('hidden'); | |
| }); | |
| document.getElementById('confirm-bubble').addEventListener('click', () => { | |
| const name = document.getElementById('bubble-name').value; | |
| const radius = parseInt(document.getElementById('bubble-radius').value); | |
| if (name) { | |
| createBubble(name, radius); | |
| bubbleModal.classList.add('hidden'); | |
| } else { | |
| alert('Veuillez donner un nom à votre bulle'); | |
| } | |
| }); | |
| document.getElementById('bubble-radius').addEventListener('input', (e) => { | |
| document.getElementById('radius-value').textContent = e.target.value; | |
| }); | |
| document.getElementById('audio-upload').addEventListener('change', (e) => { | |
| const file = e.target.files[0]; | |
| if (file) { | |
| document.getElementById('audio-file-name').textContent = file.name; | |
| } | |
| }); | |
| document.getElementById('global-message').addEventListener('click', () => { | |
| globalMessageModal.classList.remove('hidden'); | |
| }); | |
| document.getElementById('close-global-message-modal').addEventListener('click', () => { | |
| globalMessageModal.classList.add('hidden'); | |
| }); | |
| document.getElementById('send-global-message').addEventListener('click', () => { | |
| const message = document.getElementById('global-message-text').value; | |
| if (message) { | |
| sendGlobalMessage(message); | |
| globalMessageModal.classList.add('hidden'); | |
| document.getElementById('global-message-text').value = ''; | |
| } | |
| }); | |
| document.getElementById('send-message').addEventListener('click', () => { | |
| const message = document.getElementById('participant-message').value; | |
| if (message) { | |
| sendParticipantMessage(message); | |
| document.getElementById('participant-message').value = ''; | |
| } | |
| }); | |
| // Functions | |
| function showScreen(screen) { | |
| homeScreen.classList.add('hidden'); | |
| djScreen.classList.add('hidden'); | |
| participantScreen.classList.add('hidden'); | |
| appState.currentScreen = screen; | |
| if (screen === 'home') { | |
| homeScreen.classList.remove('hidden'); | |
| } else if (screen === 'dj') { | |
| djScreen.classList.remove('hidden'); | |
| renderDJMap(); | |
| } else if (screen === 'participant') { | |
| participantScreen.classList.remove('hidden'); | |
| renderParticipantMap(); | |
| } | |
| } | |
| function createSession(isDJ) { | |
| appState.isDJ = isDJ; | |
| appState.sessionCode = generateSessionCode(); | |
| if (isDJ) { | |
| document.getElementById('dj-session-code').textContent = appState.sessionCode; | |
| showScreen('dj'); | |
| } else { | |
| document.getElementById('participant-session-code').textContent = appState.sessionCode; | |
| showScreen('participant'); | |
| } | |
| // Simulate other participants joining | |
| setTimeout(() => { | |
| addParticipant('DJ Master', { x: 30, y: 30 }); | |
| addParticipant('Sound Explorer', { x: 70, y: 70 }); | |
| addParticipant('Music Traveler', { x: 60, y: 40 }); | |
| if (isDJ) { | |
| renderDJMap(); | |
| } else { | |
| renderParticipantMap(); | |
| } | |
| }, 1000); | |
| } | |
| function joinSession(code) { | |
| appState.isDJ = false; | |
| appState.sessionCode = code; | |
| document.getElementById('participant-session-code').textContent = code; | |
| showScreen('participant'); | |
| // Simulate existing bubbles | |
| setTimeout(() => { | |
| addBubble('Ambiance Chill', 20, { x: 40, y: 60 }); | |
| addBubble('Rythme Urbain', 15, { x: 70, y: 30 }); | |
| renderParticipantMap(); | |
| }, 1000); | |
| } | |
| function generateSessionCode() { | |
| return Math.random().toString(36).substring(2, 8).toUpperCase(); | |
| } | |
| function createBubble(name, radius) { | |
| const bubble = { | |
| id: Math.random().toString(36).substring(2, 10), | |
| name, | |
| radius, | |
| position: { x: 50, y: 50 }, // Center position | |
| audio: 'sample.mp3' // In a real app, this would be the uploaded file | |
| }; | |
| appState.bubbles.push(bubble); | |
| renderDJMap(); | |
| } | |
| function addBubble(name, radius, position) { | |
| const bubble = { | |
| id: Math.random().toString(36).substring(2, 10), | |
| name, | |
| radius, | |
| position, | |
| audio: 'sample.mp3' | |
| }; | |
| appState.bubbles.push(bubble); | |
| } | |
| function addParticipant(name, position) { | |
| const participant = { | |
| id: Math.random().toString(36).substring(2, 10), | |
| name, | |
| position | |
| }; | |
| appState.participants.push(participant); | |
| } | |
| function sendGlobalMessage(message) { | |
| // In a real app, this would be sent to all participants | |
| console.log('Global message sent:', message); | |
| } | |
| function sendParticipantMessage(message) { | |
| const messageObj = { | |
| id: Math.random().toString(36).substring(2, 10), | |
| sender: appState.currentUser.name, | |
| content: message, | |
| timestamp: new Date() | |
| }; | |
| // Show the message banner | |
| const banner = document.getElementById('message-banner'); | |
| const content = document.getElementById('message-content'); | |
| content.textContent = `${messageObj.sender}: ${messageObj.content}`; | |
| banner.classList.remove('hidden'); | |
| // Hide after animation | |
| setTimeout(() => { | |
| banner.classList.add('hidden'); | |
| }, 5500); | |
| } | |
| function renderDJMap() { | |
| const container = document.getElementById('dj-bubbles-container'); | |
| const participantsContainer = document.getElementById('dj-participants-container'); | |
| container.innerHTML = ''; | |
| participantsContainer.innerHTML = ''; | |
| // Render bubbles | |
| appState.bubbles.forEach(bubble => { | |
| const bubbleEl = document.createElement('div'); | |
| bubbleEl.className = 'bubble bg-purple-500 bg-opacity-30 border-2 border-purple-400'; | |
| bubbleEl.style.width = `${bubble.radius * 6}px`; | |
| bubbleEl.style.height = `${bubble.radius * 6}px`; | |
| bubbleEl.style.left = `${bubble.position.x}%`; | |
| bubbleEl.style.top = `${bubble.position.y}%`; | |
| bubbleEl.title = bubble.name; | |
| // Make draggable | |
| bubbleEl.draggable = true; | |
| bubbleEl.addEventListener('dragstart', (e) => { | |
| e.dataTransfer.setData('text/plain', bubble.id); | |
| }); | |
| container.appendChild(bubbleEl); | |
| }); | |
| // Render participants | |
| appState.participants.forEach(participant => { | |
| const participantEl = document.createElement('div'); | |
| participantEl.className = 'participant-marker bg-blue-500'; | |
| participantEl.style.left = `${participant.position.x}%`; | |
| participantEl.style.top = `${participant.position.y}%`; | |
| participantEl.textContent = participant.name.charAt(0); | |
| participantEl.title = participant.name; | |
| participantsContainer.appendChild(participantEl); | |
| }); | |
| // Add drop zone for bubbles | |
| const map = document.getElementById('dj-map'); | |
| map.addEventListener('dragover', (e) => { | |
| e.preventDefault(); | |
| }); | |
| map.addEventListener('drop', (e) => { | |
| e.preventDefault(); | |
| const bubbleId = e.dataTransfer.getData('text/plain'); | |
| const bubble = appState.bubbles.find(b => b.id === bubbleId); | |
| if (bubble) { | |
| const rect = map.getBoundingClientRect(); | |
| const x = ((e.clientX - rect.left) / rect.width) * 100; | |
| const y = ((e.clientY - rect.top) / rect.height) * 100; | |
| bubble.position = { x, y }; | |
| renderDJMap(); | |
| } | |
| }); | |
| } | |
| function renderParticipantMap() { | |
| const container = document.getElementById('participant-bubbles-container'); | |
| const participantsContainer = document.getElementById('participant-participants-container'); | |
| container.innerHTML = ''; | |
| participantsContainer.innerHTML = ''; | |
| // Render bubbles | |
| appState.bubbles.forEach(bubble => { | |
| const bubbleEl = document.createElement('div'); | |
| bubbleEl.className = 'bubble bg-purple-500 bg-opacity-20 border border-purple-400'; | |
| bubbleEl.style.width = `${bubble.radius * 6}px`; | |
| bubbleEl.style.height = `${bubble.radius * 6}px`; | |
| bubbleEl.style.left = `${bubble.position.x}%`; | |
| bubbleEl.style.top = `${bubble.position.y}%`; | |
| bubbleEl.title = bubble.name; | |
| container.appendChild(bubbleEl); | |
| }); | |
| // Render participants | |
| appState.participants.forEach(participant => { | |
| const participantEl = document.createElement('div'); | |
| participantEl.className = 'participant-marker bg-blue-500'; | |
| participantEl.style.left = `${participant.position.x}%`; | |
| participantEl.style.top = `${participant.position.y}%`; | |
| participantEl.textContent = participant.name.charAt(0); | |
| participantEl.title = participant.name; | |
| participantsContainer.appendChild(participantEl); | |
| }); | |
| // Add current user | |
| const currentUserEl = document.createElement('div'); | |
| currentUserEl.className = 'participant-marker bg-green-500'; | |
| currentUserEl.style.left = `${appState.currentUser.position.x}%`; | |
| currentUserEl.style.top = `${appState.currentUser.position.y}%`; | |
| currentUserEl.textContent = appState.currentUser.name.charAt(0); | |
| currentUserEl.title = appState.currentUser.name; | |
| participantsContainer.appendChild(currentUserEl); | |
| } | |
| // Initialize | |
| showScreen('home'); | |
| </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=PierreH/test" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |