diff --git a/PROJECT_OVERVIEW.md b/PROJECT_OVERVIEW.md index 258bac6..dc9a90e 100644 --- a/PROJECT_OVERVIEW.md +++ b/PROJECT_OVERVIEW.md @@ -45,6 +45,8 @@ MovieMapper is a desktop application designed for organizing and managing movie - **File Untagging**: Click on already tagged files to remove the tag - **File Organization**: Move files to "extras" folder for better organization - **Problematic File Handling**: Identifies and flags files that cause issues during metadata extraction +- **Video Preview**: Click the 🎬 icon next to any file to preview it in a centered modal window +- **MKV File Support**: MKV files show a warning and provide option to open in default media player - **Warning Sign Display**: Files with issues are indicated with a warning sign (⚠️) in the UI but this does not affect the actual file name ### 4. Technical Features diff --git a/main.js b/main.js index bc206a0..d628da0 100644 --- a/main.js +++ b/main.js @@ -495,6 +495,39 @@ ipcMain.handle('move-to-extras', async (event, filePath) => { } }); +// IPC handler for opening file in default player +ipcMain.handle('open-file-in-player', async (event, filePath) => { + try { + const { exec } = require('child_process'); + + // Open file in default player based on OS + let command; + if (process.platform === 'darwin') { + // macOS + command = `open "${filePath}"`; + } else if (process.platform === 'win32') { + // Windows + command = `start "" "${filePath}"`; + } else { + // Linux + command = `xdg-open "${filePath}"`; + } + + exec(command, (error, stdout, stderr) => { + if (error) { + console.error('Error opening file:', error); + return { success: false, error: error.message }; + } + console.log('File opened successfully:', filePath); + }); + + return { success: true, message: 'File opened in default player' }; + } catch (error) { + console.error('Error opening file in player:', error); + return { success: false, error: error.message }; + } +}); + // This method will be called when Electron has finished // initialization and is ready to create browser windows. app.whenReady().then(createWindow); diff --git a/renderer.js b/renderer.js index d66036a..0774443 100644 --- a/renderer.js +++ b/renderer.js @@ -89,6 +89,7 @@ function displayFiles(files) {
`; @@ -136,6 +137,14 @@ function displayFiles(files) { }); }); + // Add click handler for preview button + const previewBtn = fileItem.querySelector('.video-preview-btn'); + previewBtn.addEventListener('click', function(e) { + e.stopPropagation(); // Prevent event bubbling + const filePath = this.dataset.filePath; + openVideoPreview(filePath); + }); + fileListEl.appendChild(fileItem); }); } @@ -629,5 +638,198 @@ function debounce(func, wait) { }; } +// Modal element for video preview +let videoPreviewModal = null; + // Initialize the application -console.log('Movie Mapper application initialized'); \ No newline at end of file +console.log('Movie Mapper application initialized'); + +// Function to open video preview modal +function openVideoPreview(filePath) { + console.log('Opening video preview for:', filePath); + + // Create modal if it doesn't exist + if (!videoPreviewModal) { + createVideoPreviewModal(); + } + + // Show the modal + videoPreviewModal.style.display = 'block'; + + // Load video content + loadVideoPreview(filePath); +} + +// Function to create video preview modal +function createVideoPreviewModal() { + // Create modal container + videoPreviewModal = document.createElement('div'); + videoPreviewModal.id = 'video-preview-modal'; + 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() { + videoPreviewModal.style.display = 'none'; + }); + + // 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); + videoPreviewModal.appendChild(modalContent); + + // Add click outside to close + videoPreviewModal.addEventListener('click', function(e) { + if (e.target === videoPreviewModal) { + videoPreviewModal.style.display = 'none'; + } + }); + + // Add to body + document.body.appendChild(videoPreviewModal); +} + +// Function to load video preview +async function 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 = `Loading: ${filePath.split('/').pop()}`; + + try { + // Check if file exists + const fs = require('fs'); + 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 = ` + File: ${fileName}+ Warning: MKV files are not supported for in-app preview. +
++ This file will open in your default media player. +
+ +Error loading video preview
'; + loadingIndicator.style.display = 'none'; + } +}