mirror of
https://github.com/mediacms-io/mediacms.git
synced 2026-02-04 22:42:59 -05:00
184 lines
5.1 KiB
JavaScript
184 lines
5.1 KiB
JavaScript
/**
|
|
* KeyboardHandler - Utility for handling video player keyboard controls
|
|
*
|
|
* Provides comprehensive keyboard event handling for video players including:
|
|
* - Space bar for play/pause
|
|
* - Arrow keys for seeking
|
|
* - Input field detection to avoid conflicts
|
|
*/
|
|
|
|
class KeyboardHandler {
|
|
constructor(playerRef, customComponents = null, options = {}) {
|
|
this.playerRef = playerRef;
|
|
this.customComponents = customComponents;
|
|
this.options = {
|
|
seekAmount: 5, // Default seek amount in seconds
|
|
...options,
|
|
};
|
|
this.eventHandler = null;
|
|
this.isActive = false;
|
|
}
|
|
|
|
/**
|
|
* Check if an input element is currently focused
|
|
* @returns {boolean} True if an input element has focus
|
|
*/
|
|
isInputFocused() {
|
|
const activeElement = document.activeElement;
|
|
return (
|
|
activeElement &&
|
|
(activeElement.tagName === 'INPUT' ||
|
|
activeElement.tagName === 'TEXTAREA' ||
|
|
activeElement.contentEditable === 'true')
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Handle space key for play/pause functionality
|
|
* @param {KeyboardEvent} event - The keyboard event
|
|
*/
|
|
handleSpaceKey(event) {
|
|
if (event.code === 'Space' || event.key === ' ') {
|
|
event.preventDefault();
|
|
if (this.playerRef.current) {
|
|
if (this.playerRef.current.paused()) {
|
|
this.playerRef.current.play();
|
|
} else {
|
|
this.playerRef.current.pause();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Handle arrow keys for seeking functionality
|
|
* @param {KeyboardEvent} event - The keyboard event
|
|
*/
|
|
handleArrowKeys(event) {
|
|
const { seekAmount } = this.options;
|
|
|
|
if (event.key === 'ArrowRight' || event.keyCode === 39) {
|
|
event.preventDefault();
|
|
this.seekForward(seekAmount);
|
|
return true;
|
|
} else if (event.key === 'ArrowLeft' || event.keyCode === 37) {
|
|
event.preventDefault();
|
|
this.seekBackward(seekAmount);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Seek forward by specified amount
|
|
* @param {number} amount - Seconds to seek forward
|
|
*/
|
|
seekForward(amount) {
|
|
if (!this.playerRef.current) return;
|
|
|
|
const currentTime = this.playerRef.current.currentTime();
|
|
const duration = this.playerRef.current.duration();
|
|
const newTime = Math.min(currentTime + amount, duration);
|
|
|
|
this.playerRef.current.currentTime(newTime);
|
|
|
|
// Show seek indicator if available
|
|
if (this.customComponents?.current?.seekIndicator) {
|
|
this.customComponents.current.seekIndicator.show('forward', amount);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Seek backward by specified amount
|
|
* @param {number} amount - Seconds to seek backward
|
|
*/
|
|
seekBackward(amount) {
|
|
if (!this.playerRef.current) return;
|
|
|
|
const currentTime = this.playerRef.current.currentTime();
|
|
const newTime = Math.max(currentTime - amount, 0);
|
|
|
|
this.playerRef.current.currentTime(newTime);
|
|
|
|
// Show seek indicator if available
|
|
if (this.customComponents?.current?.seekIndicator) {
|
|
this.customComponents.current.seekIndicator.show('backward', amount);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Main keyboard event handler
|
|
* @param {KeyboardEvent} event - The keyboard event
|
|
*/
|
|
handleKeyboardEvent = (event) => {
|
|
// Only handle if no input elements are focused
|
|
if (this.isInputFocused()) {
|
|
return; // Don't interfere with input fields
|
|
}
|
|
|
|
// Handle space key for play/pause
|
|
if (this.handleSpaceKey(event)) {
|
|
return;
|
|
}
|
|
|
|
// Handle arrow keys for seeking
|
|
if (this.handleArrowKeys(event)) {
|
|
return;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Initialize keyboard event handling
|
|
*/
|
|
init() {
|
|
if (this.isActive) {
|
|
console.warn('KeyboardHandler is already active');
|
|
return;
|
|
}
|
|
|
|
// Add keyboard event listener to the document
|
|
document.addEventListener('keydown', this.handleKeyboardEvent);
|
|
this.isActive = true;
|
|
}
|
|
|
|
/**
|
|
* Clean up keyboard event handling
|
|
*/
|
|
destroy() {
|
|
if (!this.isActive) {
|
|
return;
|
|
}
|
|
|
|
document.removeEventListener('keydown', this.handleKeyboardEvent);
|
|
this.isActive = false;
|
|
}
|
|
|
|
/**
|
|
* Update options
|
|
* @param {Object} newOptions - New options to merge
|
|
*/
|
|
updateOptions(newOptions) {
|
|
this.options = { ...this.options, ...newOptions };
|
|
}
|
|
|
|
/**
|
|
* Update player reference
|
|
* @param {Object} newPlayerRef - New player reference
|
|
*/
|
|
updatePlayerRef(newPlayerRef) {
|
|
this.playerRef = newPlayerRef;
|
|
}
|
|
|
|
/**
|
|
* Update custom components reference
|
|
* @param {Object} newCustomComponents - New custom components reference
|
|
*/
|
|
updateCustomComponents(newCustomComponents) {
|
|
this.customComponents = newCustomComponents;
|
|
}
|
|
}
|
|
|
|
export default KeyboardHandler;
|