Multi-Screen Quad Player Implementation

Complete 4-Video Grid System:
- Created QuadVideoPlayer extending OverlayVideoPlayer architecture
- 2x2 responsive grid layout with professional styling
- Auto-hide individual headers, backdrop, and controls for clean quad view

 Training Mode Integration:
- Added Multi-Screen Mode button to interactive task controls
- Smart video library access using unified storage fallbacks
- Object-fit contain for proper video scaling (portrait/landscape)

 Advanced Controls:
- Shuffle All: Load 4 new random videos instantly
- Minimize: Hide overlay but continue videos in background
- Close: Stop all videos and reset state
- ESC key and backdrop click support

 State Management:
- Minimize/restore functionality for seamless training progression
- Proper cleanup on game end with video stopping
- DOM corruption prevention via force recreation strategy
- Complete player destruction and fresh initialization

 User Experience:
- Notification system integration with helpful status messages
- Responsive design with mobile considerations
- Pink/purple gradient theming matching game aesthetic
- Hover effects and smooth transitions

 Future: Individual controls, sync options, focus mode, custom layouts

Files: quadVideoPlayer.js, interactiveTaskManager.js, index.html, ROADMAP.md
This commit is contained in:
dilgenfritz 2025-10-31 21:36:30 -05:00
parent f06ec70751
commit 689574953a
5 changed files with 663 additions and 122 deletions

View File

