Spaces:
Running
Running
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>YouTube Clone</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| body { | |
| font-family: 'Roboto', sans-serif; | |
| background-color: #0f0f0f; | |
| color: #fff; | |
| } | |
| .sidebar { | |
| transform: translateX(-100%); | |
| transition: transform 0.3s ease; | |
| } | |
| .sidebar.open { | |
| transform: translateX(0); | |
| } | |
| .video-card:hover .video-thumbnail img { | |
| transform: scale(1.05); | |
| } | |
| .video-card .video-thumbnail img { | |
| transition: transform 0.3s ease; | |
| } | |
| .dark-scrollbar::-webkit-scrollbar { | |
| width: 8px; | |
| } | |
| .dark-scrollbar::-webkit-scrollbar-track { | |
| background: #181818; | |
| } | |
| .dark-scrollbar::-webkit-scrollbar-thumb { | |
| background: #555; | |
| border-radius: 4px; | |
| } | |
| .dark-scrollbar::-webkit-scrollbar-thumb:hover { | |
| background: #777; | |
| } | |
| .search-container { | |
| max-width: 600px; | |
| } | |
| @media (max-width: 768px) { | |
| .sidebar { | |
| width: 100%; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-[#0f0f0f] text-white"> | |
| <!-- Header --> | |
| <header class="fixed top-0 left-0 right-0 bg-[#0f0f0f] border-b border-gray-800 z-50"> | |
| <div class="flex items-center justify-between px-4 py-2"> | |
| <!-- Left Section --> | |
| <div class="flex items-center space-x-4"> | |
| <button id="menu-toggle" class="p-2 hover:bg-gray-800 rounded-full transition"> | |
| <i class="fas fa-bars text-xl"></i> | |
| </button> | |
| <div class="flex items-center space-x-1"> | |
| <i class="fab fa-youtube text-red-600 text-2xl"></i> | |
| <span class="text-xl font-bold">YouTube</span> | |
| </div> | |
| </div> | |
| <!-- Center Section --> | |
| <div class="hidden md:flex items-center flex-1 max-w-2xl mx-4"> | |
| <div class="flex w-full"> | |
| <input type="text" | |
| placeholder="Rechercher" | |
| class="flex-1 bg-[#121212] border border-gray-600 rounded-l-full px-4 py-2 text-white placeholder-gray-400 focus:outline-none focus:border-blue-500"> | |
| <button class="bg-gray-700 px-6 py-2 rounded-r-full hover:bg-gray-600 transition"> | |
| <i class="fas fa-search"></i> | |
| </button> | |
| </div> | |
| <button class="ml-4 p-2 bg-gray-700 rounded-full hover:bg-gray-600 transition"> | |
| <i class="fas fa-microphone"></i> | |
| </button> | |
| </div> | |
| <!-- Right Section --> | |
| <div class="flex items-center space-x-4"> | |
| <button class="p-2 hover:bg-gray-800 rounded-full transition"> | |
| <i class="fas fa-video-plus text-xl"></i> | |
| </button> | |
| <button class="p-2 hover:bg-gray-800 rounded-full transition"> | |
| <i class="fas fa-bell text-xl"></i> | |
| </button> | |
| <img src="https://via.placeholder.com/32" alt="Profile" class="w-8 h-8 rounded-full"> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Sidebar --> | |
| <aside id="sidebar" class="fixed left-0 top-[60px] bottom-0 w-64 bg-[#0f0f0f] overflow-y-auto dark-scrollbar z-40"> | |
| <nav class="px-2 py-4"> | |
| <div class="space-y-1"> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 hover:bg-gray-800 rounded-lg transition"> | |
| <i class="fas fa-home w-6 text-center"></i> | |
| <span>Accueil</span> | |
| </a> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 hover:bg-gray-800 rounded-lg transition"> | |
| <i class="fas fa-fire w-6 text-center"></i> | |
| <span>Tendances</span> | |
| </a> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 hover:bg-gray-800 rounded-lg transition"> | |
| <i class="fas fa-compass w-6 text-center"></i> | |
| <span>Explorer</span> | |
| </a> | |
| </div> | |
| <div class="border-t border-gray-800 my-4"></div> | |
| <div class="space-y-1"> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 hover:bg-gray-800 rounded-lg transition"> | |
| <i class="fas fa-history w-6 text-center"></i> | |
| <span>Historique</span> | |
| </a> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 hover:bg-gray-800 rounded-lg transition"> | |
| <i class="fas fa-clock w-6 text-center"></i> | |
| <span>À regarder plus tard</span> | |
| </a> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 hover:bg-gray-800 rounded-lg transition"> | |
| <i class="fas fa-thumbs-up w-6 text-center"></i> | |
| <span>Vidéos likées</span> | |
| </a> | |
| </div> | |
| <div class="border-t border-gray-800 my-4"></div> | |
| <div class="px-3 py-2"> | |
| <h3 class="text-sm font-semibold text-gray-400 uppercase mb-2">Abonnements</h3> | |
| <div class="space-y-1"> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 hover:bg-gray-800 rounded-lg transition"> | |
| <img src="https://via.placeholder.com/24" alt="Channel" class="w-6 h-6 rounded-full"> | |
| <span>Chaîne 1</span> | |
| </a> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 hover:bg-gray-800 rounded-lg transition"> | |
| <img src="https://via.placeholder.com/24" alt="Channel" class="w-6 h-6 rounded-full"> | |
| <span>Chaîne 2</span> | |
| </a> | |
| <a href="#" class="flex items-center space-x-3 px-3 py-2 hover:bg-gray-800 rounded-lg transition"> | |
| <img src="https://via.placeholder.com/24" alt="Channel" class="w-6 h-6 rounded-full"> | |
| <span>Chaîne 3</span> | |
| </a> | |
| </div> | |
| </div> | |
| </nav> | |
| </aside> | |
| <!-- Main Content --> | |
| <main class="pt-[60px] ml-0 md:ml-64"> | |
| <!-- Chips --> | |
| <div class="flex space-x-2 px-4 py-4 overflow-x-auto dark-scrollbar"> | |
| <button class="px-4 py-2 bg-white text-black rounded-full font-medium">Tout</button> | |
| <button class="px-4 py-2 bg-gray-800 text-white rounded-full font-medium hover:bg-gray-700 transition">Musique</button> | |
| <button class="px-4 py-2 bg-gray-800 text-white rounded-full font-medium hover:bg-gray-700 transition">Jeux vidéo</button> | |
| <button class="px-4 py-2 bg-gray-800 text-white rounded-full font-medium hover:bg-gray-700 transition">Technologie</button> | |
| <button class="px-4 py-2 bg-gray-800 text-white rounded-full font-medium hover:bg-gray-700 transition">Actualités</button> | |
| <button class="px-4 py-2 bg-gray-800 text-white rounded-full font-medium hover:bg-gray-700 transition">Divertissement</button> | |
| <button class="px-4 py-2 bg-gray-800 text-white rounded-full font-medium hover:bg-gray-700 transition">Sports</button> | |
| </div> | |
| <!-- Video Grid --> | |
| <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 px-4"> | |
| <!-- Video Card 1 --> | |
| <div class="video-card"> | |
| <div class="video-thumbnail relative"> | |
| <img src="https://via.placeholder.com/400x225" alt="Thumbnail" class="w-full rounded-lg"> | |
| <span class="absolute bottom-2 right-2 bg-black bg-opacity-75 px-2 py-1 text-xs rounded">10:30</span> | |
| </div> | |
| <div class="flex mt-3"> | |
| <img src="https://via.placeholder.com/36" alt="Channel" class="w-9 h-9 rounded-full mr-3"> | |
| <div> | |
| <h3 class="font-semibold text-sm line-clamp-2">Titre de la vidéo incroyable qui explique tout</h3> | |
| <p class="text-sm text-gray-400 mt-1">Nom de la chaîne</p> | |
| <p class="text-sm text-gray-400">1.2M vues • il y a 2 jours</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Video Card 2 --> | |
| <div class="video-card"> | |
| <div class="video-thumbnail relative"> | |
| <img src="https://via.placeholder.com/400x225" alt="Thumbnail" class="w-full rounded-lg"> | |
| <span class="absolute bottom-2 right-2 bg-black bg-opacity-75 px-2 py-1 text-xs rounded">5:45</span> | |
| </div> | |
| <div class="flex mt-3"> | |
| <img src="https://via.placeholder.com/36" alt="Channel" class="w-9 h-9 rounded-full mr-3"> | |
| <div> | |
| <h3 class="font-semibold text-sm line-clamp-2">Tutoriel complet sur Tailwind CSS</h3> | |
| <p class="text-sm text-gray-400 mt-1">Tech Channel</p> | |
| <p class="text-sm text-gray-400">856K vues • il y a 1 semaine</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Video Card 3 --> | |
| <div class="video-card"> | |
| <div class="video-thumbnail relative"> | |
| <img src="https://via.placeholder.com/400x225" alt="Thumbnail" class="w-full rounded-lg"> | |
| <span class="absolute bottom-2 right-2 bg-black bg-opacity-75 px-2 py-1 text-xs rounded">15:20</span> | |
| </div> | |
| <div class="flex mt-3"> | |
| <img src="https://via.placeholder.com/36" alt="Channel" class="w-9 h-9 rounded-full mr-3"> | |
| <div> | |
| <h3 class="font-semibold text-sm line-clamp-2">Les meilleurs moments du match</h3> | |
| <p class="text-sm text-gray-400 mt-1">Sports TV</p> | |
| <p class="text-sm text-gray-400">2.8M vues • il y a 3 heures</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Video Card 4 --> | |
| <div class="video-card"> | |
| <div class="video-thumbnail relative"> | |
| <img src="https://via.placeholder.com/400x225" alt="Thumbnail" class="w-full rounded-lg"> | |
| <span class="absolute bottom-2 right-2 bg-black bg-opacity-75 px-2 py-1 text-xs rounded">8:12</span> | |
| </div> | |
| <div class="flex mt-3"> | |
| <img src="https://via.placeholder.com/36" alt="Channel" class="w-9 h-9 rounded-full mr-3"> | |
| <div> | |
| <h3 class="font-semibold text-sm line-clamp-2">Recette de cuisine facile du jour</h3> | |
| <p class="text-sm text-gray-400 mt-1">Chef Gourmet</p> | |
| <p class="text-sm text-gray-400">432K vues • il y a 5 jours</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Video Card 5 --> | |
| <div class="video-card"> | |
| <div class="video-thumbnail relative"> | |
| <img src="https://via.placeholder.com/400x225" alt="Thumbnail" class="w-full rounded-lg"> | |
| <span class="absolute bottom-2 right-2 bg-black bg-opacity-75 px-2 py-1 text-xs rounded">12:30</span> | |
| </div> | |
| <div class="flex mt-3"> | |
| <img src="https://via.placeholder.com/36" alt="Channel" class="w-9 h-9 rounded-full mr-3"> | |
| <div> | |
| <h3 class="font-semibold text-sm line-clamp-2">Review du nouvel iPhone 15 Pro</h3> | |
| <p class="text-sm text-gray-400 mt-1">Tech Reviews</p> | |
| <p class="text-sm text-gray-400">1.5M vues • il y a 1 jour</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Video Card 6 --> | |
| <div class="video-card"> | |
| <div class="video-thumbnail relative"> | |
| <img src="https://via.placeholder.com/400x225" alt="Thumbnail" class="w-full rounded-lg"> | |
| <span class="absolute bottom-2 right-2 bg-black bg-opacity-75 px-2 py-1 text-xs rounded">20:15</span> | |
| </div> | |
| <div class="flex mt-3"> | |
| <img src="https://via.placeholder.com/36" alt="Channel" class="w-9 h-9 rounded-full mr-3"> | |
| <div> | |
| <h3 class="font-semibold text-sm line-clamp-2">Documentaire sur la nature incroyable</h3> | |
| <p class="text-sm text-gray-400 mt-1">Nature Explorer</p> | |
| <p class="text-sm text-gray-400">890K vues • il y a 2 semaines</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Video Card 7 --> | |
| <div class="video-card"> | |
| <div class="video-thumbnail relative"> | |
| <img src="https://via.placeholder.com/400x225" alt="Thumbnail" class="w-full rounded-lg"> | |
| <span class="absolute bottom-2 right-2 bg-black bg-opacity-75 px-2 py-1 text-xs rounded">7:45</span> | |
| </div> | |
| <div class="flex mt-3"> | |
| <img src="https://via.placeholder.com/36" alt="Channel" class="w-9 h-9 rounded-full mr-3"> | |
| <div> | |
| <h3 class="font-semibold text-sm line-clamp-2">Top 10 des astuces de coding</h3> | |
| <p class="text-sm text-gray-400 mt-1">Code Academy</p> | |
| <p class="text-sm text-gray-400">234K vues • il y a 3 jours</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Video Card 8 --> | |
| <div class="video-card"> | |
| <div class="video-thumbnail relative"> | |
| <img src="https://via.placeholder.com/400x225" alt="Thumbnail" class="w-full rounded-lg"> | |
| <span class="absolute bottom-2 right-2 bg-black bg-opacity-75 px-2 py-1 text-xs rounded">25:00</span> | |
| </div> | |
| <div class="flex mt-3"> | |
| <img src="https://via.placeholder.com/36" alt="Channel" class="w-9 h-9 rounded-full mr-3"> | |
| <div> | |
| <h3 class="font-semibold text-sm line-clamp-2">Live de gaming avec les abonnés</h3> | |
| <p class="text-sm text-gray-400 mt-1">Gamer Pro</p> | |
| <p class="text-sm text-gray-400">5.6K en direct</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Overlay for mobile --> | |
| <div id="overlay" class="fixed inset-0 bg-black bg-opacity-50 z-30 hidden"></div> | |
| <script> | |
| const API_KEY = 'AIzaSyDSIPuVfX7Lj1SXVm8swNPO8HL1BxxdgcA'; | |
| const BASE_URL = 'https://www.googleapis.com/youtube/v3'; | |
| let videos = []; | |
| const menuToggle = document.getElementById('menu-toggle'); | |
| const sidebar = document.getElementById('sidebar'); | |
| const overlay = document.getElementById('overlay'); | |
| const searchInput = document.querySelector('input[type="text"]'); | |
| const searchBtn = document.querySelector('.bg-gray-700'); | |
| // Initialize | |
| fetchTrendingVideos(); | |
| // Event listeners | |
| menuToggle.addEventListener('click', toggleSidebar); | |
| overlay.addEventListener('click', closeSidebar); | |
| searchBtn.addEventListener('click', searchVideos); | |
| searchInput.addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') searchVideos(); | |
| }); | |
| // API Functions | |
| async function fetchTrendingVideos() { | |
| try { | |
| const response = await fetch(`${BASE_URL}/videos?part=snippet,statistics&chart=mostPopular&maxResults=50&key=${API_KEY}`); | |
| const data = await response.json(); | |
| videos = data.items; | |
| displayVideos(videos); | |
| } catch (error) { | |
| console.error('Error fetching trending videos:', error); | |
| } | |
| } | |
| async function searchVideos() { | |
| const query = searchInput.value.trim(); | |
| if (!query) return; | |
| try { | |
| const response = await fetch(`${BASE_URL}/search?part=snippet&q=${encodeURIComponent(query)}&type=video&maxResults=50&key=${API_KEY}`); | |
| const data = await response.json(); | |
| // Fetch full video details | |
| const videoIds = data.items.map(item => item.id.videoId).join(','); | |
| const videoResponse = await fetch(`${BASE_URL}/videos?part=snippet,statistics&id=${videoIds}&key=${API_KEY}`); | |
| const videoData = await videoResponse.json(); | |
| videos = videoData.items; | |
| displayVideos(videos); | |
| } catch (error) { | |
| console.error('Error searching videos:', error); | |
| } | |
| } | |
| function displayVideos(videos) { | |
| const grid = document.querySelector('.grid'); | |
| grid.innerHTML = ''; | |
| videos.forEach(video => { | |
| const videoEl = createVideoElement(video); | |
| grid.appendChild(videoEl); | |
| }); | |
| } | |
| function createVideoElement(video) { | |
| const div = document.createElement('div'); | |
| div.className = 'video-card cursor-pointer'; | |
| const videoId = video.id?.videoId || video.id; | |
| const thumbnail = video.snippet.thumbnails?.high?.url || video.snippet.thumbnails?.medium?.url || 'https://via.placeholder.com/400x225'; | |
| const title = video.snippet?.title || 'Titre non disponible'; | |
| const channel = video.snippet?.channelTitle || 'Chaîne inconnue'; | |
| const views = formatViews(video.statistics?.viewCount || 0); | |
| const date = video.snippet?.publishedAt ? formatDate(video.snippet.publishedAt) : 'Date inconnue'; | |
| div.innerHTML = ` | |
| <div class="video-thumbnail relative"> | |
| <img src="${thumbnail}" alt="${title}" class="w-full rounded-lg"> | |
| <span class="absolute bottom-2 right-2 bg-black bg-opacity-75 px-2 py-1 text-xs rounded">10:30</span> | |
| </div> | |
| <div class="flex mt-3"> | |
| <img src="https://via.placeholder.com/36" alt="${channel}" class="w-9 h-9 rounded-full mr-3"> | |
| <div> | |
| <h3 class="font-semibold text-sm line-clamp-2">${title}</h3> | |
| <p class="text-sm text-gray-400 mt-1">${channel}</p> | |
| <p class="text-sm text-gray-400">${views} vues • ${date}</p> | |
| </div> | |
| </div> | |
| `; | |
| div.addEventListener('click', () => { | |
| openVideoPlayer(videoId); | |
| }); | |
| return div; | |
| } | |
| function openVideoPlayer(videoId) { | |
| // Create modal for video player | |
| const modal = document.createElement('div'); | |
| modal.className = 'fixed inset-0 bg-black bg-opacity-90 z-[100] flex items-center justify-center'; | |
| modal.innerHTML = ` | |
| <div class="relative w-full max-w-4xl"> | |
| <button id="close-player" class="absolute -top-12 right-0 text-white text-2xl"> | |
| <i class="fas fa-times"></i> | |
| </button> | |
| <div class="aspect-video"> | |
| <iframe | |
| src="https://www.youtube.com/embed/${videoId}?autoplay=1" | |
| class="w-full h-full rounded-lg" | |
| frameborder="0" | |
| allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" | |
| allowfullscreen> | |
| </iframe> | |
| </div> | |
| </div> | |
| `; | |
| document.body.appendChild(modal); | |
| // Close modal event | |
| document.getElementById('close-player').addEventListener('click', () => { | |
| document.body.removeChild(modal); | |
| }); | |
| // Close on backdrop click | |
| modal.addEventListener('click', (e) => { | |
| if (e.target === modal) { | |
| document.body.removeChild(modal); | |
| } | |
| }); | |
| } | |
| function formatViews(views) { | |
| if (views >= 1000000) { | |
| return (views / 1000000).toFixed(1) + 'M'; | |
| } else if (views >= 1000) { | |
| return (views / 1000).toFixed(1) + 'K'; | |
| } | |
| return views.toString(); | |
| } | |
| function formatDate(dateString) { | |
| const date = new Date(dateString); | |
| const now = new Date(); | |
| const diffTime = Math.abs(now - date); | |
| const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); | |
| if (diffDays === 1) return 'il y a 1 jour'; | |
| if (diffDays < 7) return `il y a ${diffDays} jours`; | |
| if (diffDays < 30) return `il y a ${Math.floor(diffDays / 7)} semaines`; | |
| return `il y a ${Math.floor(diffDays / 30)} mois`; | |
| } | |
| function formatDuration(duration) { | |
| const match = duration.match(/PT(\d+H)?(\d+M)?(\d+S)?/); | |
| const hours = parseInt(match[1]) || 0; | |
| const minutes = parseInt(match[2]) || 0; | |
| const seconds = parseInt(match[3]) || 0; | |
| if (hours > 0) { | |
| return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; | |
| } | |
| return `${minutes}:${seconds.toString().padStart(2, '0')}`; | |
| } | |
| function toggleSidebar() { | |
| sidebar.classList.toggle('open'); | |
| overlay.classList.toggle('hidden'); | |
| } | |
| function closeSidebar() { | |
| sidebar.classList.remove('open'); | |
| overlay.classList.add('hidden'); | |
| } | |
| window.addEventListener('resize', function() { | |
| if (window.innerWidth >= 768) { | |
| sidebar.classList.remove('open'); | |
| overlay.classList.add('hidden'); | |
| } | |
| }); | |
| function handleResize() { | |
| const main = document.querySelector('main'); | |
| if (window.innerWidth >= 768) { | |
| main.style.marginLeft = '256px'; | |
| } else { | |
| main.style.marginLeft = '0'; | |
| } | |
| } | |
| window.addEventListener('resize', handleResize); | |
| handleResize(); | |
| </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=Bridon/youtubeclone" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |