Spaces:
No application file
No application file
| // Video Player Application | |
| document.addEventListener('DOMContentLoaded', function() { | |
| const video = document.getElementById('videoPlayer'); | |
| const playlist = document.getElementById('playlist'); | |
| const overlay = document.getElementById('videoOverlay'); | |
| const currentTitle = document.getElementById('currentTitle'); | |
| const playPauseBtn = document.getElementById('playPauseBtn'); | |
| const prevBtn = document.getElementById('prevBtn'); | |
| const nextBtn = document.getElementById('nextBtn'); | |
| const muteBtn = document.getElementById('muteBtn'); | |
| const volumeSlider = document.getElementById('volumeSlider'); | |
| const fullscreenBtn = document.getElementById('fullscreenBtn'); | |
| let videos = []; | |
| let currentIndex = -1; | |
| // Load playlist from API | |
| async function loadPlaylist() { | |
| try { | |
| const response = await fetch('/api/playlist'); | |
| const data = await response.json(); | |
| videos = data.videos; | |
| renderPlaylist(); | |
| } catch (error) { | |
| console.error('Failed to load playlist:', error); | |
| playlist.innerHTML = ` | |
| <div class="empty-playlist"> | |
| <span>β</span> | |
| <p>Failed to load playlist</p> | |
| </div> | |
| `; | |
| } | |
| } | |
| // Render playlist items | |
| function renderPlaylist() { | |
| if (videos.length === 0) { | |
| playlist.innerHTML = ` | |
| <div class="empty-playlist"> | |
| <span>π</span> | |
| <p>No videos found in playlist folder</p> | |
| </div> | |
| `; | |
| return; | |
| } | |
| playlist.innerHTML = videos.map((video, index) => ` | |
| <div class="playlist-item ${index === currentIndex ? 'active' : ''}" | |
| data-index="${index}" | |
| onclick="playVideo(${index})"> | |
| <span class="item-icon">π¬</span> | |
| <div class="item-info"> | |
| <div class="item-title" title="${video.name}">${video.title}</div> | |
| <div class="item-size">${video.size_human}</div> | |
| </div> | |
| </div> | |
| `).join(''); | |
| } | |
| // Play video at index | |
| window.playVideo = function(index) { | |
| if (index < 0 || index >= videos.length) return; | |
| currentIndex = index; | |
| const videoData = videos[index]; | |
| video.src = videoData.path; | |
| video.load(); | |
| video.play().catch(e => console.log('Autoplay prevented:', e)); | |
| currentTitle.textContent = videoData.title; | |
| overlay.classList.add('hidden'); | |
| // Update playlist highlight | |
| document.querySelectorAll('.playlist-item').forEach((item, i) => { | |
| item.classList.toggle('active', i === index); | |
| }); | |
| updatePlayPauseButton(); | |
| }; | |
| // Play/Pause toggle | |
| function togglePlayPause() { | |
| if (video.paused) { | |
| video.play().catch(e => console.log('Play failed:', e)); | |
| } else { | |
| video.pause(); | |
| } | |
| } | |
| // Update play/pause button icon | |
| function updatePlayPauseButton() { | |
| playPauseBtn.textContent = video.paused ? 'βΆ' : 'βΈ'; | |
| } | |
| // Play previous video | |
| function playPrevious() { | |
| if (videos.length === 0) return; | |
| const newIndex = currentIndex > 0 ? currentIndex - 1 : videos.length - 1; | |
| playVideo(newIndex); | |
| } | |
| // Play next video | |
| function playNext() { | |
| if (videos.length === 0) return; | |
| const newIndex = currentIndex < videos.length - 1 ? currentIndex + 1 : 0; | |
| playVideo(newIndex); | |
| } | |
| // Toggle mute | |
| function toggleMute() { | |
| video.muted = !video.muted; | |
| muteBtn.textContent = video.muted ? 'π' : 'π'; | |
| volumeSlider.value = video.muted ? 0 : video.volume; | |
| } | |
| // Update volume | |
| function updateVolume() { | |
| video.volume = volumeSlider.value; | |
| video.muted = video.volume === 0; | |
| muteBtn.textContent = video.muted ? 'π' : 'π'; | |
| } | |
| // Toggle fullscreen | |
| function toggleFullscreen() { | |
| const container = document.querySelector('.video-container'); | |
| if (document.fullscreenElement) { | |
| document.exitFullscreen(); | |
| } else if (container.requestFullscreen) { | |
| container.requestFullscreen(); | |
| } else if (container.webkitRequestFullscreen) { | |
| container.webkitRequestFullscreen(); | |
| } | |
| } | |
| // Event listeners | |
| playPauseBtn.addEventListener('click', togglePlayPause); | |
| prevBtn.addEventListener('click', playPrevious); | |
| nextBtn.addEventListener('click', playNext); | |
| muteBtn.addEventListener('click', toggleMute); | |
| volumeSlider.addEventListener('input', updateVolume); | |
| fullscreenBtn.addEventListener('click', toggleFullscreen); | |
| video.addEventListener('play', updatePlayPauseButton); | |
| video.addEventListener('pause', updatePlayPauseButton); | |
| video.addEventListener('ended', playNext); | |
| // Keyboard shortcuts | |
| document.addEventListener('keydown', function(e) { | |
| if (e.target.tagName === 'INPUT') return; | |
| switch(e.key) { | |
| case ' ': | |
| case 'k': | |
| e.preventDefault(); | |
| togglePlayPause(); | |
| break; | |
| case 'ArrowLeft': | |
| e.preventDefault(); | |
| video.currentTime = Math.max(0, video.currentTime - 10); | |
| break; | |
| case 'ArrowRight': | |
| e.preventDefault(); | |
| video.currentTime = Math.min(video.duration, video.currentTime + 10); | |
| break; | |
| case 'ArrowUp': | |
| e.preventDefault(); | |
| video.volume = Math.min(1, video.volume + 0.1); | |
| volumeSlider.value = video.volume; | |
| break; | |
| case 'ArrowDown': | |
| e.preventDefault(); | |
| video.volume = Math.max(0, video.volume - 0.1); | |
| volumeSlider.value = video.volume; | |
| break; | |
| case 'f': | |
| e.preventDefault(); | |
| toggleFullscreen(); | |
| break; | |
| case 'm': | |
| e.preventDefault(); | |
| toggleMute(); | |
| break; | |
| case 'n': | |
| e.preventDefault(); | |
| playNext(); | |
| break; | |
| case 'p': | |
| e.preventDefault(); | |
| playPrevious(); | |
| break; | |
| } | |
| }); | |
| // Initialize | |
| loadPlaylist(); | |
| }); | |