@ -19,141 +19,51 @@
- Modern layout with header navigation and sidebar panels
- Interactive video controls with progress bar seeking
- Auto-hide control behavior and responsive design
- Foundation ready for video library and playlist features
- Video library, playlist management, and search functionality
- Full video loading system with unified library integration
## 🚧 Active Development
- Enhanced user experience improvements
- Bug fixes and stability enhancements
- Performance optimizations
- **✅ 🎬 Overlay Video Player System (October 31, 2025)**
- ✅ **Portable Video Player Architecture**: Created OverlayVideoPlayer class extending BaseVideoPlayer for maximum reusability
- ✅ **Modal Popup Interface**: Professional overlay system with backdrop blur, smooth animations, and responsive design
- ✅ **Random Video Selection**: Automatic random video loading from unified video library with robust fallback mechanisms
- ✅ **Full Video Controls**: Inherited complete video control system (play/pause, seek, volume, fullscreen) from BaseVideoPlayer
- ✅ **User Experience Features**: Dismissible via Escape/close button/backdrop, video metadata display, mobile optimization
- ✅ **Integration Testing**: Successfully tested with linked video directories, accessible via Video Management screen
- ✅ **Glassmorphism Styling**: Professional dark theme with CSS animations and modern UI design patterns
- **✅ 🎬 Porn Cinema Video Loading Bug Fix (October 31, 2025)**
- ✅ **Critical Bug Resolution**: Fixed video loading issue where Porn Cinema couldn't access videos from linked directories
- ✅ **Data Preservation Logic**: Implemented safeguards to prevent DesktopFileManager from overwriting existing video data
- ✅ **Storage System Enhancement**: Enhanced unified video library fallback mechanisms for reliable video access
- ✅ **Console Cleanup**: Removed excessive debug logging for cleaner user experience
- ✅ **Cross-Component Synchronization**: Fixed timing issues between main game and Porn Cinema video data access
- **✅ 🎬 Complete Playlist System Implementation (October 31, 2025)**
- ✅ **Playlist Management UI**: Professional sidebar with playlist tab, controls, and real-time display updates
- ✅ **Add/Remove/Play Operations**: Full CRUD operations with /✕/▶ buttons and direct playlist item interaction
- ✅ **Smart Playlist Features**: Shuffle, clear, duplicate prevention, and current video highlighting
- ✅ **Save/Load System**: Custom naming dialog, localStorage persistence, and JSON export/import functionality
- ✅ **Video Library Playlist Creation**: Multi-selection system with checkboxes, batch playlist creation, and immediate switching
- ✅ **Professional UI/UX**: Toast notifications, modal dialogs, responsive design, and consistent theming
- **✅ 📊 Player Statistics System (October 31, 2025)**
- ✅ **Real-time Watch Time Tracking**: Precise play/pause detection with cumulative timer that never resets
- ✅ **Comprehensive Viewing Metrics**: Videos watched, completed (90%+), skipped (<10%), and completion rates
- ✅ **Session Analytics**: Session counting, average length, longest session, and binge session detection (2+ hours)
- ✅ **Engagement Statistics**: Playlists created, videos added to playlists, and most watched video tracking
- ✅ **Achievement Metrics**: Days active, consecutive day streaks, and daily activity pattern analysis
- ✅ **Professional Stats Dashboard**: Beautiful card-based visualization with export/reset functionality and main navigation integration
- **✅ 👤 User Profile System (October 31, 2025)**
- ✅ **Profile Information Management**: Customizable username, bio, join date, theme preferences with localStorage persistence
- ✅ **Dynamic Avatar System**: Auto-generated avatar from username with visual profile identity
- ✅ **Statistics Integration**: Seamless integration with PlayerStats infrastructure for real-time data display
- ✅ **Level Progression System**: XP-based leveling with visual progress bars and level calculation
- ✅ **Achievement System**: 8 unique achievements with dynamic unlocking based on player statistics
- ✅ **Profile Data Management**: Export/import functionality for profile and statistics backup
- ✅ **Navigation Integration**: Added profile button to main menu with cross-page navigation links
- ✅ **Professional UI Design**: Card-based responsive layout with glassmorphism styling and notifications
- **🎬 User Profile System** *(📋 Planned - November 2025)*
- ✅ **Navigation Integration**: Added profile button to main menu with cross-page navigation links
- ✅ **Professional UI Design**: Card-based responsive layout with glassmorphism styling and notifications
- **🎬 Porn Cinema Player Enhancements** *(📋 Planned - November 2025)*
- 📋 **Pause Button Fix**: Debug and repair non-functioning pause button in video player
- 📋 **Autoplay Next Video**: Implement automatic progression to next playlist video on completion
- 📋 **Repeat/Loop Options**: Add single video repeat and full playlist loop functionality
- 📋 **Enhanced Playlist Controls**: Improved playlist navigation and playback options
- 📋 **Video Player Reliability**: Ensure all basic controls function correctly across all scenarios
- **🎬 Porn Cinema Media Player** *(✅ Major Progress - October 30-31, 2025)*
- ✅ **Complete Layout Implementation**: Professional two-column design with main content area and right sidebar
- ✅ **Header Navigation**: Slim, modern header with Home, Settings, Theater, and Fullscreen controls
- ✅ **Sidebar Navigation**: Tabbed interface with Playlist and Search panels
- ✅ **Video Player Core**: Full-featured video player with professional controls
- ✅ **Progress Bar**: Interactive seeking with hover effects and click-to-seek functionality
- ✅ **Auto-Hide Controls**: Smart control visibility with 3-second timeout during playback
- ✅ **Video Library Integration**: Minimal, clean library section with grid/list views
- ✅ **Responsive Design**: Clean mockup-matching layout with proper CSS architecture
- **🎬 Multi-Screen Quad Player (October 31, 2025)** *(🚧 In Progress)*
- ✅ **Quad Video Layout**: 2x2 grid displaying 4 simultaneous video streams for intensive training
- ✅ **Training Integration**: Multi-Screen Mode button added to interactive task controls
- ✅ **Smart Controls**: Shuffle all videos, minimize to background, and close functionality
- ✅ **Minimize Feature**: Continue videos in background while progressing through training scenarios
- ✅ **Proper Cleanup**: Videos stop when game ends, DOM corruption prevention with force recreation
- 🚧 **Future Enhancements**: Individual video controls, sync options, focus mode, custom layouts
- **🎬 Porn Cinema Media Player** *(✅ COMPLETED - October 30-31, 2025)*
- ✅ **Complete Professional Interface**: Modern two-column layout with header navigation and sidebar panels
- ✅ **Full Video Player Controls**: Interactive progress bar, auto-hide behavior, quality/speed selection, volume control
- ✅ **Playlist & Library System**: Video library integration, playlist management, search functionality
- ✅ **Responsive Design**: Clean architecture with purple gradient theming
- ✅ **Video Loading System**: Robust video loading from unified video library with fallback mechanisms
- 🚧 **Next Steps**: Video library population, playlist functionality, search implementation
- **🔧 Base Video Player Extraction** *(✅ COMPLETED - October 31, 2025)*
- ✅ **Extract Reusable Components**: Created BaseVideoPlayer class with full video control functionality (400+ lines)
- **🔧 Base Video Player Architecture** *(✅ COMPLETED - October 31, 2025)*
- ✅ **Reusable Components**: Created BaseVideoPlayer class with full video control functionality (400+ lines)
- ✅ **Focus Video Player**: Built FocusVideoPlayer extending BaseVideoPlayer for minimal focus session UI
- ✅ **Shared CSS System**: Created base-video-player.css for reusable video styling across game modes
- ✅ **Focus Interruption Integration**: Updated interactiveTaskManager to use new FocusVideoPlayer with graceful fallback
- ✅ **Testing Infrastructure**: Created video-player-test.html with comprehensive validation - ALL TESTS PASSING ✅
- ✅ **Script Integration**: Added baseVideoPlayer.js and focusVideoPlayer.js to index.html loading sequence
- ✅ **Global Export**: Properly exported classes to window object for browser compatibility
- ✅ **Syntax Validation**: Clean JavaScript validation with no errors
- ✅ **Integration & Testing**: Successfully integrated with focus interruptions and validated with comprehensive tests
- **🎬 Porn Cinema Refactoring** *(✅ COMPLETED - October 31, 2025)*
- ✅ **Legacy Code Analysis**: Analyzed existing pornCinema.js for BaseVideoPlayer integration points
- ✅ **Architecture Planning**: Identified cinema-specific features (playlist, theater mode, navigation)
- ✅ **Code Backup**: Created pornCinema-backup.js to preserve original implementation
- ✅ **Class Refactoring**: Created clean PornCinema class extending BaseVideoPlayer
- ✅ **Core Inheritance**: PornCinema now properly extends BaseVideoPlayer for shared functionality
- ✅ **Method Implementation**: Added initialize(), playVideo(), addToPlaylist() methods
- ✅ **Error Handling**: Proper TypeError resolution and method validation
- ✅ **Integration Testing**: Successfully tested in Option A architecture
- ✅ **Clean Architecture**: Created PornCinema class extending BaseVideoPlayer for shared functionality
- ✅ **Legacy Preservation**: Created pornCinema-backup.js to preserve original implementation
- ✅ **Integration**: Proper inheritance with initialize(), playVideo(), addToPlaylist() methods
- **🎮 Focus Interruption Video Integration** *(✅ COMPLETED - October 31, 2025)*
- ✅ **Video Library Access**: Fixed FocusVideoPlayer video library initialization
- ✅ **Volume Control Integration**: Added ultra-compact volume slider (60px width)
- ✅ **CSS Override System**: Resolved CSS conflicts with focus-volume-slider class
- ✅ **UI Refinement**: Achieved ultra-compact volume control design per user specs
- ✅ **Video Collection**: 34 videos successfully integrated from punishment/task/background categories
- ✅ **Testing Complete**: Focus interruption videos playing successfully with proper controls
- **NEW XP System Implementation:**
- **Main Game**
- User gains 1 XP per task
- User gains 5 XP for a streak of 10 completed tasks.
- User gains No XP to their overall XP counter if the game is quit
- **Scenario Games(punishment, photo, training academy, endurance)**
- Time-based XP: 1 XP per 2 minutes of gameplay
- Focus session bonuses: 3 XP per 30 seconds
- Webcam mirror bonuses: 3 XP per 30 seconds
- Photo rewards: 1 XP per picture taken
- No XP awarded for abandoned/quit sessions
- ✅ **Video Library Access**: Fixed FocusVideoPlayer video library initialization with 34 videos integrated
- ✅ **Ultra-Compact Controls**: Added 60px width volume slider with CSS override system
- ✅ **Complete Integration**: Focus interruption videos playing successfully with proper controls
- **✅ XP System Implementation (October 2025)**
- **Main Game**: 1 XP per task, 5 XP for 10-task streaks, no XP for quit sessions
- **Scenario Games**: Time-based XP (1 XP per 2 minutes), focus session bonuses (3 XP per 30 seconds), webcam bonuses, photo rewards
## 📋 Feature Backlog
### 🎯 High Priority (Core Game Polish)
- [✅] **Porn Cinema Media Player** - *Major Milestone Achieved October 30-31, 2025*
- **✅ Layout & Design Completed:**
- Two-column responsive layout with main content and sidebar
- Professional header with navigation controls
- Tabbed sidebar interface (Playlist/Search)
- Clean, minimal video library section
- Modern purple gradient theming throughout
- **✅ Video Player Core:**
- Full-featured video container with overlay system
- Interactive progress bar with click-to-seek
- Auto-hide controls with smart timeout behavior
- Professional media control buttons
- Quality and speed selection dropdowns
- Volume control with visual feedback
- **✅ User Experience Features:**
- Hover-to-reveal control behavior
- Keyboard shortcuts support structure
- Theater mode and fullscreen toggle buttons
- Responsive design for different screen sizes
- **🚧 Remaining Implementation:**
- Video library population from desktop file manager
- Playlist creation and management functionality
- Search functionality for video library
- Video thumbnail generation and metadata display
- Remember last played position
- Keyboard shortcuts activation
- An overall counter time watching videos that is saved to the users stats
- [✅] **Overlay Video Player System** - *Completed October 31, 2025*
- **✅ Architecture**: Portable BaseVideoPlayer extension for popup/modal video playback
- **✅ Features**: Random video selection, full controls, dismissible interface, responsive design
- **✅ Integration**: Successfully integrated with video management and unified video library
- **🎯 Future Applications**: Could be used for focus interruptions, random rewards, punishment videos, or mini-cinema modes
- [✅] **Porn Cinema Media Player** - *Completed October 30-31, 2025*
- **✅ Complete Professional Interface**: Two-column responsive layout, header navigation, tabbed sidebar
- **✅ Full Video Player**: Interactive progress bar, auto-hide controls, quality/speed selection, volume control
- **✅ Advanced Features**: Video library integration, playlist management, search functionality, theater mode
- **✅ User Experience**: Hover effects, keyboard shortcuts support, responsive design, purple gradient theming
- [ ] More interactive task types and scenarios
- [ ] Improved user interface and visual design
- [ ] Better error handling and user feedback

View File

@ -1661,6 +1661,7 @@
<script src="src/features/media/baseVideoPlayer.js"></script>
<script src="src/features/media/focusVideoPlayer.js"></script>
<script src="src/features/media/overlayVideoPlayer.js"></script>
<script src="src/features/media/quadVideoPlayer.js"></script>
<script src="src/features/tasks/interactiveTaskManager.js"></script>
<script src="src/features/video/videoPlayerManager.js"></script>
<script src="src/utils/desktop-file-manager.js"></script>

View File

@ -4518,6 +4518,11 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
}
startGame() {
// Clean up any existing interactive resources before starting new game
if (this.interactiveTaskManager) {
this.interactiveTaskManager.cleanup();
}
if (!this.imageDiscoveryComplete) {
console.log('Image discovery not complete, retrying in 500ms...');
@ -5241,6 +5246,11 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
this.stopTimer();
this.flashMessageManager.stop();
// Clean up interactive task resources (including quad video player)
if (this.interactiveTaskManager) {
this.interactiveTaskManager.cleanup();
}
// Handle XP calculation - use scenario XP for scenarios, task XP for main game
let sessionXp;
if (window.gameModeManager && window.gameModeManager.isScenarioMode()) {

View File

@ -0,0 +1,549 @@
/**
* Quad Video Player - Multi-screen video overlay system
* Displays 4 videos simultaneously in a grid layout for intensive viewing sessions
*/
class QuadVideoPlayer {
constructor() {
this.players = [];
this.container = null;
this.isActive = false;
this.isMinimized = false;
this.videoLibrary = null;
}
/**
* Initialize the quad video player system
*/
async initialize() {
console.log('🎬 Initializing QuadVideoPlayer...');
// Get video library using the same pattern as OverlayVideoPlayer
this.videoLibrary = this.getAvailableVideos();
if (!this.videoLibrary || this.videoLibrary.length === 0) {
console.warn('⚠️ No videos available for quad player');
return false;
}
console.log('📹 Found', this.videoLibrary.length, 'videos for quad player');
this.createQuadContainer();
await this.initializePlayers();
console.log('✅ QuadVideoPlayer initialized with', this.players.length, 'players');
return true;
}
/**
* Get available videos using the same logic as OverlayVideoPlayer
*/
getAvailableVideos() {
let allVideos = [];
console.log('📹 Checking video sources...');
// Try desktop file manager first
if (window.desktopFileManager) {
allVideos = window.desktopFileManager.getAllVideos();
console.log('📹 Desktop file manager videos:', allVideos.length);
}
// Fallback to unified storage
if (allVideos.length === 0) {
const unifiedData = JSON.parse(localStorage.getItem('unifiedVideoLibrary') || '{}');
allVideos = unifiedData.allVideos || [];
console.log('📹 Unified storage videos:', allVideos.length);
}
// Fallback to legacy storage
if (allVideos.length === 0) {
const storedVideos = JSON.parse(localStorage.getItem('videoFiles') || '{}');
allVideos = Object.values(storedVideos).flat();
console.log('📹 Legacy storage videos:', allVideos.length);
}
console.log('📹 Total videos found:', allVideos.length);
return allVideos;
}
/**
* Create the main quad container
*/
createQuadContainer() {
this.container = document.createElement('div');
this.container.className = 'quad-video-overlay';
this.container.innerHTML = `
<div class="quad-header">
<h2>🎬 Multi-Screen Training Mode</h2>
<div class="quad-controls">
<button id="quad-shuffle-btn" class="btn btn-secondary btn-small">🔄 Shuffle All</button>
<button id="quad-minimize-btn" class="btn btn-warning btn-small"> Minimize</button>
<button id="quad-close-btn" class="btn btn-danger btn-small"> Close</button>
</div>
</div>
<div class="quad-grid">
<div class="quad-slot" data-slot="0"></div>
<div class="quad-slot" data-slot="1"></div>
<div class="quad-slot" data-slot="2"></div>
<div class="quad-slot" data-slot="3"></div>
</div>
`;
// Add to body but keep hidden initially
this.container.style.display = 'none';
document.body.appendChild(this.container);
// Add event listeners for controls
this.setupEventListeners();
this.addQuadStyles();
}
/**
* Initialize 4 overlay video players
*/
async initializePlayers() {
for (let i = 0; i < 4; i++) {
const player = new OverlayVideoPlayer();
// Configure for quad layout
this.setupQuadPlayer(player, i);
this.players.push(player);
}
}
/**
* Configure individual player for quad layout
*/
setupQuadPlayer(player, index) {
const slot = this.container.querySelector(`[data-slot="${index}"]`);
// Ensure the overlay element is in the DOM (constructor removes it)
if (!document.body.contains(player.overlayElement)) {
document.body.appendChild(player.overlayElement);
}
// Configure the overlay element for quad layout
player.overlayElement.style.position = 'relative';
player.overlayElement.style.width = '100%';
player.overlayElement.style.height = '100%';
player.overlayElement.style.background = 'transparent';
player.overlayElement.style.display = 'flex'; // Override the default display: none
// Set visibility states
player.isVisible = true;
player.overlayElement.classList.add('visible');
// Remove/hide the backdrop
const backdrop = player.overlayElement.querySelector('.overlay-backdrop');
if (backdrop) {
backdrop.style.display = 'none';
}
// Find and configure the overlay window
const overlayWindow = player.overlayElement.querySelector('.overlay-window');
if (overlayWindow) {
overlayWindow.style.position = 'relative';
overlayWindow.style.width = '100%';
overlayWindow.style.height = '100%';
overlayWindow.style.margin = '0';
overlayWindow.style.transform = 'none';
overlayWindow.style.maxWidth = 'none';
overlayWindow.style.maxHeight = 'none';
}
// Find and configure the video container
const videoContainer = player.overlayElement.querySelector('.overlay-video-container');
if (videoContainer) {
videoContainer.style.width = '100%';
videoContainer.style.height = '100%';
videoContainer.style.position = 'relative';
}
// Find and configure the video element
const video = player.overlayElement.querySelector('video');
if (video) {
video.style.width = '100%';
video.style.height = '100%';
video.style.objectFit = 'contain'; // Changed from 'cover' to 'contain' to fit entire video
video.style.display = 'block';
video.style.backgroundColor = '#000'; // Add black background for letterboxing
}
// Hide the header to save space
const header = player.overlayElement.querySelector('.overlay-header');
if (header) {
header.style.display = 'none';
}
// Hide individual close button
const closeBtn = player.overlayElement.querySelector('.overlay-close-btn');
if (closeBtn) {
closeBtn.style.display = 'none';
}
// Remove from body and add to quad slot
document.body.removeChild(player.overlayElement);
slot.appendChild(player.overlayElement);
// Load random video for this slot
player.playRandomVideo();
}
/**
* Setup event listeners for quad controls
*/
setupEventListeners() {
// Shuffle all videos
const shuffleBtn = this.container.querySelector('#quad-shuffle-btn');
shuffleBtn?.addEventListener('click', () => {
this.shuffleAllVideos();
});
// Minimize quad mode
const minimizeBtn = this.container.querySelector('#quad-minimize-btn');
minimizeBtn?.addEventListener('click', () => {
this.minimize();
});
// Close quad mode
const closeBtn = this.container.querySelector('#quad-close-btn');
closeBtn?.addEventListener('click', () => {
this.hide();
});
// ESC key to close
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && this.isActive) {
this.hide();
}
});
// Backdrop click to close
this.container.addEventListener('click', (e) => {
if (e.target === this.container) {
this.hide();
}
});
}
/**
* Show the quad video overlay
*/
show() {
if (!this.container) {
console.error('❌ QuadVideoPlayer not initialized');
return;
}
console.log('🎬 Showing quad video overlay');
this.container.style.display = 'flex';
this.isActive = true;
// Start all videos
this.players.forEach(player => {
if (player.videoElement) {
player.videoElement.play().catch(e => console.log('Video autoplay prevented:', e));
}
});
}
/**
* Hide the quad video overlay
*/
hide() {
if (!this.container) return;
console.log('🎬 Hiding quad video overlay');
this.container.style.display = 'none';
this.isActive = false;
this.isMinimized = false; // Reset minimized state when fully hiding
// Always pause and stop all videos, regardless of current state
this.stopAllVideos();
// Reset player states more thoroughly
this.players.forEach((player, index) => {
if (player.overlayElement) {
// Reset video source to prevent corruption
if (player.videoElement) {
player.videoElement.src = '';
player.videoElement.load(); // Force reload to clear state
}
// Reset player state
player.isVisible = false;
player.currentVideo = null;
player.overlayElement.classList.remove('visible');
}
});
}
/**
* Stop all videos (separate method for cleanup purposes)
*/
stopAllVideos() {
console.log('🛑 Stopping all quad videos');
this.players.forEach((player, index) => {
// Use videoElement (BaseVideoPlayer property) instead of video
if (player.videoElement) {
player.videoElement.pause();
player.videoElement.currentTime = 0; // Reset to beginning
console.log(`🛑 Stopped video ${index + 1}: ${player.videoElement.src || 'Unknown'}`);
} else {
console.log(`⚠️ No videoElement found for player ${index + 1}`);
}
// Also hide the individual players
if (player.overlayElement) {
player.isVisible = false;
player.overlayElement.classList.remove('visible');
}
});
}
/**
* Minimize the quad video overlay (hide but keep videos playing)
*/
minimize() {
if (!this.container) return;
console.log('🎬 Minimizing quad video overlay');
this.container.style.display = 'none';
this.isMinimized = true;
// Note: Keep isActive = true and videos continue playing
// Show notification to user
if (window.game && window.game.showNotification) {
window.game.showNotification('📺 Multi-Screen Mode minimized - videos continue in background. Click Multi-Screen button to restore.', 'info');
}
}
/**
* Restore from minimized state
*/
restore() {
if (!this.container || !this.isMinimized) return;
console.log('🎬 Restoring quad video overlay from minimized');
this.container.style.display = 'flex';
this.isMinimized = false;
this.isActive = true;
}
/**
* Load new random videos in all slots
*/
shuffleAllVideos() {
console.log('🔄 Shuffling all quad videos');
// Refresh video library in case new videos were added
this.videoLibrary = this.getAvailableVideos();
if (this.videoLibrary.length === 0) {
console.warn('⚠️ No videos available for shuffle');
return;
}
this.players.forEach(player => {
player.playRandomVideo();
});
}
/**
* Add CSS styles for quad layout
*/
addQuadStyles() {
if (document.getElementById('quad-video-styles')) return;
const styles = document.createElement('style');
styles.id = 'quad-video-styles';
styles.textContent = `
.quad-video-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.95);
z-index: 10000;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
box-sizing: border-box;
}
.quad-header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
max-width: 1200px;
margin-bottom: 20px;
color: white;
}
.quad-header h2 {
margin: 0;
color: #ff6b9d;
text-shadow: 0 2px 4px rgba(0,0,0,0.5);
}
.quad-controls {
display: flex;
gap: 10px;
}
.quad-controls .btn {
transition: all 0.3s ease;
}
.quad-controls .btn:hover {
transform: translateY(-1px);
}
.quad-grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
gap: 15px;
width: 100%;
height: calc(100vh - 120px);
max-width: 1200px;
max-height: 800px;
}
.quad-slot {
position: relative;
background: #000;
border-radius: 12px;
overflow: hidden;
border: 2px solid #333;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
}
.quad-slot:hover {
border-color: #ff6b9d;
transform: scale(1.02);
transition: all 0.3s ease;
}
/* Force overlay elements to display properly in quad layout */
.quad-slot .video-overlay-popup {
position: relative !important;
width: 100% !important;
height: 100% !important;
background: transparent !important;
display: block !important;
}
.quad-slot .overlay-window {
position: relative !important;
width: 100% !important;
height: 100% !important;
margin: 0 !important;
transform: none !important;
max-width: none !important;
max-height: none !important;
background: transparent !important;
}
.quad-slot .overlay-video-container {
width: 100% !important;
height: 100% !important;
position: relative !important;
}
.quad-slot video {
width: 100% !important;
height: 100% !important;
object-fit: contain !important; /* Ensure entire video is visible */
display: block !important;
background-color: #000 !important; /* Black background for letterboxing */
}
/* Responsive design for smaller screens */
@media (max-width: 768px) {
.quad-grid {
grid-template-columns: 1fr;
grid-template-rows: repeat(4, 1fr);
gap: 10px;
max-height: 90vh;
}
.quad-header {
flex-direction: column;
gap: 10px;
text-align: center;
}
}
@media (max-width: 480px) {
.quad-video-overlay {
padding: 10px;
}
.quad-grid {
gap: 8px;
}
}
`;
document.head.appendChild(styles);
}
/**
* Cleanup resources
*/
destroy() {
console.log('🧹 Destroying QuadVideoPlayer...');
// Stop all videos first
this.stopAllVideos();
// Destroy individual players
this.players.forEach((player, index) => {
console.log(`🧹 Destroying player ${index + 1}`);
// Remove event listeners and clean up player
if (player.overlayElement) {
// Remove from DOM
if (player.overlayElement.parentNode) {
player.overlayElement.parentNode.removeChild(player.overlayElement);
}
}
// Call destroy method if it exists
if (typeof player.destroy === 'function') {
player.destroy();
}
});
// Remove container
if (this.container && this.container.parentNode) {
this.container.parentNode.removeChild(this.container);
}
// Reset state
this.players = [];
this.container = null;
this.isActive = false;
this.isMinimized = false;
// Remove styles
const styles = document.getElementById('quad-video-styles');
if (styles) {
styles.remove();
}
console.log('✅ QuadVideoPlayer destroyed');
}
}
// Export for use in other modules
if (typeof module !== 'undefined' && module.exports) {
module.exports = QuadVideoPlayer;
}
// Make available globally
window.QuadVideoPlayer = QuadVideoPlayer;

