- Split large renderer.js file into 8 separate class files: - AppState.js: Manages application state - FileListManager.js: Handles file list display and manipulation - TagManager.js: Manages file tagging functionality - EpisodeManager.js: Handles episode number editing and highlighting - SearchManager.js: Manages TVDB search and show selection - FileManager.js: Handles file operations - ModalManager.js: Manages video preview modal - ProgressManager.js: Manages progress display - UIManager.js: Main coordinator for UI functionality - Follows SOLID principles and single responsibility - Improves code maintainability and testability - All syntax verified with node --check
211 lines
6.0 KiB
JavaScript
211 lines
6.0 KiB
JavaScript
const { ipcRenderer } = require('electron');
|
|
const fs = require('fs');
|
|
|
|
/**
|
|
* ModalManager - Manages video preview modal
|
|
*/
|
|
class ModalManager {
|
|
constructor() {
|
|
this.videoPreviewModal = null;
|
|
}
|
|
|
|
/**
|
|
* Open video preview modal
|
|
* @param {string} filePath - File path to preview
|
|
*/
|
|
async openVideoPreview(filePath) {
|
|
console.log('Opening video preview for:', filePath);
|
|
|
|
// Create modal if it doesn't exist
|
|
if (!this.videoPreviewModal) {
|
|
this.createVideoPreviewModal();
|
|
}
|
|
|
|
// Show the modal
|
|
this.videoPreviewModal.style.display = 'block';
|
|
|
|
// Load video content
|
|
await this.loadVideoPreview(filePath);
|
|
}
|
|
|
|
/**
|
|
* Create video preview modal
|
|
*/
|
|
createVideoPreviewModal() {
|
|
// Create modal container
|
|
this.videoPreviewModal = document.createElement('div');
|
|
this.videoPreviewModal.id = 'video-preview-modal';
|
|
this.videoPreviewModal.style.cssText = `
|
|
display: none;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: rgba(0, 0, 0, 0.9);
|
|
z-index: 1000;
|
|
justify-content: center;
|
|
align-items: center;
|
|
overflow: auto;
|
|
`;
|
|
|
|
// Create modal content
|
|
const modalContent = document.createElement('div');
|
|
modalContent.style.cssText = `
|
|
position: relative;
|
|
max-width: 90%;
|
|
max-height: 90%;
|
|
background-color: #fff;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
margin: 20px;
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
|
`;
|
|
|
|
// Create close button
|
|
const closeButton = document.createElement('span');
|
|
closeButton.innerHTML = '×';
|
|
closeButton.style.cssText = `
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 15px;
|
|
font-size: 30px;
|
|
font-weight: bold;
|
|
color: #aaa;
|
|
cursor: pointer;
|
|
transition: color 0.3s;
|
|
`;
|
|
|
|
closeButton.addEventListener('mouseenter', function() {
|
|
this.style.color = '#000';
|
|
});
|
|
|
|
closeButton.addEventListener('click', function() {
|
|
this.videoPreviewModal.style.display = 'none';
|
|
}.bind(this));
|
|
|
|
// Create video container
|
|
const videoContainer = document.createElement('div');
|
|
videoContainer.id = 'video-preview-container';
|
|
videoContainer.style.cssText = `
|
|
text-align: center;
|
|
margin-bottom: 15px;
|
|
`;
|
|
|
|
// Create file info display
|
|
const fileInfo = document.createElement('div');
|
|
fileInfo.id = 'video-preview-file-info';
|
|
fileInfo.style.cssText = `
|
|
text-align: center;
|
|
margin-bottom: 15px;
|
|
padding: 10px;
|
|
background-color: #f8f9fa;
|
|
border-radius: 5px;
|
|
font-size: 14px;
|
|
`;
|
|
|
|
// Create loading indicator
|
|
const loadingIndicator = document.createElement('div');
|
|
loadingIndicator.id = 'video-preview-loading';
|
|
loadingIndicator.textContent = 'Loading video preview...';
|
|
loadingIndicator.style.cssText = `
|
|
text-align: center;
|
|
padding: 20px;
|
|
font-size: 16px;
|
|
color: #666;
|
|
`;
|
|
|
|
// Assemble modal
|
|
modalContent.appendChild(closeButton);
|
|
modalContent.appendChild(fileInfo);
|
|
modalContent.appendChild(videoContainer);
|
|
modalContent.appendChild(loadingIndicator);
|
|
this.videoPreviewModal.appendChild(modalContent);
|
|
|
|
// Add click outside to close
|
|
this.videoPreviewModal.addEventListener('click', function(e) {
|
|
if (e.target === this.videoPreviewModal) {
|
|
this.videoPreviewModal.style.display = 'none';
|
|
}
|
|
}.bind(this));
|
|
|
|
// Add to body
|
|
document.body.appendChild(this.videoPreviewModal);
|
|
}
|
|
|
|
/**
|
|
* Load video preview
|
|
* @param {string} filePath - File path to load
|
|
*/
|
|
async loadVideoPreview(filePath) {
|
|
const fileInfo = document.getElementById('video-preview-file-info');
|
|
const videoContainer = document.getElementById('video-preview-container');
|
|
const loadingIndicator = document.getElementById('video-preview-loading');
|
|
|
|
// Show loading
|
|
loadingIndicator.style.display = 'block';
|
|
videoContainer.innerHTML = '';
|
|
fileInfo.innerHTML = `<strong>Loading:</strong> ${filePath.split('/').pop()}`;
|
|
|
|
try {
|
|
// Check if file exists
|
|
if (!fs.existsSync(filePath)) {
|
|
throw new Error('File not found');
|
|
}
|
|
|
|
// Get file stats for info
|
|
const stats = fs.statSync(filePath);
|
|
const fileName = filePath.split('/').pop();
|
|
|
|
// Update file info
|
|
fileInfo.innerHTML = `
|
|
<strong>File:</strong> ${fileName}<br>
|
|
<strong>Size:</strong> ${(stats.size / (1024 * 1024)).toFixed(2)} MB<br>
|
|
<strong>Path:</strong> ${filePath}
|
|
`;
|
|
|
|
// For MKV files, open directly in default player
|
|
const ext = filePath.toLowerCase().split('.').pop();
|
|
if (ext === 'mkv') {
|
|
// Close the modal and open in default player directly
|
|
this.videoPreviewModal.style.display = 'none';
|
|
ipcRenderer.invoke('open-file-in-player', filePath);
|
|
} else {
|
|
// For other formats, try to create a video player
|
|
videoContainer.innerHTML = `
|
|
<video id="preview-video" controls style="width: 100%; max-width: 800px; height: auto; margin: 0 auto; display: block;">
|
|
<source src="${filePath}" type="video/mp4">
|
|
Your browser does not support the video tag.
|
|
</video>
|
|
`;
|
|
|
|
// Hide loading
|
|
loadingIndicator.style.display = 'none';
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading video preview:', error);
|
|
fileInfo.innerHTML = `<strong>Error:</strong> Could not load preview for ${filePath}`;
|
|
videoContainer.innerHTML = '<p style="color: #dc3545; text-align: center;">Error loading video preview</p>';
|
|
loadingIndicator.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Close the video preview modal
|
|
*/
|
|
closeVideoPreview() {
|
|
if (this.videoPreviewModal) {
|
|
this.videoPreviewModal.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the modal element
|
|
* @returns {HTMLElement|null} Modal element
|
|
*/
|
|
getModal() {
|
|
return this.videoPreviewModal;
|
|
}
|
|
}
|
|
|
|
module.exports = ModalManager; |