diff --git a/css/funkwhale-tracks.css b/css/funkwhale-tracks.css index 6b3e230..e110685 100644 --- a/css/funkwhale-tracks.css +++ b/css/funkwhale-tracks.css @@ -62,22 +62,28 @@ display: flex; padding: 8px 12px; border-bottom: 1px solid var(--border-color); - text-decoration: none; color: inherit; transition: background-color 0.2s ease; gap: 8px; + position: relative; } .funkwhale-track-item:hover { background: var(--hover-bg); - text-decoration: none; - color: inherit; } .funkwhale-track-item:last-child { border-bottom: none; } +.funkwhale-track-item.playing { + background: var(--hover-bg); +} + +.funkwhale-track-item.playing .funkwhale-track-title { + color: var(--primary-red); +} + .funkwhale-track-thumb { width: 60px; height: 60px; @@ -90,6 +96,14 @@ justify-content: center; color: var(--text-secondary); position: relative; + border: none; + padding: 0; + cursor: pointer; + transition: transform 0.2s ease; +} + +.funkwhale-track-thumb:hover { + transform: scale(1.05); } .funkwhale-track-thumb img { @@ -98,7 +112,8 @@ object-fit: cover; } -.funkwhale-play-icon { +.funkwhale-play-icon, +.funkwhale-pause-icon { position: absolute; top: 50%; left: 50%; @@ -115,6 +130,18 @@ opacity: 1; } +.funkwhale-track-item.playing .funkwhale-play-icon { + opacity: 0; +} + +.funkwhale-track-item.playing .funkwhale-pause-icon { + opacity: 1; +} + +.funkwhale-track-item.playing:hover .funkwhale-pause-icon { + opacity: 1; +} + .funkwhale-track-info { flex: 1; min-width: 0; @@ -170,6 +197,36 @@ font-size: 0.9rem; } +/* Lien externe vers Funkwhale */ +.funkwhale-external-link { + display: flex; + align-items: center; + justify-content: center; + width: 36px; + height: 36px; + flex-shrink: 0; + color: var(--text-secondary); + text-decoration: none; + border-radius: 50%; + transition: all 0.2s ease; + margin-left: auto; +} + +.funkwhale-external-link:hover { + background: var(--tag-bg); + color: var(--primary-red); + transform: scale(1.1); +} + +.funkwhale-external-link i { + font-size: 0.85rem; +} + +/* Masquer l'élément audio */ +.funkwhale-track-item audio { + display: none; +} + /* Responsive Design */ @media (max-width: 1024px) { .funkwhale-section { diff --git a/includes/config.php b/includes/config.php index f04249d..52c8f2f 100644 --- a/includes/config.php +++ b/includes/config.php @@ -953,6 +953,14 @@ function getFunkwhaleTracks($funkwhaleUrl = null, $count = null) { // Ne garder que les morceaux locaux if ($isLocal) { + // Récupérer l'URL d'écoute depuis l'API (peut être relative) + $listenUrl = $item['listen_url'] ?? ''; + + // Si l'URL est relative, la transformer en URL absolue + if (!empty($listenUrl) && strpos($listenUrl, 'http') !== 0) { + $listenUrl = rtrim($funkwhaleUrl, '/') . $listenUrl; + } + $track = [ 'title' => $item['title'] ?? '', 'artist' => $item['artist']['name'] ?? 'Artiste inconnu', @@ -961,6 +969,7 @@ function getFunkwhaleTracks($funkwhaleUrl = null, $count = null) { 'duration' => $item['uploads'][0]['duration'] ?? 0, 'link' => rtrim($funkwhaleUrl, '/') . '/library/tracks/' . ($item['id'] ?? ''), 'trackId' => $item['id'] ?? 0, + 'audioUrl' => $listenUrl, ]; // Formater la durée diff --git a/index.php b/index.php index c0d8565..9dfcb7e 100644 --- a/index.php +++ b/index.php @@ -208,15 +208,15 @@ setSecurityHeaders(); if (empty($funkwhaleTracks)) { echo '
Aucun morceau disponible
'; } else { - foreach ($funkwhaleTracks as $track): + foreach ($funkwhaleTracks as $index => $track): ?> - +
-
+
+
+ +
-
+

@@ -246,7 +249,21 @@ setSecurityHeaders();

-
+ + + + + + + + + + + + + diff --git a/js/funkwhale-player.js b/js/funkwhale-player.js new file mode 100644 index 0000000..8e7b41f --- /dev/null +++ b/js/funkwhale-player.js @@ -0,0 +1,132 @@ +/** + * Lecteur audio intégré pour Funkwhale + * Permet de lire les morceaux directement dans la page + */ + +(function() { + 'use strict'; + + let currentlyPlayingTrack = null; + let currentAudioElement = null; + + /** + * Arrête le morceau en cours de lecture + */ + function stopCurrentTrack() { + if (currentAudioElement) { + currentAudioElement.pause(); + currentAudioElement.currentTime = 0; + } + if (currentlyPlayingTrack) { + currentlyPlayingTrack.classList.remove('playing'); + currentlyPlayingTrack = null; + } + } + + /** + * Démarre la lecture d'un morceau + */ + function playTrack(trackItem, audioElement) { + // Arrêter le morceau actuel s'il y en a un + if (currentlyPlayingTrack && currentlyPlayingTrack !== trackItem) { + stopCurrentTrack(); + } + + currentlyPlayingTrack = trackItem; + currentAudioElement = audioElement; + + // Marquer comme en cours de lecture + trackItem.classList.add('playing'); + + // Démarrer la lecture + audioElement.play().catch(function(error) { + console.error('Erreur lors de la lecture:', error); + stopCurrentTrack(); + }); + } + + /** + * Met en pause le morceau + */ + function pauseTrack(trackItem, audioElement) { + audioElement.pause(); + trackItem.classList.remove('playing'); + } + + /** + * Initialise les contrôles du lecteur + */ + function initPlayer() { + const trackItems = document.querySelectorAll('.funkwhale-track-item'); + + trackItems.forEach(function(trackItem) { + const playButton = trackItem.querySelector('.funkwhale-play-btn'); + const audioElement = trackItem.querySelector('audio'); + + if (!playButton || !audioElement) { + return; + } + + // Gestion du clic sur le bouton play/pause + playButton.addEventListener('click', function(e) { + e.preventDefault(); + e.stopPropagation(); + + if (trackItem.classList.contains('playing')) { + pauseTrack(trackItem, audioElement); + } else { + playTrack(trackItem, audioElement); + } + }); + + // Gérer la fin de la lecture + audioElement.addEventListener('ended', function() { + trackItem.classList.remove('playing'); + + // Passer automatiquement au morceau suivant + const nextTrack = trackItem.nextElementSibling; + if (nextTrack && nextTrack.classList.contains('funkwhale-track-item')) { + const nextAudio = nextTrack.querySelector('audio'); + if (nextAudio) { + playTrack(nextTrack, nextAudio); + } + } else { + // Réinitialiser si c'était le dernier morceau + currentlyPlayingTrack = null; + currentAudioElement = null; + } + }); + + // Gérer les erreurs de chargement + audioElement.addEventListener('error', function(e) { + console.error('Erreur de chargement audio:', e); + trackItem.classList.remove('playing'); + + // Afficher un message d'erreur temporaire + const trackTitle = trackItem.querySelector('.funkwhale-track-title'); + if (trackTitle) { + const originalText = trackTitle.textContent; + trackTitle.textContent = 'Erreur de lecture'; + trackTitle.style.color = '#ff0000'; + + setTimeout(function() { + trackTitle.textContent = originalText; + trackTitle.style.color = ''; + }, 3000); + } + }); + }); + } + + // Initialiser le lecteur quand le DOM est prêt + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initPlayer); + } else { + initPlayer(); + } + + // Nettoyer à la fermeture de la page + window.addEventListener('beforeunload', function() { + stopCurrentTrack(); + }); +})();