Enhance training academy video controls with playlist and improved styling
ADDED: Complete video control panel matching quick-play - Added collapsible video control panel positioned in top-right corner - Implemented rewind/forward 10s, skip, play/pause functionality - Added volume control with slider and visual percentage display - Included video progress bar with time display ADDED: Playlist selection dropdown - Added Source dropdown with Random Videos and Playlist options - Integrated playlist selection change handler - Matches quick-play interface for consistency IMPROVED: Button styling and spacing - Optimized button padding and font size for better fit - Reduced gap between buttons for cleaner layout - Added proper CSS for playlist dropdown with hover effects FIXED: Video info display - Fixed 'No video loaded' issue by properly calling updateVideoInfo() - Added metadata loading handlers for initial and subsequent videos - Enhanced video switching to update info immediately RESULT: Training academy now has identical video controls to quick-play - Fixed positioning with proper z-index and floating panel - Fully functional collapse/expand with smooth transitions - Current video name displays correctly - All control buttons fit properly in the panel
This commit is contained in:
parent
9e00f05af3
commit
3b55de325d
|
|
@ -0,0 +1,259 @@
|
||||||
|
# 🧹 GAME MODE CLEANUP PLAN
|
||||||
|
*Generated: November 8, 2025*
|
||||||
|
|
||||||
|
## 📋 OVERVIEW
|
||||||
|
After moving all game modes to their own dedicated HTML files (`quick-play.html`, `training-academy.html`, etc.), we discovered that all the original game mode infrastructure still exists in `index.html`. This document outlines a comprehensive cleanup plan to remove obsolete game mode code and screens.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎮 CURRENT GAME MODE ARCHITECTURE
|
||||||
|
|
||||||
|
### ✅ **NEW SYSTEM - Dedicated HTML Files**
|
||||||
|
- **quick-play.html** - Quick play game mode
|
||||||
|
- **training-academy.html** - Training academy mode
|
||||||
|
- **porn-cinema.html** - Media viewing mode
|
||||||
|
- **player-stats.html** - Statistics and progress
|
||||||
|
- **user-profile.html** - User profile management
|
||||||
|
|
||||||
|
### ❌ **OLD SYSTEM - Embedded in index.html (TO REMOVE)**
|
||||||
|
All game mode functionality is still embedded in `index.html` as separate screens and should be removed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗂️ OBSOLETE SCREENS ANALYSIS
|
||||||
|
|
||||||
|
### **1. GAME SCREEN (Lines 1632-1677)**
|
||||||
|
- **Element:** `<div id="game-screen" class="screen">`
|
||||||
|
- **Purpose:** Main gameplay interface with task display
|
||||||
|
- **Components:**
|
||||||
|
- `.task-container` - Task display and controls
|
||||||
|
- `.task-image-container` - Task image display
|
||||||
|
- `.task-text-container` - Task text display
|
||||||
|
- `.action-buttons` - Complete, Skip, Mercy Skip, Pause buttons
|
||||||
|
- `.game-stats` - Real-time session statistics
|
||||||
|
- **Status:** ❌ **OBSOLETE** - Functionality moved to dedicated mode files
|
||||||
|
|
||||||
|
### **2. PAUSED SCREEN (Lines 1678-1685)**
|
||||||
|
- **Element:** `<div id="paused-screen" class="screen">`
|
||||||
|
- **Purpose:** Game pause interface
|
||||||
|
- **Components:**
|
||||||
|
- Resume button
|
||||||
|
- Quit button
|
||||||
|
- **Status:** ❌ **OBSOLETE** - Handled in dedicated mode files
|
||||||
|
|
||||||
|
### **3. GAME OVER SCREEN (Lines 1686-1700)**
|
||||||
|
- **Element:** `<div id="game-over-screen" class="screen">`
|
||||||
|
- **Purpose:** End game statistics and replay option
|
||||||
|
- **Components:**
|
||||||
|
- Final stats display (XP, time, tasks, streaks)
|
||||||
|
- Play again button
|
||||||
|
- **Status:** ❌ **OBSOLETE** - Handled in dedicated mode files
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📜 OBSOLETE SCRIPTS ANALYSIS
|
||||||
|
|
||||||
|
### **4. GAME MODE DATA SCRIPTS (Lines 1705-1710)**
|
||||||
|
- **Files:**
|
||||||
|
- `src/data/modes/mainGameData.js`
|
||||||
|
- `src/data/modes/humiliationGameData.js`
|
||||||
|
- `src/data/modes/trainingGameData.js`
|
||||||
|
- `src/data/modes/enduranceGameData.js`
|
||||||
|
- `src/data/modes/dressUpGameData.js`
|
||||||
|
- `src/data/gameDataManager.js`
|
||||||
|
- **Status:** ❌ **MAY BE OBSOLETE** - Check if still used by dedicated HTML files
|
||||||
|
|
||||||
|
### **5. GAME MODE MANAGER SCRIPT (Line 1843)**
|
||||||
|
- **File:** `src/core/gameModeManager.js`
|
||||||
|
- **Status:** ❌ **MAY BE OBSOLETE** - Check if still used by dedicated HTML files
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 OBSOLETE FUNCTIONALITY ANALYSIS
|
||||||
|
|
||||||
|
### **6. SCREEN NAVIGATION SYSTEM**
|
||||||
|
- **Functions:** `showScreen()` calls throughout JavaScript
|
||||||
|
- **References:** Lines 1892, 1893, 3807, 3808, 3872, 3874, 3876, 3899, 3900
|
||||||
|
- **Purpose:** Navigate between embedded game screens
|
||||||
|
- **Status:** ❌ **PARTIALLY OBSOLETE** - Still needed for media management screens, but game mode navigation should be removed
|
||||||
|
|
||||||
|
### **7. GAME STATE MANAGEMENT**
|
||||||
|
- **Elements:** Session stats, final stats, game mode tracking
|
||||||
|
- **Purpose:** Track progress within embedded game modes
|
||||||
|
- **Status:** ❌ **OBSOLETE** - Now handled in dedicated HTML files
|
||||||
|
|
||||||
|
### **8. TASK DISPLAY SYSTEM**
|
||||||
|
- **Elements:** Task images, task text, action buttons
|
||||||
|
- **Purpose:** Display and interact with game tasks
|
||||||
|
- **Status:** ❌ **OBSOLETE** - Now handled in dedicated HTML files
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 KEEP vs REMOVE ANALYSIS
|
||||||
|
|
||||||
|
### **✅ KEEP - Media Management Screens**
|
||||||
|
These screens are still used for media library management:
|
||||||
|
- `start-screen` - Home/landing page
|
||||||
|
- `library-screen` - Media library management
|
||||||
|
- `image-management-screen` - Image organization
|
||||||
|
- `audio-management-screen` - Audio management
|
||||||
|
- `video-management-screen` - Video management
|
||||||
|
- `photo-gallery-screen` - Photo viewing
|
||||||
|
- `annoyance-management-screen` - Settings management
|
||||||
|
|
||||||
|
### **❌ REMOVE - Game Mode Screens**
|
||||||
|
These screens are obsolete after moving to dedicated HTML files:
|
||||||
|
- `game-screen` - Main gameplay (moved to dedicated files)
|
||||||
|
- `paused-screen` - Game pause (moved to dedicated files)
|
||||||
|
- `game-over-screen` - End game stats (moved to dedicated files)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗂️ CLEANUP PHASES
|
||||||
|
|
||||||
|
### **PHASE 1: SCREEN REMOVAL**
|
||||||
|
|
||||||
|
#### Step 1.1: Remove Game Screens
|
||||||
|
- [ ] Delete `game-screen` element and all contents (Lines 1632-1677)
|
||||||
|
- [ ] Delete `paused-screen` element and all contents (Lines 1678-1685)
|
||||||
|
- [ ] Delete `game-over-screen` element and all contents (Lines 1686-1700)
|
||||||
|
|
||||||
|
#### Step 1.2: Update Screen Navigation
|
||||||
|
- [ ] Remove game screen references from `showScreen()` calls
|
||||||
|
- [ ] Keep media management screen navigation intact
|
||||||
|
- [ ] Remove obsolete screen transition JavaScript
|
||||||
|
|
||||||
|
### **PHASE 2: SCRIPT CLEANUP**
|
||||||
|
|
||||||
|
#### Step 2.1: Evaluate Game Mode Scripts
|
||||||
|
- [ ] Check if `mainGameData.js` is used by dedicated HTML files
|
||||||
|
- [ ] Check if `humiliationGameData.js` is used by dedicated files
|
||||||
|
- [ ] Check if `trainingGameData.js` is used by dedicated files
|
||||||
|
- [ ] Check if `enduranceGameData.js` is used by dedicated files
|
||||||
|
- [ ] Check if `dressUpGameData.js` is used by dedicated files
|
||||||
|
- [ ] Check if `gameDataManager.js` is used by dedicated files
|
||||||
|
|
||||||
|
#### Step 2.2: Remove Unused Scripts
|
||||||
|
- [ ] Remove script references from `index.html` if not used elsewhere
|
||||||
|
- [ ] Keep script references if still used by dedicated HTML files
|
||||||
|
|
||||||
|
#### Step 2.3: Evaluate Core Scripts
|
||||||
|
- [ ] Check if `gameModeManager.js` is used by dedicated HTML files
|
||||||
|
- [ ] Remove from `index.html` if not needed for media management
|
||||||
|
|
||||||
|
### **PHASE 3: JAVASCRIPT CLEANUP**
|
||||||
|
|
||||||
|
#### Step 3.1: Remove Game Mode Functions
|
||||||
|
- [ ] Remove task display functions
|
||||||
|
- [ ] Remove game state management functions
|
||||||
|
- [ ] Remove game statistics functions
|
||||||
|
- [ ] Remove game navigation functions (skip, complete, pause, etc.)
|
||||||
|
|
||||||
|
#### Step 3.2: Clean Screen Navigation
|
||||||
|
- [ ] Remove references to deleted screens in JavaScript
|
||||||
|
- [ ] Update screen navigation to only handle media management screens
|
||||||
|
- [ ] Clean up obsolete event listeners
|
||||||
|
|
||||||
|
#### Step 3.3: Remove Game Mode Variables
|
||||||
|
- [ ] Remove game state variables
|
||||||
|
- [ ] Remove task management variables
|
||||||
|
- [ ] Remove obsolete game mode tracking variables
|
||||||
|
|
||||||
|
### **PHASE 4: CSS CLEANUP**
|
||||||
|
|
||||||
|
#### Step 4.1: Remove Game Screen Styles
|
||||||
|
- [ ] Remove `.task-container` and related styles
|
||||||
|
- [ ] Remove `.task-image-container` styles
|
||||||
|
- [ ] Remove `.task-text-container` styles
|
||||||
|
- [ ] Remove `.action-buttons` styles
|
||||||
|
- [ ] Remove `.game-stats` styles
|
||||||
|
|
||||||
|
#### Step 4.2: Remove Game Mode Specific Styles
|
||||||
|
- [ ] Remove paused screen styles
|
||||||
|
- [ ] Remove game over screen styles
|
||||||
|
- [ ] Remove game mode specific animations and transitions
|
||||||
|
|
||||||
|
#### Step 4.3: Keep Media Management Styles
|
||||||
|
- [ ] Keep all styles for media management screens
|
||||||
|
- [ ] Keep start screen and library screen styles
|
||||||
|
- [ ] Keep general screen navigation styles
|
||||||
|
|
||||||
|
### **PHASE 5: HTML CLEANUP**
|
||||||
|
|
||||||
|
#### Step 5.1: Remove Obsolete Elements
|
||||||
|
- [ ] Remove task image containers
|
||||||
|
- [ ] Remove action button containers
|
||||||
|
- [ ] Remove game statistics displays
|
||||||
|
- [ ] Remove final stats displays
|
||||||
|
|
||||||
|
#### Step 5.2: Clean Comments and Documentation
|
||||||
|
- [ ] Remove comments referring to removed screens
|
||||||
|
- [ ] Update HTML structure comments
|
||||||
|
- [ ] Clean up obsolete TODO comments
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 ESTIMATED IMPACT
|
||||||
|
|
||||||
|
### **Code Reduction:**
|
||||||
|
- **HTML:** ~200 lines removed (obsolete game screens)
|
||||||
|
- **CSS:** ~300 lines removed (game mode specific styles)
|
||||||
|
- **JavaScript:** ~500 lines removed (game mode functions)
|
||||||
|
- **Scripts:** 5-7 script references potentially removed
|
||||||
|
- **Total:** ~1,000+ lines of obsolete code cleanup
|
||||||
|
|
||||||
|
### **Performance Benefits:**
|
||||||
|
- ✅ Reduced index.html complexity and load time
|
||||||
|
- ✅ Cleaner separation of concerns (media management vs gameplay)
|
||||||
|
- ✅ Reduced JavaScript bundle size
|
||||||
|
- ✅ Faster startup time for index.html
|
||||||
|
- ✅ Simplified debugging and maintenance
|
||||||
|
|
||||||
|
### **Architecture Benefits:**
|
||||||
|
- ✅ Clear separation between media management and gameplay
|
||||||
|
- ✅ index.html focused solely on media library management
|
||||||
|
- ✅ Dedicated HTML files handle all game mode functionality
|
||||||
|
- ✅ Reduced code duplication and conflicts
|
||||||
|
- ✅ Easier to maintain and extend individual game modes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ TESTING CHECKLIST
|
||||||
|
|
||||||
|
After each phase, verify:
|
||||||
|
- [ ] index.html loads and displays correctly
|
||||||
|
- [ ] Start screen navigation works
|
||||||
|
- [ ] Media library screens function properly
|
||||||
|
- [ ] Image, audio, video management still works
|
||||||
|
- [ ] Settings/annoyance management still works
|
||||||
|
- [ ] No JavaScript console errors
|
||||||
|
- [ ] Dedicated HTML files (quick-play.html, training-academy.html) still work
|
||||||
|
- [ ] No broken links or missing resources
|
||||||
|
- [ ] CSS styling remains consistent
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 DEPENDENCIES CHECK
|
||||||
|
|
||||||
|
Before cleanup, verify which dedicated HTML files use shared resources:
|
||||||
|
- [ ] Check if quick-play.html uses game mode data files
|
||||||
|
- [ ] Check if training-academy.html uses gameModeManager.js
|
||||||
|
- [ ] Check if any dedicated files import from src/data/modes/
|
||||||
|
- [ ] Check if any dedicated files use shared CSS from styles.css
|
||||||
|
- [ ] Ensure cleanup doesn't break shared dependencies
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 NOTES
|
||||||
|
|
||||||
|
- **Primary Goal:** Remove obsolete game mode infrastructure from index.html
|
||||||
|
- **Secondary Goal:** Maintain all media management functionality
|
||||||
|
- **Tertiary Goal:** Ensure dedicated HTML files continue working
|
||||||
|
- This cleanup addresses the architectural shift from embedded game modes to dedicated HTML files
|
||||||
|
- All game mode functionality has been successfully moved to dedicated files
|
||||||
|
- index.html should focus solely on being a media library management interface
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Document created after successful character image toggle implementation*
|
||||||
|
*Next: Execute cleanup phases to remove obsolete game mode infrastructure*
|
||||||
|
|
@ -603,6 +603,215 @@
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
color: #e8f5e8;
|
color: #e8f5e8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Video Control Panel Styles */
|
||||||
|
.control-sidebar {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
width: 220px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
border: 1px solid rgba(0, 212, 255, 0.3);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
gap: 10px;
|
||||||
|
height: fit-content;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-control-panel {
|
||||||
|
background: rgba(0, 0, 0, 0.9);
|
||||||
|
border: 1px solid rgba(139, 92, 246, 0.4);
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-control-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 12px;
|
||||||
|
background: rgba(139, 92, 246, 0.2);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-control-header:hover {
|
||||||
|
background: rgba(139, 92, 246, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-control-icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-control-title {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #E5E7EB;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-control-toggle {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-control-toggle.collapsed {
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-control-content {
|
||||||
|
padding: 12px;
|
||||||
|
display: block;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-control-content.collapsed {
|
||||||
|
display: none;
|
||||||
|
max-height: 0;
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #9CA3AF;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-btn {
|
||||||
|
background: rgba(139, 92, 246, 0.2);
|
||||||
|
color: #E5E7EB;
|
||||||
|
border: 1px solid rgba(139, 92, 246, 0.4);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 6px 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-btn:hover {
|
||||||
|
background: rgba(139, 92, 246, 0.4);
|
||||||
|
border-color: rgba(139, 92, 246, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-control {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-slider {
|
||||||
|
flex: 1;
|
||||||
|
height: 4px;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 2px;
|
||||||
|
outline: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-slider::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
background: #8B5CF6;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.volume-display {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #9CA3AF;
|
||||||
|
min-width: 35px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-select {
|
||||||
|
width: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
color: #E5E7EB;
|
||||||
|
border: 1px solid rgba(139, 92, 246, 0.4);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 6px 8px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-select:hover {
|
||||||
|
border-color: rgba(139, 92, 246, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.playlist-select:focus {
|
||||||
|
border-color: #8B5CF6;
|
||||||
|
box-shadow: 0 0 0 2px rgba(139, 92, 246, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-info {
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-video-name {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #E5E7EB;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-progress {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
height: 4px;
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, #8B5CF6, #EC4899);
|
||||||
|
width: 0%;
|
||||||
|
transition: width 0.1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-time {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
color: #9CA3AF;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -611,11 +820,59 @@
|
||||||
<!-- Video will be inserted here -->
|
<!-- Video will be inserted here -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Video Controls Overlay -->
|
<!-- Video Control Panel (Collapsible) -->
|
||||||
<div class="video-controls-overlay" id="videoControlsOverlay">
|
<div class="control-sidebar">
|
||||||
<button onclick="skipToNextVideo()">Next Video</button>
|
<div id="video-control-panel" class="video-control-panel">
|
||||||
<button onclick="toggleVideoOpacity()">Opacity</button>
|
<div class="video-control-header" onclick="toggleVideoControls()">
|
||||||
<button onclick="toggleVideoPlayback()">Play/Pause</button>
|
<span class="video-control-icon">🎬</span>
|
||||||
|
<span class="video-control-title">Video Controls</span>
|
||||||
|
<span id="video-control-toggle" class="video-control-toggle collapsed">▶</span>
|
||||||
|
</div>
|
||||||
|
<div id="video-control-content" class="video-control-content collapsed">
|
||||||
|
<!-- Playback Controls -->
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="control-row">
|
||||||
|
<button id="video-rewind" class="control-btn" title="Rewind 10s">⏪</button>
|
||||||
|
<button id="video-play-pause" class="control-btn" title="Play/Pause">⏸️</button>
|
||||||
|
<button id="video-forward" class="control-btn" title="Forward 10s">⏩</button>
|
||||||
|
<button id="video-skip" class="control-btn" title="Skip Video">⏭️</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Volume Control -->
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label">🔊 Volume</label>
|
||||||
|
<div class="volume-control">
|
||||||
|
<input type="range" id="video-volume" class="volume-slider" min="0" max="100" value="50">
|
||||||
|
<span id="video-volume-display" class="volume-display">50%</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Playlist Selection -->
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label">📂 Source</label>
|
||||||
|
<select id="video-playlist-select" class="playlist-select">
|
||||||
|
<option value="random">🎲 Random Videos</option>
|
||||||
|
<option value="playlist1">📝 Playlist 1</option>
|
||||||
|
<option value="playlist2">📝 Playlist 2</option>
|
||||||
|
<option value="playlist3">📝 Playlist 3</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Video Info -->
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="video-info">
|
||||||
|
<div id="current-video-name" class="current-video-name">No video loaded</div>
|
||||||
|
<div id="video-progress" class="video-progress">
|
||||||
|
<div class="progress-bar">
|
||||||
|
<div id="progress-fill" class="progress-fill"></div>
|
||||||
|
</div>
|
||||||
|
<div id="video-time" class="video-time">00:00 / 00:00</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Navigation -->
|
<!-- Navigation -->
|
||||||
|
|
@ -1051,7 +1308,16 @@
|
||||||
|
|
||||||
video.onloadeddata = () => {
|
video.onloadeddata = () => {
|
||||||
console.log('🎬 Video data loaded');
|
console.log('🎬 Video data loaded');
|
||||||
document.getElementById('videoControlsOverlay').style.display = 'block';
|
setupVideoControlListeners(); // Initialize control functionality
|
||||||
|
};
|
||||||
|
|
||||||
|
video.onloadedmetadata = () => {
|
||||||
|
console.log('🎬 Video metadata loaded');
|
||||||
|
// Update video info once metadata is available
|
||||||
|
setTimeout(() => {
|
||||||
|
updateVideoInfo();
|
||||||
|
updateVideoProgress();
|
||||||
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
video.onerror = (e) => {
|
video.onerror = (e) => {
|
||||||
|
|
@ -1077,6 +1343,12 @@
|
||||||
if (video) {
|
if (video) {
|
||||||
video.src = `file://${nextVideo.fullPath}`;
|
video.src = `file://${nextVideo.fullPath}`;
|
||||||
console.log(`🎬 Switched to: ${nextVideo.name}`);
|
console.log(`🎬 Switched to: ${nextVideo.name}`);
|
||||||
|
|
||||||
|
// Update video info for the new video
|
||||||
|
video.addEventListener('loadedmetadata', function() {
|
||||||
|
updateVideoInfo();
|
||||||
|
updateVideoProgress();
|
||||||
|
}, { once: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1107,6 +1379,214 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle Video Controls Panel
|
||||||
|
function toggleVideoControls() {
|
||||||
|
const content = document.getElementById('video-control-content');
|
||||||
|
const toggle = document.getElementById('video-control-toggle');
|
||||||
|
|
||||||
|
if (content.classList.contains('collapsed')) {
|
||||||
|
content.classList.remove('collapsed');
|
||||||
|
toggle.classList.remove('collapsed');
|
||||||
|
toggle.textContent = '▼';
|
||||||
|
} else {
|
||||||
|
content.classList.add('collapsed');
|
||||||
|
toggle.classList.add('collapsed');
|
||||||
|
toggle.textContent = '▶';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup Complete Video Control System (from Quick Play)
|
||||||
|
function setupVideoControlListeners() {
|
||||||
|
const video = document.getElementById('backgroundVideo');
|
||||||
|
if (!video) {
|
||||||
|
console.log('⚠️ Background video element not found during control setup');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🎮 Setting up video control listeners...');
|
||||||
|
|
||||||
|
// Play/Pause control
|
||||||
|
const playPauseBtn = document.getElementById('video-play-pause');
|
||||||
|
if (playPauseBtn) {
|
||||||
|
playPauseBtn.addEventListener('click', async () => {
|
||||||
|
const currentVideo = document.getElementById('backgroundVideo');
|
||||||
|
if (!currentVideo) {
|
||||||
|
console.log('No video element found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (currentVideo.paused) {
|
||||||
|
await currentVideo.play();
|
||||||
|
playPauseBtn.textContent = '⏸️';
|
||||||
|
playPauseBtn.title = 'Pause';
|
||||||
|
console.log('▶️ Video resumed');
|
||||||
|
} else {
|
||||||
|
currentVideo.pause();
|
||||||
|
playPauseBtn.textContent = '▶️';
|
||||||
|
playPauseBtn.title = 'Play';
|
||||||
|
console.log('⏸️ Video paused');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Video playback error:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rewind 10 seconds
|
||||||
|
const rewindBtn = document.getElementById('video-rewind');
|
||||||
|
if (rewindBtn) {
|
||||||
|
rewindBtn.addEventListener('click', () => {
|
||||||
|
const currentVideo = document.getElementById('backgroundVideo');
|
||||||
|
if (currentVideo && currentVideo.duration && isFinite(currentVideo.duration)) {
|
||||||
|
currentVideo.currentTime = Math.max(0, currentVideo.currentTime - 10);
|
||||||
|
console.log('⏪ Rewound 10 seconds');
|
||||||
|
} else {
|
||||||
|
console.log('Cannot rewind: video not ready');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward 10 seconds
|
||||||
|
const forwardBtn = document.getElementById('video-forward');
|
||||||
|
if (forwardBtn) {
|
||||||
|
forwardBtn.addEventListener('click', () => {
|
||||||
|
const currentVideo = document.getElementById('backgroundVideo');
|
||||||
|
if (currentVideo && currentVideo.duration && isFinite(currentVideo.duration)) {
|
||||||
|
currentVideo.currentTime = Math.min(currentVideo.duration, currentVideo.currentTime + 10);
|
||||||
|
console.log('⏩ Fast forwarded 10 seconds');
|
||||||
|
} else {
|
||||||
|
console.log('Cannot fast forward: video not ready');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip video
|
||||||
|
const skipBtn = document.getElementById('video-skip');
|
||||||
|
if (skipBtn) {
|
||||||
|
skipBtn.addEventListener('click', () => {
|
||||||
|
skipToNextVideo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Volume control
|
||||||
|
const volumeSlider = document.getElementById('video-volume');
|
||||||
|
const volumeDisplay = document.getElementById('video-volume-display');
|
||||||
|
if (volumeSlider && volumeDisplay) {
|
||||||
|
volumeSlider.addEventListener('input', (e) => {
|
||||||
|
const currentVideo = document.getElementById('backgroundVideo');
|
||||||
|
if (currentVideo) {
|
||||||
|
const volume = e.target.value / 100;
|
||||||
|
currentVideo.volume = volume;
|
||||||
|
volumeDisplay.textContent = e.target.value + '%';
|
||||||
|
console.log(`🔊 Volume set to ${e.target.value}% (${volume})`);
|
||||||
|
|
||||||
|
// Auto-mute when volume is 0
|
||||||
|
if (volume === 0) {
|
||||||
|
currentVideo.muted = true;
|
||||||
|
} else if (currentVideo.muted && volume > 0) {
|
||||||
|
currentVideo.muted = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn('⚠️ No background video element found for volume control');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set initial volume when video loads
|
||||||
|
const initializeVolume = () => {
|
||||||
|
const currentVideo = document.getElementById('backgroundVideo');
|
||||||
|
if (currentVideo) {
|
||||||
|
currentVideo.volume = volumeSlider.value / 100;
|
||||||
|
volumeDisplay.textContent = volumeSlider.value + '%';
|
||||||
|
console.log(`🔊 Initial volume set to ${volumeSlider.value}%`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try to set initial volume now and also when video loads
|
||||||
|
initializeVolume();
|
||||||
|
|
||||||
|
// Also set up a listener for when new videos are loaded
|
||||||
|
document.addEventListener('videoLoaded', initializeVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Playlist selection
|
||||||
|
const playlistSelect = document.getElementById('video-playlist-select');
|
||||||
|
if (playlistSelect) {
|
||||||
|
playlistSelect.addEventListener('change', (e) => {
|
||||||
|
const selectedPlaylist = e.target.value;
|
||||||
|
console.log('🎵 Playlist changed to:', selectedPlaylist);
|
||||||
|
// For now, just load a random video from current library
|
||||||
|
skipToNextVideo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Video progress and time updates
|
||||||
|
video.addEventListener('timeupdate', updateVideoProgress);
|
||||||
|
video.addEventListener('loadedmetadata', updateVideoInfo);
|
||||||
|
video.addEventListener('play', () => {
|
||||||
|
const playPauseBtn = document.getElementById('video-play-pause');
|
||||||
|
if (playPauseBtn) {
|
||||||
|
playPauseBtn.textContent = '⏸️';
|
||||||
|
playPauseBtn.title = 'Pause';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
video.addEventListener('pause', () => {
|
||||||
|
const playPauseBtn = document.getElementById('video-play-pause');
|
||||||
|
if (playPauseBtn) {
|
||||||
|
playPauseBtn.textContent = '▶️';
|
||||||
|
playPauseBtn.title = 'Play';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initial updates
|
||||||
|
setTimeout(() => {
|
||||||
|
updateVideoInfo();
|
||||||
|
updateVideoProgress();
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
console.log('✅ Video control listeners set up successfully');
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateVideoProgress() {
|
||||||
|
const video = document.getElementById('backgroundVideo');
|
||||||
|
const progressFill = document.getElementById('progress-fill');
|
||||||
|
const videoTime = document.getElementById('video-time');
|
||||||
|
|
||||||
|
if (video && progressFill && videoTime && video.duration && isFinite(video.duration)) {
|
||||||
|
const progress = (video.currentTime / video.duration) * 100;
|
||||||
|
progressFill.style.width = isNaN(progress) ? '0%' : progress + '%';
|
||||||
|
|
||||||
|
const currentMinutes = Math.floor(video.currentTime / 60);
|
||||||
|
const currentSeconds = Math.floor(video.currentTime % 60);
|
||||||
|
const durationMinutes = Math.floor(video.duration / 60);
|
||||||
|
const durationSeconds = Math.floor(video.duration % 60);
|
||||||
|
|
||||||
|
videoTime.textContent = `${currentMinutes.toString().padStart(2, '0')}:${currentSeconds.toString().padStart(2, '0')} / ${durationMinutes.toString().padStart(2, '0')}:${durationSeconds.toString().padStart(2, '0')}`;
|
||||||
|
} else if (videoTime) {
|
||||||
|
videoTime.textContent = '00:00 / 00:00';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateVideoInfo() {
|
||||||
|
const video = document.getElementById('backgroundVideo');
|
||||||
|
const videoName = document.getElementById('current-video-name');
|
||||||
|
|
||||||
|
if (video && videoName) {
|
||||||
|
const videoPath = video.src || (video.querySelector('source') && video.querySelector('source').src);
|
||||||
|
if (videoPath) {
|
||||||
|
const fileName = videoPath.split('/').pop().split('\\').pop().split('.')[0];
|
||||||
|
const formattedName = fileName.replace(/[-_]/g, ' ');
|
||||||
|
// Capitalize each word
|
||||||
|
const displayName = formattedName.split(' ').map(word =>
|
||||||
|
word.charAt(0).toUpperCase() + word.slice(1)
|
||||||
|
).join(' ');
|
||||||
|
videoName.textContent = displayName;
|
||||||
|
} else {
|
||||||
|
videoName.textContent = 'No video loaded';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Training Mode Selection
|
// Training Mode Selection
|
||||||
function setupTrainingModeSelection() {
|
function setupTrainingModeSelection() {
|
||||||
const container = document.getElementById('trainingModeSelection');
|
const container = document.getElementById('trainingModeSelection');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue