From b1a2e20b4b6dc8822da46ceac5934655a4d560ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drix?= Date: Fri, 27 Mar 2026 01:28:29 +0100 Subject: [PATCH] Simplification des fichiers --- public/index.html | 314 +------------------------------------------ public/manifest.json | 2 +- public/script.js | 201 +++++++++++++++++++++++++++ public/style.css | 103 ++++++++++++++ 4 files changed, 308 insertions(+), 312 deletions(-) create mode 100644 public/script.js create mode 100644 public/style.css diff --git a/public/index.html b/public/index.html index ecc6604..c1bcb05 100644 --- a/public/index.html +++ b/public/index.html @@ -5,114 +5,11 @@ Soundboard A5L + - + @@ -153,212 +50,7 @@ - - - - + \ No newline at end of file diff --git a/public/manifest.json b/public/manifest.json index 53af46a..a321b85 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,6 +1,6 @@ { "name": "Soundboard A5L", - "short_name": "Soundboard", + "short_name": "Soundboard A5L", "description": "Studio de sons 64 touches pour écran tactile", "start_url": "index.html", "display": "fullscreen", diff --git a/public/script.js b/public/script.js new file mode 100644 index 0000000..5568919 --- /dev/null +++ b/public/script.js @@ -0,0 +1,201 @@ + let isEditMode = false; + let editingIndex = null; + let tempFileData = null; + + let deferredPrompt; + const installBtn = document.getElementById('installBtn'); + + window.addEventListener('beforeinstallprompt', (e) => { + // Empêche Chrome d'afficher sa propre mini-barre + e.preventDefault(); + // Stocke l'événement pour l'utiliser plus tard + deferredPrompt = e; + // Affiche votre bouton personnalisé + installBtn.style.display = 'block'; + + installBtn.addEventListener('click', async () => { + if (deferredPrompt) { + // Montre la fenêtre d'installation native + deferredPrompt.prompt(); + // Attend la réponse de l'utilisateur + const { outcome } = await deferredPrompt.userChoice; + console.log(`L'utilisateur a répondu : ${outcome}`); + // On nettoie + deferredPrompt = null; + installBtn.style.display = 'none'; + } + }); + }); + + // Cache le bouton si l'app est déjà installée + window.addEventListener('appinstalled', () => { + installBtn.style.display = 'none'; + deferredPrompt = null; + console.log('PWA installée avec succès !'); + }); + + // Données pour 64 boutons (Grille 8x8) + let btnData = JSON.parse(localStorage.getItem('sb_studio_data')) || Array(64).fill(null).map((_, i) => ({ + id: i, name: "", file: null, loop: false, volume: 1 + })); + + const players = {}; + + let draggedIndex = null; + + function handleDragStart(e, index) { + draggedIndex = index; + e.target.classList.add('dragging'); + // On définit un transfert de données pour Firefox + e.dataTransfer.setData('text/plain', index); + } + + function handleDragOver(e) { + e.preventDefault(); // Nécessaire pour permettre le drop + return false; + } + + function handleDrop(e, targetIndex) { + e.preventDefault(); + const targetElement = document.getElementById(`btn-${targetIndex}`); + targetElement.classList.remove('drag-over'); + + if (draggedIndex === targetIndex) return; + + // --- LOGIQUE D'INVERSION --- + // On inverse les données dans le tableau btnData + const temp = btnData[draggedIndex]; + btnData[draggedIndex] = btnData[targetIndex]; + btnData[targetIndex] = temp; + + // On s'assure que les IDs restent corrects (optionnel selon ton usage) + btnData[draggedIndex].id = draggedIndex; + btnData[targetIndex].id = targetIndex; + + // Si des sons étaient en cours, on les arrête pour éviter les bugs + stopAll(); + + // On réinitialise les lecteurs audio pour ces deux boutons + delete players[draggedIndex]; + delete players[targetIndex]; + + // Sauvegarde et mise à jour de l'affichage + localStorage.setItem('sb_studio_data', JSON.stringify(btnData)); + init(); + } + + function init() { + const board = document.getElementById('board'); + board.innerHTML = ""; + btnData.forEach((data, i) => { + const div = document.createElement('div'); + div.className = `btn ${data.file ? 'active' : ''} ${data.loop ? 'has-loop' : ''}`; + div.id = `btn-${i}`; + div.setAttribute('draggable', 'true'); // Rend le bouton draggable + + div.innerHTML = `${i+1} + ${data.name || "-"} + `; + + // Clic pour lecture ou édition + div.onclick = () => handleBtnClick(i); + + // Événements de Drag & Drop + div.ondragstart = (e) => handleDragStart(e, i); + div.ondragover = (e) => handleDragOver(e); + div.ondragenter = (e) => div.classList.add('drag-over'); + div.ondragleave = (e) => div.classList.remove('drag-over'); + div.ondrop = (e) => handleDrop(e, i); + div.ondragend = (e) => div.classList.remove('dragging'); + + board.appendChild(div); + }); + } + + function toggleEditMode() { + isEditMode = !isEditMode; + document.body.classList.toggle('edit-mode', isEditMode); + document.getElementById('toggleBtn').innerText = isEditMode ? "QUITTER L'ÉDITION" : "MODE ÉDITION"; + document.getElementById('toggleBtn').style.background = isEditMode ? "var(--accent)" : "#444"; + document.getElementById('toggleBtn').style.color = isEditMode ? "black" : "white"; + } + + function handleBtnClick(i) { + if (isEditMode) openEdit(i); + else playSound(i); + } + + function playSound(i) { + const data = btnData[i]; + if (!data.file) return; + + if (players[i] && !players[i].paused) { + players[i].pause(); + players[i].currentTime = 0; + document.getElementById(`btn-${i}`).classList.remove('playing'); + } else { + if (!players[i]) players[i] = new Audio(data.file); + players[i].loop = data.loop; + players[i].volume = data.volume || 1; + players[i].play(); + document.getElementById(`btn-${i}`).classList.add('playing'); + players[i].onended = () => { if(!data.loop) document.getElementById(`btn-${i}`).classList.remove('playing'); }; + } + } + + function stopAll() { + Object.keys(players).forEach(key => { + players[key].pause(); players[key].currentTime = 0; + document.getElementById(`btn-${key}`).classList.remove('playing'); + }); + } + + function openEdit(i) { + editingIndex = i; + const data = btnData[i]; + document.getElementById('editTitle').innerText = "Bouton " + (i + 1); + document.getElementById('inputName').value = data.name; + document.getElementById('inputLoop').checked = data.loop; + document.getElementById('inputVolume').value = data.volume || 1; + document.getElementById('fileNameLabel').innerText = data.file ? "Audio présent" : "Audio vide"; + tempFileData = data.file; + document.getElementById('editOverlay').style.display = 'flex'; + } + + document.getElementById('fileInput').onchange = (e) => { + const file = e.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = (ev) => { + tempFileData = ev.target.result; + document.getElementById('fileNameLabel').innerText = "Fichier : " + file.name; + }; + reader.readAsDataURL(file); + } + }; + + function saveSettings() { + btnData[editingIndex].name = document.getElementById('inputName').value; + btnData[editingIndex].loop = document.getElementById('inputLoop').checked; + btnData[editingIndex].volume = parseFloat(document.getElementById('inputVolume').value); + btnData[editingIndex].file = tempFileData; + localStorage.setItem('sb_studio_data', JSON.stringify(btnData)); + if (players[editingIndex]) delete players[editingIndex]; + closeEdit(); + init(); + } + + // Désactive le menu contextuel (clic droit) sur toute la page + window.oncontextmenu = function(event) { + event.preventDefault(); + event.stopPropagation(); + return false; + }; + + function closeEdit() { document.getElementById('editOverlay').style.display = 'none'; } + init(); + + if ('serviceWorker' in navigator) { + navigator.serviceWorker.register('sw.js') + .then(() => console.log("Service Worker Enregistré")); + } \ No newline at end of file diff --git a/public/style.css b/public/style.css new file mode 100644 index 0000000..8bb3dec --- /dev/null +++ b/public/style.css @@ -0,0 +1,103 @@ +:root { + --bg: #050505; + --panel-bg: #151515; + --accent: #00f2ff; /* Cyan néon pour le 1080p */ + --danger: #ff004c; + --text: #ffffff; +} + +body { + background: var(--bg); + color: var(--text); + margin: 0; + font-family: 'Segoe UI', Roboto, sans-serif; + overflow: hidden; + height: 100vh; +} + +/* Header Studio */ +header { + height: 80px; + background: linear-gradient(180deg, #222 0%, #111 100%); + display: flex; + align-items: center; + padding: 0 30px; + justify-content: space-between; + border-bottom: 3px solid #333; + box-shadow: 0 4px 20px rgba(0,0,0,0.5); +} + +/* Grille Full HD (8 colonnes x 8 lignes = 64 boutons) */ +.grid { + display: grid; + grid-template-columns: repeat(8, 1fr); + grid-template-rows: repeat(8, 1fr); + gap: 10px; + height: calc(100vh - 80px); + padding: 15px; + box-sizing: border-box; +} + +.btn { + background: #1a1a1a; + border: 1px solid #333; + border-radius: 6px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; + font-size: 0.9rem; + font-weight: 500; + transition: all 0.1s ease; + cursor: pointer; + box-shadow: inset 0 0 10px rgba(0,0,0,0.5); +} + +.btn:hover { background: #222; border-color: #555; } +.btn.active { border-color: #444; color: #aaa; } +.btn.playing { + background: var(--danger); + color: white; + box-shadow: 0 0 20px var(--danger), inset 0 0 15px rgba(0,0,0,0.3); + border-color: white; + transform: scale(0.98); +} + +.btn-num { position: absolute; top: 5px; left: 8px; font-size: 0.7rem; color: #555; } +.loop-tag { position: absolute; bottom: 5px; right: 8px; font-size: 14px; color: var(--accent); opacity: 0; } +.btn.has-loop .loop-tag { opacity: 1; } + +/* Modale d'édition centrée (Style Desktop) */ +#editOverlay { + position: fixed; top: 0; left: 0; width: 100%; height: 100%; + background: rgba(0,0,0,0.9); display: none; z-index: 100; + justify-content: center; align-items: center; +} +#editPanel { + background: var(--panel-bg); width: 500px; padding: 40px; + border-radius: 15px; border: 2px solid var(--accent); + box-shadow: 0 0 50px rgba(0,242,255,0.2); +} + +input[type="text"], input[type="range"] { + width: 100%; padding: 12px; margin: 10px 0; background: #000; + border: 1px solid #444; color: white; border-radius: 4px; +} + +.actions { display: flex; gap: 15px; margin-top: 30px; } +.actions button { flex: 1; padding: 15px; border-radius: 5px; font-weight: bold; border: none; cursor: pointer; } +.btn-save { background: var(--accent); color: black; } +.btn-cancel { background: #333; color: white; } + +body.edit-mode .btn { border: 1px dashed var(--accent); cursor: crosshair; } +.stop-all { background: var(--danger); color: white; border: none; padding: 12px 25px; border-radius: 4px; font-weight: bold; cursor: pointer; } +.btn.dragging { + opacity: 0.4; + transform: scale(0.9); +} + +.btn.drag-over { + border: 2px solid var(--accent) !important; + background: #333; +}