UNPKG

spectatr-player-sdk

Version:

A custom video player built with Stencil with Shaka Player integration

343 lines (339 loc) 13.3 kB
import { j as addReaction } from './p-Bqc1mM21.js'; function setupTracks(component) { const { player } = component; if (!player) return; const audioTracks = player.getAudioTracks(); // Use a Map to store the first occurrence of each language const uniqueLanguageTracks = new Map(); audioTracks.forEach(track => { const language = track.language; if (!uniqueLanguageTracks.has(language)) { uniqueLanguageTracks.set(language, { index: track.id, language: language, label: track.label || `Audio ${language}`, enabled: track.active, }); } }); // Convert Map values back to an array component.audioTracks = Array.from(uniqueLanguageTracks.values()); // Set the first track as active (or keep existing logic) component.currentAudioTrack = 0; setupQualityTrack(component); } function setupQualityTrack(component) { const { player } = component; if (!player) return; const tracks = player.getVariantTracks(); component.qualities = tracks .filter(track => !track.label || track.label === component.audioTracks[component.currentAudioTrack]?.label) .reduce((unique, track) => { const qualityLabel = track.height ? `${track.height}p` : `${Math.floor(track.bandwidth / 1000)}kbps`; unique.push({ index: track.id, height: track.height, bitrate: track.bandwidth, name: qualityLabel, }); return unique; }, []); component.currentQuality = -1; } function togglePlay(component) { const video = component.videoElement; if (video.paused) { video.play(); component.playVideo.emit(); window.parent.postMessage({ type: 'ON_VIDEO_PLAY', }, '*'); } else { video.pause(); component.pauseVideo.emit(); window.parent.postMessage({ type: 'ON_VIDEO_PAUSE', }, '*'); } } function toggleMute(component) { component.videoElement.muted = !component.videoElement.muted; } function setVolume(component, volume) { if (volume !== 0 && component.videoElement.muted) { component.videoElement.muted = false; } component.videoElement.volume = volume; } function seek(component, time) { if (component.isLive) { const dvrStartTime = component.player.seekRange().start; component.videoElement.currentTime = Math.max(time, dvrStartTime); component.currentTime = component.videoElement.currentTime; } else { component.videoElement.currentTime = time; component.currentTime = time; } } function skipForward(component) { component.videoElement.currentTime = Math.min(component.duration, component.videoElement.currentTime + 10); } function skipBackward(component) { let seekToTime = component.videoElement.currentTime - 10; if (component.isLive) { const dvrStartTime = component.player.seekRange().start; if (seekToTime < dvrStartTime) { seekToTime = dvrStartTime; } } component.videoElement.currentTime = seekToTime; } const toggleFullscreen = (component) => { // Get the video container directly from the component reference const videoContainer = component.videoContainer; if (!videoContainer) { console.error('Video container element not found'); component.videoError.emit('Video container element not found'); return; } if (!document.fullscreenElement) { // Enter fullscreen if (videoContainer.requestFullscreen) { videoContainer .requestFullscreen() .then(() => { component.isFullscreen = true; }) .catch(err => { console.error('Error attempting to enable fullscreen:', err); component.videoError.emit('Error attempting to enable fullscreen'); }); } } else { // Exit fullscreen if (document.exitFullscreen) { document .exitFullscreen() .then(() => { component.isFullscreen = false; }) .catch(err => { console.error('Error attempting to exit fullscreen:', err); component.videoError.emit('Error attempting to exit fullscreen'); }); } } }; function startProgressUpdate(component) { component.progressUpdateInterval = setInterval(() => { component.currentTime = component.videoElement.currentTime; }, 100); } function stopProgressUpdate(component) { if (component.progressUpdateInterval) { clearInterval(component.progressUpdateInterval); } } async function setQuality(component, qualityIndex) { if (!component.player) return; if (qualityIndex === -1) { // Auto quality component.player.configure({ abr: { enabled: true } }); } else { // Specific quality component.player.configure({ abr: { enabled: false } }); const tracks = component.player.getVariantTracks().filter(track => !track.label || track.label === component.audioTracks[component.currentAudioTrack]?.label); component.player.selectVariantTrack(tracks[qualityIndex], true); } component.currentQuality = qualityIndex; } function setAudioTrack(component, trackIndex) { if (!component.player) return; const audioTracks = component.player.getAudioTracks(); if (audioTracks[trackIndex]) { component.player.selectAudioTrack(audioTracks[trackIndex]); component.currentAudioTrack = trackIndex; setupQualityTrack(component); } } function toggleSettings(component, e) { e.stopPropagation(); // Prevent component click from triggering the outside click handler component.showSettings = !component.showSettings; if (component.showSettings) { component.showMainSettings = true; component.showQualityOptions = false; component.showAudioOptions = false; } } function handleGoLive(component) { component.duration = component.player.seekRange().end; component.videoElement.currentTime = component.duration; } function handleClickOutsideSetting(component, event) { if (!component.showSettings) return; const settingsMenu = component.hostElement.shadowRoot?.querySelector('.settings-menu'); const settingsButton = component.hostElement.shadowRoot?.querySelector('.control-btn'); // Check if click was outside both the menu and the settings button const clickedInsideMenu = settingsMenu?.contains(event.target); const clickedSettingsButton = settingsButton?.contains(event.target); if (!clickedInsideMenu && !clickedSettingsButton) { component.showSettings = false; component.showQualityOptions = false; component.showAudioOptions = false; } } function shouldShowToggle(component) { // Only show toggle if description is longer than 2 lines return component.videoDescription.length > 200; // Adjust this threshold as needed } function toggleDescription(component) { component.showFullDescription = !component.showFullDescription; } async function toggleLike(component) { try { component.isLiked = !component.isLiked; component.isDisliked = false; component.totalLikes = component.isLiked ? component.totalLikes + 1 : component.totalLikes - 1; await addReaction(component, 'like'); } catch (error) { component.isLiked = !component.isLiked; component.isDisliked = false; component.totalLikes = component.isLiked ? component.totalLikes + 1 : component.totalLikes - 1; console.error('like toggle failed:', error); component.videoError.emit('React to video failed'); } } async function toggleDislike(component) { const wasLiked = component.isLiked; const wasDisliked = component.isDisliked; const originalLikes = component.totalLikes; try { if (component.isLiked) { component.isLiked = false; component.totalLikes--; } component.isDisliked = !component.isDisliked; await addReaction(component, 'dislike'); } catch (error) { component.isLiked = wasLiked; component.isDisliked = wasDisliked; component.totalLikes = originalLikes; console.error('Dislike toggle failed:', error); component.videoError.emit('React to video failed'); } } function formatTimeAgo(createdAt) { const date = new Date(createdAt); const now = new Date(); const seconds = Math.floor((now.getTime() - date.getTime()) / 1000); const intervals = { year: 31536000, month: 2592000, week: 604800, day: 86400, hour: 3600, minute: 60, second: 1, }; for (const [unit, secondsInUnit] of Object.entries(intervals)) { const interval = Math.floor(seconds / secondsInUnit); if (interval >= 1) { return new Intl.RelativeTimeFormat('en', { numeric: 'auto' }).format(-interval, unit); } } return 'just now'; } function formatLikeCount(count) { return Math.abs(count) >= 1e9 ? (count / 1e9).toFixed(1).replace(/\.0$/, '') + 'B' : Math.abs(count) >= 1e6 ? (count / 1e6).toFixed(1).replace(/\.0$/, '') + 'M' : Math.abs(count) >= 1e3 ? (count / 1e3).toFixed(1).replace(/\.0$/, '') + 'K' : count.toString(); } function getUserUUID(userId) { if (userId) return userId; if (localStorage.getItem('spactatr_user_id')) { return localStorage.getItem('spactatr_user_id'); } else { const id = crypto.randomUUID(); localStorage.setItem('spactatr_user_id', id); return id; } } function cleanupData(component) { component.src = null; component.token = null; component.videoDescription = ''; component.videoTitle = ''; component.isLoading = true; component.showPoll = false; component.showQuiz = false; component.pollAnswered = []; component.quizAnswered = []; component.quizzes = null; component.timelineEvents = []; component.isLive = false; component.currentTime = 0; component.duration = 0; clearTimeout(component.controlsTimeout); clearInterval(component.progressUpdateInterval); clearInterval(component.livePollingInterval); clearInterval(component.reactionPollingInterval); } function applyTheme(themeId, root) { switch (themeId) { case 'minimal-dark': //pass root.style.setProperty('--vp-primary-bg', '#121212'); root.style.setProperty('--vp-controls-bg', 'rgba(0, 0, 0, 0.7)'); root.style.setProperty('--vp-accent', '#ff5555'); root.style.setProperty('--vp-video-text', '#ffffff'); root.style.setProperty('--vp-text', '#ffffff'); break; case 'minimal-light': //pass root.style.setProperty('--vp-primary-bg', '#f8f8f8'); root.style.setProperty('--vp-controls-bg', 'rgba(48, 48, 48, 0.7)'); root.style.setProperty('--vp-accent', '#e53e3e'); // Deep red for contrast root.style.setProperty('--vp-video-text', '#ffffff'); root.style.setProperty('--vp-text', '#1a202c'); break; case 'classic-youtube': //pass root.style.setProperty('--vp-primary-bg', '#f9f9f9'); root.style.setProperty('--vp-controls-bg', 'rgba(0, 0, 0, 0.7)'); root.style.setProperty('--vp-accent', '#065fd4'); root.style.setProperty('--vp-video-text', '#ffffff'); root.style.setProperty('--vp-text', '#000'); break; case 'cinema-mode': //pass root.style.setProperty('--vp-primary-bg', '#f9f9f9'); root.style.setProperty('--vp-controls-bg', 'rgba(156, 3, 29, 0.45)'); root.style.setProperty('--vp-accent', '#cd2843ff'); root.style.setProperty('--vp-video-text', '#ffffff'); root.style.setProperty('--vp-text', '#000'); break; case 'true-back': //pass root.style.setProperty('--vp-primary-bg', '#000000'); root.style.setProperty('--vp-controls-bg', 'rgba(255, 255, 255, 0.3)'); root.style.setProperty('--vp-accent', '#000000'); root.style.setProperty('--vp-video-text', '#ffffff'); root.style.setProperty('--vp-text', '#aaaaaa'); break; } } export { applyTheme as a, stopProgressUpdate as b, setupTracks as c, cleanupData as d, toggleDislike as e, formatLikeCount as f, getUserUUID as g, handleClickOutsideSetting as h, formatTimeAgo as i, shouldShowToggle as j, toggleDescription as k, skipBackward as l, togglePlay as m, skipForward as n, toggleMute as o, setVolume as p, toggleSettings as q, toggleFullscreen as r, startProgressUpdate as s, toggleLike as t, handleGoLive as u, seek as v, setQuality as w, setAudioTrack as x }; //# sourceMappingURL=p-CjB1Ea9v.js.map //# sourceMappingURL=p-CjB1Ea9v.js.map