Manually create poster element for YouTube UI blocking

Key changes:
- Create .plyr__poster element manually (Plyr doesn't auto-create for YouTube)
- Set z-index: 10 and pointer-events: auto when visible
- Add 500ms delay before hiding poster on play (matches reference)
- Clear timeout if paused before poster fully hides
- poster blocks YouTube UI when paused/initial, fades out when playing

This matches the reference implementation behavior exactly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
dwindown
2026-01-01 01:37:02 +07:00
parent b335164a58
commit 50d7d6a8dc

View File

@@ -94,32 +94,74 @@ export const VideoPlayerWithChapters = forwardRef<VideoPlayerRef, VideoPlayerWit
playerRef.current = player; playerRef.current = player;
// Get poster element // Create poster element manually for YouTube
posterRef.current = player.elements.wrapper.querySelector('.plyr__poster') as HTMLDivElement; if (!player.elements.wrapper.querySelector('.plyr__poster')) {
const poster = document.createElement('div');
poster.className = 'plyr__poster';
poster.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
z-index: 10;
opacity: 1;
transition: opacity 0.5s ease;
pointer-events: auto;
`;
player.elements.wrapper.appendChild(poster);
posterRef.current = poster;
} else {
posterRef.current = player.elements.wrapper.querySelector('.plyr__poster') as HTMLDivElement;
}
// Track play/pause state to show/hide poster overlay with delay
let hidePosterTimeout: NodeJS.Timeout | null = null;
// Track play/pause state to show/hide poster overlay
player.on('play', () => { player.on('play', () => {
setIsPlaying(true); setIsPlaying(true);
if (posterRef.current) { // Clear any existing timeout
posterRef.current.style.opacity = '0'; if (hidePosterTimeout) {
clearTimeout(hidePosterTimeout);
} }
// Wait 500ms before fading out the poster (like your reference)
hidePosterTimeout = setTimeout(() => {
if (posterRef.current) {
posterRef.current.style.opacity = '0';
posterRef.current.style.pointerEvents = 'none';
}
}, 500);
}); });
player.on('pause', () => { player.on('pause', () => {
setIsPlaying(false); setIsPlaying(false);
// Clear timeout if paused before poster hides
if (hidePosterTimeout) {
clearTimeout(hidePosterTimeout);
hidePosterTimeout = null;
}
if (posterRef.current) { if (posterRef.current) {
posterRef.current.style.opacity = '1'; posterRef.current.style.opacity = '1';
posterRef.current.style.pointerEvents = 'auto';
} }
}); });
player.on('ended', () => { player.on('ended', () => {
setIsPlaying(false); setIsPlaying(false);
// Clear timeout
if (hidePosterTimeout) {
clearTimeout(hidePosterTimeout);
hidePosterTimeout = null;
}
if (posterRef.current) { if (posterRef.current) {
posterRef.current.style.opacity = '1'; posterRef.current.style.opacity = '1';
posterRef.current.style.pointerEvents = 'auto';
} }
}); });
// Apply custom accent color and poster styles // Apply custom accent color
if (accentColor) { if (accentColor) {
const style = document.createElement('style'); const style = document.createElement('style');
style.textContent = ` style.textContent = `
@@ -135,11 +177,6 @@ export const VideoPlayerWithChapters = forwardRef<VideoPlayerRef, VideoPlayerWit
.plyr__progress__buffer { .plyr__progress__buffer {
color: ${accentColor}40 !important; color: ${accentColor}40 !important;
} }
/* Poster overlay to block YouTube UI when paused */
.plyr__poster {
background-color: transparent !important;
transition: opacity 0.3s ease;
}
`; `;
document.head.appendChild(style); document.head.appendChild(style);