import videojs from 'video.js'; import './SeekIndicator.css'; const Component = videojs.getComponent('Component'); // Custom Seek Indicator Component for showing visual feedback during arrow key seeking class SeekIndicator extends Component { constructor(player, options) { super(player, options); this.seekAmount = options.seekAmount || 5; // Default seek amount in seconds this.isEmbedPlayer = options.isEmbedPlayer || false; // Store embed mode flag this.showTimeout = null; } createEl() { const el = super.createEl('div', { className: 'vjs-seek-indicator', }); // Create the indicator content el.innerHTML = `
`; // Initially hide the indicator completely el.style.display = 'none'; el.style.opacity = '0'; el.style.visibility = 'hidden'; return el; } /** * Show seek indicator with direction and amount * @param {string} direction - 'forward', 'backward', 'play', or 'pause' * @param {number} seconds - Number of seconds to seek (only used for forward/backward) */ show(direction, seconds = this.seekAmount) { const el = this.el(); const iconEl = el.querySelector('.vjs-seek-indicator-icon'); const textEl = el.querySelector('.vjs-seek-indicator-text'); // Clear any existing timeout if (this.showTimeout) { clearTimeout(this.showTimeout); } // Set content based on direction - YouTube-style circular design if (direction === 'forward') { iconEl.innerHTML = `
${seconds} seconds
`; } else if (direction === 'backward') { iconEl.innerHTML = `
${seconds} seconds
`; } else if (direction === 'play') { iconEl.innerHTML = `
`; textEl.textContent = 'Play'; } else if (direction === 'pause') { iconEl.innerHTML = `
`; textEl.textContent = 'Pause'; } // Clear any text content in the text element textEl.textContent = ''; // Position relative to video player container, not viewport el.style.cssText = ` position: absolute !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; z-index: 10000 !important; display: flex !important; align-items: center !important; justify-content: center !important; visibility: visible !important; opacity: 1 !important; pointer-events: none !important; width: auto !important; height: auto !important; margin: 0 !important; padding: 0 !important; `; // Auto-hide after 1 second this.showTimeout = setTimeout(() => { this.hide(); }, 1000); } /** * Hide the seek indicator */ hide() { const el = this.el(); el.style.opacity = '0'; setTimeout(() => { el.style.display = 'none'; el.style.visibility = 'hidden'; }, 200); // Wait for fade out animation } /** * Clean up when component is disposed */ dispose() { if (this.showTimeout) { clearTimeout(this.showTimeout); } super.dispose(); } } // Register the component with Video.js videojs.registerComponent('SeekIndicator', SeekIndicator); export default SeekIndicator;