View File

@ -192,7 +192,9 @@ class InteractiveTaskManager {
<button id="interactive-give-up-btn" class="btn btn-danger interactive-btn">
Give Up
</button>
<button id="multi-screen-btn" class="btn btn-primary interactive-btn">
🎬 Multi-Screen Mode
</button>
`;
actionButtons.appendChild(interactiveControls);
@ -206,6 +208,7 @@ class InteractiveTaskManager {
this.completeInteractiveTask();
});
document.getElementById('interactive-give-up-btn').addEventListener('click', () => this.giveUpInteractiveTask());
document.getElementById('multi-screen-btn').addEventListener('click', () => this.openMultiScreenMode());
}
@ -3763,6 +3766,74 @@ class InteractiveTaskManager {
document.head.appendChild(styles);
}
/**
* Open multi-screen mode overlay for intensive training
*/
async openMultiScreenMode() {
console.log('🎬 Opening Multi-Screen Mode...');
try {
// Check if quad player exists and is minimized
if (this.quadPlayer && this.quadPlayer.isMinimized) {
console.log('🎬 Restoring minimized QuadVideoPlayer');
this.quadPlayer.restore();
return;
}
// If quad player exists but might be corrupted, destroy and recreate
if (this.quadPlayer) {
console.log('🎬 Recreating QuadVideoPlayer to prevent corruption');
this.quadPlayer.destroy();
this.quadPlayer = null;
}
// Create new quad player
this.quadPlayer = new QuadVideoPlayer();
const initialized = await this.quadPlayer.initialize();
if (!initialized) {
console.error('❌ Failed to initialize QuadVideoPlayer');
// Show user-friendly error
if (this.game && this.game.showNotification) {
this.game.showNotification('⚠️ No videos available for multi-screen mode', 'warning');
}
return;
}
// Show the quad overlay
this.quadPlayer.show();
// Log for user feedback
if (this.game && this.game.showNotification) {
this.game.showNotification('🎬 Multi-Screen Mode activated! Press ESC to close, — to minimize', 'info');
}
} catch (error) {
console.error('❌ Error opening multi-screen mode:', error);
if (this.game && this.game.showNotification) {
this.game.showNotification('❌ Failed to open multi-screen mode', 'error');
}
}
}
/**
* Clean up quad video player and other resources
*/
cleanup() {
if (this.quadPlayer) {
console.log('🧹 Cleaning up QuadVideoPlayer...');
// Always stop all videos during cleanup
this.quadPlayer.stopAllVideos();
// Fully destroy the quad player to prevent DOM corruption
this.quadPlayer.destroy();
this.quadPlayer = null;
console.log('✅ QuadVideoPlayer fully cleaned up');
}
}
}
// Export for use in other modules