mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-07 16:08:54 -05:00
feat: Create the component CustomRemainingTime
This commit is contained in:
parent
b314f7d628
commit
3d08f3b29f
@ -35,15 +35,6 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Responsive App container */
|
||||
.App {
|
||||
width: 100%;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Ensure video.js responsive behavior */
|
||||
.video-js.vjs-fluid {
|
||||
width: 100% !important;
|
||||
@ -248,9 +239,8 @@
|
||||
|
||||
.vjs-chapter-floating-tooltip {
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif !important;
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans",
|
||||
"Droid Sans", "Helvetica Neue", sans-serif !important;
|
||||
line-height: 1.4 !important;
|
||||
animation: fadeIn 0.2s ease-in-out;
|
||||
}
|
||||
@ -353,3 +343,106 @@
|
||||
font-size: 12px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Played portion, buffered portion, unplayed portion */
|
||||
.vjs-play-progress {
|
||||
background-color: #019932 !important;
|
||||
}
|
||||
.vjs-load-progress {
|
||||
background: rgba(255, 255, 255, 0.5) !important;
|
||||
}
|
||||
.vjs-progress-holder {
|
||||
background: rgba(255, 255, 255, 0.5) !important;
|
||||
}
|
||||
|
||||
/* Move progress control out of control bar and position it above */
|
||||
.video-js .vjs-progress-control {
|
||||
position: absolute !important;
|
||||
bottom: 46px !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
width: 100% !important;
|
||||
height: 0 !important;
|
||||
z-index: 3 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
/* Hide the original progress control from the control bar */
|
||||
.video-js .vjs-control-bar .vjs-progress-control {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Optional: Ensure the progress control is visible */
|
||||
.video-js .vjs-progress-control.vjs-control {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
/* Make the seek bar thicker */
|
||||
/* .video-js .vjs-play-progress,
|
||||
.video-js .vjs-load-progress,
|
||||
.video-js .vjs-progress-holder {
|
||||
height: 4px !important;
|
||||
} */
|
||||
|
||||
/* Remove the semi-transparent background from control bar */
|
||||
.video-js .vjs-control-bar {
|
||||
background: transparent !important;
|
||||
background-color: transparent !important;
|
||||
background-image: none !important;
|
||||
display: flex !important;
|
||||
flex-direction: row !important;
|
||||
align-items: center !important;
|
||||
justify-content: flex-start !important;
|
||||
gap: 6px !important;
|
||||
}
|
||||
|
||||
/* Push specific buttons to the right */
|
||||
.video-js .vjs-playback-rate,
|
||||
.video-js .vjs-picture-in-picture-control,
|
||||
.video-js .vjs-fullscreen-control {
|
||||
margin-left: auto !important;
|
||||
order: 999 !important;
|
||||
}
|
||||
.video-js .vjs-picture-in-picture-control {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
.video-js .vjs-fullscreen-control {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
/* Make all control bar icons bigger */
|
||||
.video-js .vjs-control-bar .vjs-icon-placeholder,
|
||||
.video-js .vjs-control-bar .vjs-button .vjs-icon-placeholder,
|
||||
.video-js .vjs-control-bar [class*="vjs-icon-"] {
|
||||
font-size: 1.5em !important; /* 1.5x bigger */
|
||||
transform: translateY(-28px) !important; /* Move icons up by 3px */
|
||||
}
|
||||
.video-js .vjs-control-bar svg {
|
||||
width: 3em !important;
|
||||
height: 3em !important;
|
||||
transform: translateY(-16px) !important;
|
||||
}
|
||||
|
||||
/******** BEGIN: Custom Remaining Time Styles *********/
|
||||
.vjs-control-bar .custom-remaining-time .vjs-remaining-time-display {
|
||||
font-size: 14px !important; /* Increase font size */
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Ensure proper vertical alignment within control bar */
|
||||
.vjs-control-bar .custom-remaining-time {
|
||||
top: -5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/********* END: Custom Remaining Time Styles *********/
|
||||
|
||||
@ -0,0 +1,106 @@
|
||||
// components/controls/CustomRemainingTime.js
|
||||
import videojs from 'video.js';
|
||||
|
||||
// Get the Component base class from Video.js
|
||||
const Component = videojs.getComponent('Component');
|
||||
|
||||
class CustomRemainingTime extends Component {
|
||||
constructor(player, options) {
|
||||
super(player, options);
|
||||
|
||||
// Bind methods to ensure correct 'this' context
|
||||
this.updateContent = this.updateContent.bind(this);
|
||||
|
||||
// Set up event listeners
|
||||
this.on(player, 'timeupdate', this.updateContent);
|
||||
this.on(player, 'durationchange', this.updateContent);
|
||||
this.on(player, 'loadedmetadata', this.updateContent);
|
||||
|
||||
// Store custom options
|
||||
this.options_ = {
|
||||
displayNegative: false,
|
||||
customPrefix: '',
|
||||
customSuffix: '',
|
||||
...options,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the component's DOM element
|
||||
*/
|
||||
createEl() {
|
||||
const el = videojs.dom.createEl('div', {
|
||||
className: 'vjs-remaining-time vjs-time-control vjs-control custom-remaining-time',
|
||||
});
|
||||
|
||||
// Add ARIA accessibility
|
||||
el.innerHTML = `
|
||||
<span class="vjs-control-text" role="presentation">Time Display </span>
|
||||
<span class="vjs-remaining-time-display" role="presentation">0:00 / 0:00</span>
|
||||
`;
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the time display
|
||||
*/
|
||||
updateContent() {
|
||||
const player = this.player();
|
||||
const currentTime = player.currentTime();
|
||||
const duration = player.duration();
|
||||
|
||||
const display = this.el().querySelector('.vjs-remaining-time-display');
|
||||
|
||||
if (display) {
|
||||
const formattedCurrentTime = this.formatTime(isNaN(currentTime) ? 0 : currentTime);
|
||||
const formattedDuration = this.formatTime(isNaN(duration) ? 0 : duration);
|
||||
display.textContent = `${formattedCurrentTime} / ${formattedDuration}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time with custom logic
|
||||
*/
|
||||
formatTime(seconds) {
|
||||
const { customPrefix, customSuffix } = this.options_;
|
||||
|
||||
const hours = Math.floor(seconds / 3600);
|
||||
const minutes = Math.floor((seconds % 3600) / 60);
|
||||
const secs = Math.floor(seconds % 60);
|
||||
|
||||
let timeString;
|
||||
if (hours > 0) {
|
||||
timeString = `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
|
||||
} else {
|
||||
timeString = `${minutes}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
return `${customPrefix}${timeString}${customSuffix}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add click handler for additional functionality
|
||||
*/
|
||||
handleClick() {
|
||||
// Example: Toggle between different time formats
|
||||
console.log('Time display clicked');
|
||||
// Could toggle between current/duration vs remaining time
|
||||
}
|
||||
|
||||
/**
|
||||
* Component disposal cleanup
|
||||
*/
|
||||
dispose() {
|
||||
// Clean up any additional resources if needed
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Set component name for Video.js
|
||||
CustomRemainingTime.prototype.controlText_ = 'Time Display';
|
||||
|
||||
// Register the component with Video.js
|
||||
videojs.registerComponent('CustomRemainingTime', CustomRemainingTime);
|
||||
|
||||
export default CustomRemainingTime;
|
||||
@ -6,6 +6,7 @@ import 'video.js/dist/video-js.css';
|
||||
import EndScreenOverlay from '../overlays/EndScreenOverlay';
|
||||
import ChapterMarkers from '../markers/ChapterMarkers';
|
||||
import NextVideoButton from '../controls/NextVideoButton';
|
||||
import CustomRemainingTime from '../controls/CustomRemainingTime';
|
||||
|
||||
function VideoJSPlayer() {
|
||||
const videoRef = useRef(null);
|
||||
@ -47,9 +48,7 @@ function VideoJSPlayer() {
|
||||
sources: mediaData.data?.original_media_url
|
||||
? [
|
||||
{
|
||||
src:
|
||||
mediaData.siteUrl +
|
||||
mediaData.data.original_media_url,
|
||||
src: mediaData.siteUrl + mediaData.data.original_media_url,
|
||||
type: 'video/mp4',
|
||||
},
|
||||
]
|
||||
@ -155,11 +154,7 @@ function VideoJSPlayer() {
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
// Double-check that we still don't have a player and element exists
|
||||
if (
|
||||
!playerRef.current &&
|
||||
videoRef.current &&
|
||||
!videoRef.current.player
|
||||
) {
|
||||
if (!playerRef.current && videoRef.current && !videoRef.current.player) {
|
||||
playerRef.current = videojs(videoRef.current, {
|
||||
// ===== STANDARD <video> ELEMENT OPTIONS =====
|
||||
|
||||
@ -318,9 +313,7 @@ function VideoJSPlayer() {
|
||||
|
||||
// Function to override play/pause key (default: 'k' and Space)
|
||||
playPauseKey: function (event) {
|
||||
return (
|
||||
event.which === 75 || event.which === 32
|
||||
); // 'k' or Space
|
||||
return event.which === 75 || event.which === 32; // 'k' or Space
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -345,9 +338,10 @@ function VideoJSPlayer() {
|
||||
},
|
||||
},
|
||||
// Remaining time display configuration
|
||||
remainingTimeDisplay: {
|
||||
remainingTimeDisplay: false,
|
||||
/* remainingTimeDisplay: {
|
||||
displayNegative: true,
|
||||
},
|
||||
}, */
|
||||
|
||||
// Volume panel configuration
|
||||
volumePanel: {
|
||||
@ -425,22 +419,14 @@ function VideoJSPlayer() {
|
||||
// Event listeners
|
||||
playerRef.current.on('ready', () => {
|
||||
// Auto-play video when navigating from next button
|
||||
const urlParams = new URLSearchParams(
|
||||
window.location.search
|
||||
);
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const hasVideoParam = urlParams.get('m');
|
||||
if (hasVideoParam) {
|
||||
// Small delay to ensure everything is loaded
|
||||
setTimeout(() => {
|
||||
if (
|
||||
playerRef.current &&
|
||||
!playerRef.current.isDisposed()
|
||||
) {
|
||||
if (playerRef.current && !playerRef.current.isDisposed()) {
|
||||
playerRef.current.play().catch((error) => {
|
||||
console.log(
|
||||
'Autoplay was prevented:',
|
||||
error
|
||||
);
|
||||
console.log('Autoplay was prevented:', error);
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
@ -471,16 +457,11 @@ function VideoJSPlayer() {
|
||||
);
|
||||
|
||||
// Create a text track for chapters programmatically
|
||||
const chaptersTrack = playerRef.current.addTextTrack(
|
||||
'chapters',
|
||||
'Chapters',
|
||||
'en'
|
||||
);
|
||||
const chaptersTrack = playerRef.current.addTextTrack('chapters', 'Chapters', 'en');
|
||||
|
||||
// Add cues to the chapters track
|
||||
chaptersData.forEach((chapter) => {
|
||||
const cue = new (window.VTTCue ||
|
||||
window.TextTrackCue)(
|
||||
const cue = new (window.VTTCue || window.TextTrackCue)(
|
||||
chapter.startTime,
|
||||
chapter.endTime,
|
||||
chapter.text
|
||||
@ -494,44 +475,45 @@ function VideoJSPlayer() {
|
||||
.getChild('controlBar')
|
||||
.getChild('progressControl');
|
||||
if (progressControl) {
|
||||
const seekBar =
|
||||
progressControl.getChild('seekBar');
|
||||
const seekBar = progressControl.getChild('seekBar');
|
||||
if (seekBar) {
|
||||
const markers =
|
||||
seekBar.getChild('ChapterMarkers');
|
||||
if (
|
||||
markers &&
|
||||
markers.updateChapterMarkers
|
||||
) {
|
||||
const markers = seekBar.getChild('ChapterMarkers');
|
||||
if (markers && markers.updateChapterMarkers) {
|
||||
markers.updateChapterMarkers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
|
||||
console.log(
|
||||
'Subtitles loaded but disabled by default - use CC button to enable'
|
||||
);
|
||||
console.log('Subtitles loaded but disabled by default - use CC button to enable');
|
||||
});
|
||||
|
||||
// Add Next Video button to control bar and reorder chapters button
|
||||
playerRef.current.ready(() => {
|
||||
const controlBar =
|
||||
playerRef.current.getChild('controlBar');
|
||||
const nextVideoButton = new NextVideoButton(
|
||||
playerRef.current
|
||||
);
|
||||
|
||||
// Insert after play button
|
||||
const controlBar = playerRef.current.getChild('controlBar');
|
||||
const playToggle = controlBar.getChild('playToggle');
|
||||
const playToggleIndex = controlBar
|
||||
.children()
|
||||
.indexOf(playToggle);
|
||||
controlBar.addChild(
|
||||
nextVideoButton,
|
||||
{},
|
||||
playToggleIndex + 1
|
||||
);
|
||||
const currentTimeDisplay = controlBar.getChild('currentTimeDisplay');
|
||||
|
||||
// Implement custom time display component
|
||||
const customRemainingTime = new CustomRemainingTime(playerRef.current, {
|
||||
displayNegative: false,
|
||||
customPrefix: '',
|
||||
customSuffix: '',
|
||||
});
|
||||
|
||||
// Insert it in the desired position (e.g., after current time display)
|
||||
if (currentTimeDisplay) {
|
||||
const currentTimeIndex = controlBar.children().indexOf(currentTimeDisplay);
|
||||
controlBar.addChild(customRemainingTime, {}, currentTimeIndex + 1);
|
||||
} else {
|
||||
controlBar.addChild(customRemainingTime, {}, 2);
|
||||
}
|
||||
|
||||
// Implement custom next video button
|
||||
const nextVideoButton = new NextVideoButton(playerRef.current);
|
||||
|
||||
const playToggleIndex = controlBar.children().indexOf(playToggle); // Insert it after play button
|
||||
controlBar.addChild(nextVideoButton, {}, playToggleIndex + 1);
|
||||
|
||||
// Remove duplicate captions button and move chapters to end
|
||||
const cleanupControls = () => {
|
||||
@ -539,10 +521,7 @@ function VideoJSPlayer() {
|
||||
const allChildren = controlBar.children();
|
||||
|
||||
// Try to find and remove captions/subs-caps button (but keep subtitles)
|
||||
const possibleCaptionButtons = [
|
||||
'captionsButton',
|
||||
'subsCapsButton',
|
||||
];
|
||||
const possibleCaptionButtons = ['captionsButton', 'subsCapsButton'];
|
||||
possibleCaptionButtons.forEach((buttonName) => {
|
||||
const button = controlBar.getChild(buttonName);
|
||||
if (button) {
|
||||
@ -550,47 +529,29 @@ function VideoJSPlayer() {
|
||||
controlBar.removeChild(button);
|
||||
console.log(`✓ Removed ${buttonName}`);
|
||||
} catch (e) {
|
||||
console.log(
|
||||
`✗ Failed to remove ${buttonName}:`,
|
||||
e
|
||||
);
|
||||
console.log(`✗ Failed to remove ${buttonName}:`, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Alternative: hide buttons we can't remove
|
||||
allChildren.forEach((child, index) => {
|
||||
const name = (
|
||||
child.name_ ||
|
||||
child.constructor.name ||
|
||||
''
|
||||
).toLowerCase();
|
||||
if (
|
||||
name.includes('caption') &&
|
||||
!name.includes('subtitle')
|
||||
) {
|
||||
const name = (child.name_ || child.constructor.name || '').toLowerCase();
|
||||
if (name.includes('caption') && !name.includes('subtitle')) {
|
||||
child.hide();
|
||||
console.log(
|
||||
`✓ Hidden button at index ${index}: ${name}`
|
||||
);
|
||||
console.log(`✓ Hidden button at index ${index}: ${name}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Move chapters button to the very end
|
||||
const chaptersButton =
|
||||
controlBar.getChild('chaptersButton');
|
||||
const chaptersButton = controlBar.getChild('chaptersButton');
|
||||
if (chaptersButton) {
|
||||
try {
|
||||
controlBar.removeChild(chaptersButton);
|
||||
controlBar.addChild(chaptersButton);
|
||||
console.log(
|
||||
'✓ Chapters button moved to last position'
|
||||
);
|
||||
console.log('✓ Chapters button moved to last position');
|
||||
} catch (e) {
|
||||
console.log(
|
||||
'✗ Failed to move chapters button:',
|
||||
e
|
||||
);
|
||||
console.log('✗ Failed to move chapters button:', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -604,15 +565,10 @@ function VideoJSPlayer() {
|
||||
setTimeout(() => {
|
||||
const setupClickableMenus = () => {
|
||||
// Find all menu buttons (chapters, subtitles, etc.)
|
||||
const menuButtons = [
|
||||
'chaptersButton',
|
||||
'subtitlesButton',
|
||||
'playbackRateMenuButton',
|
||||
];
|
||||
const menuButtons = ['chaptersButton', 'subtitlesButton', 'playbackRateMenuButton'];
|
||||
|
||||
menuButtons.forEach((buttonName) => {
|
||||
const button =
|
||||
controlBar.getChild(buttonName);
|
||||
const button = controlBar.getChild(buttonName);
|
||||
if (button && button.menuButton_) {
|
||||
// Override the menu button behavior
|
||||
const menuButton = button.menuButton_;
|
||||
@ -623,75 +579,40 @@ function VideoJSPlayer() {
|
||||
|
||||
// Add click-to-toggle behavior
|
||||
menuButton.on('click', function () {
|
||||
if (
|
||||
this.menu.hasClass(
|
||||
'vjs-lock-showing'
|
||||
)
|
||||
) {
|
||||
this.menu.removeClass(
|
||||
'vjs-lock-showing'
|
||||
);
|
||||
if (this.menu.hasClass('vjs-lock-showing')) {
|
||||
this.menu.removeClass('vjs-lock-showing');
|
||||
this.menu.hide();
|
||||
} else {
|
||||
this.menu.addClass(
|
||||
'vjs-lock-showing'
|
||||
);
|
||||
this.menu.addClass('vjs-lock-showing');
|
||||
this.menu.show();
|
||||
}
|
||||
});
|
||||
|
||||
console.log(
|
||||
`✓ Made ${buttonName} clickable`
|
||||
);
|
||||
console.log(`✓ Made ${buttonName} clickable`);
|
||||
} else if (button) {
|
||||
// For buttons without menuButton_ property
|
||||
const buttonEl = button.el();
|
||||
if (buttonEl) {
|
||||
// Add click handler to show/hide menu
|
||||
buttonEl.addEventListener(
|
||||
'click',
|
||||
function (e) {
|
||||
buttonEl.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const menu =
|
||||
buttonEl.querySelector(
|
||||
'.vjs-menu'
|
||||
);
|
||||
const menu = buttonEl.querySelector('.vjs-menu');
|
||||
if (menu) {
|
||||
if (
|
||||
menu.style
|
||||
.display ===
|
||||
'block'
|
||||
) {
|
||||
menu.style.display =
|
||||
'none';
|
||||
if (menu.style.display === 'block') {
|
||||
menu.style.display = 'none';
|
||||
} else {
|
||||
// Hide other menus first
|
||||
document
|
||||
.querySelectorAll(
|
||||
'.vjs-menu'
|
||||
)
|
||||
.forEach(
|
||||
(m) => {
|
||||
if (
|
||||
m !==
|
||||
menu
|
||||
)
|
||||
m.style.display =
|
||||
'none';
|
||||
}
|
||||
);
|
||||
menu.style.display =
|
||||
'block';
|
||||
document.querySelectorAll('.vjs-menu').forEach((m) => {
|
||||
if (m !== menu) m.style.display = 'none';
|
||||
});
|
||||
menu.style.display = 'block';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
console.log(
|
||||
`✓ Added click handler to ${buttonName}`
|
||||
);
|
||||
console.log(`✓ Added click handler to ${buttonName}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -701,15 +622,11 @@ function VideoJSPlayer() {
|
||||
}, 1500);
|
||||
|
||||
// Add chapter markers to progress control
|
||||
const progressControl =
|
||||
controlBar.getChild('progressControl');
|
||||
const progressControl = controlBar.getChild('progressControl');
|
||||
if (progressControl) {
|
||||
const progressHolder =
|
||||
progressControl.getChild('seekBar');
|
||||
const progressHolder = progressControl.getChild('seekBar');
|
||||
if (progressHolder) {
|
||||
const chapterMarkers = new ChapterMarkers(
|
||||
playerRef.current
|
||||
);
|
||||
const chapterMarkers = new ChapterMarkers(playerRef.current);
|
||||
progressHolder.addChild(chapterMarkers);
|
||||
}
|
||||
}
|
||||
@ -738,23 +655,16 @@ function VideoJSPlayer() {
|
||||
|
||||
// Keep controls active after video ends
|
||||
setTimeout(() => {
|
||||
if (
|
||||
playerRef.current &&
|
||||
!playerRef.current.isDisposed()
|
||||
) {
|
||||
if (playerRef.current && !playerRef.current.isDisposed()) {
|
||||
// Remove vjs-ended class if it disables controls
|
||||
const playerEl = playerRef.current.el();
|
||||
if (playerEl) {
|
||||
// Keep the visual ended state but ensure controls work
|
||||
const controlBar =
|
||||
playerRef.current.getChild(
|
||||
'controlBar'
|
||||
);
|
||||
const controlBar = playerRef.current.getChild('controlBar');
|
||||
if (controlBar) {
|
||||
controlBar.show();
|
||||
controlBar.el().style.opacity = '1';
|
||||
controlBar.el().style.pointerEvents =
|
||||
'auto';
|
||||
controlBar.el().style.pointerEvents = 'auto';
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -762,9 +672,7 @@ function VideoJSPlayer() {
|
||||
|
||||
// Prevent creating multiple end screens
|
||||
if (endScreen) {
|
||||
console.log(
|
||||
'End screen already exists, removing previous one'
|
||||
);
|
||||
console.log('End screen already exists, removing previous one');
|
||||
playerRef.current.removeChild(endScreen);
|
||||
endScreen = null;
|
||||
}
|
||||
@ -809,26 +717,15 @@ function VideoJSPlayer() {
|
||||
});
|
||||
|
||||
playerRef.current.on('fullscreenchange', () => {
|
||||
console.log(
|
||||
'Fullscreen changed:',
|
||||
playerRef.current.isFullscreen()
|
||||
);
|
||||
console.log('Fullscreen changed:', playerRef.current.isFullscreen());
|
||||
});
|
||||
|
||||
playerRef.current.on('volumechange', () => {
|
||||
console.log(
|
||||
'Volume changed:',
|
||||
playerRef.current.volume(),
|
||||
'Muted:',
|
||||
playerRef.current.muted()
|
||||
);
|
||||
console.log('Volume changed:', playerRef.current.volume(), 'Muted:', playerRef.current.muted());
|
||||
});
|
||||
|
||||
playerRef.current.on('ratechange', () => {
|
||||
console.log(
|
||||
'Playback rate changed:',
|
||||
playerRef.current.playbackRate()
|
||||
);
|
||||
console.log('Playback rate changed:', playerRef.current.playbackRate());
|
||||
});
|
||||
|
||||
playerRef.current.on('texttrackchange', () => {
|
||||
@ -853,18 +750,13 @@ function VideoJSPlayer() {
|
||||
// Focus the player element
|
||||
if (playerRef.current.el()) {
|
||||
playerRef.current.el().focus();
|
||||
console.log(
|
||||
'Video player focused for keyboard controls'
|
||||
);
|
||||
console.log('Video player focused for keyboard controls');
|
||||
}
|
||||
|
||||
// Start playing the video immediately if autoplay is enabled
|
||||
if (playerRef.current.autoplay()) {
|
||||
playerRef.current.play().catch((error) => {
|
||||
console.log(
|
||||
'Autoplay prevented by browser:',
|
||||
error
|
||||
);
|
||||
console.log('Autoplay prevented by browser:', error);
|
||||
// If autoplay fails, we can still focus the element
|
||||
// so the user can manually start and use keyboard controls
|
||||
});
|
||||
@ -915,21 +807,12 @@ function VideoJSPlayer() {
|
||||
setTimeout(focusVideo, 500);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener(
|
||||
'visibilitychange',
|
||||
handleVisibilityChange
|
||||
);
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
window.removeEventListener('focus', handleWindowFocus);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<video
|
||||
ref={videoRef}
|
||||
className='video-js vjs-default-skin'
|
||||
tabIndex='0'
|
||||
/>
|
||||
);
|
||||
return <video ref={videoRef} className="video-js vjs-default-skin" tabIndex="0" />;
|
||||
}
|
||||
|
||||
export default VideoJSPlayer;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user