const { ipcRenderer } = require('electron'); const path = require('path'); // DOM Elements const selectDirBtn = document.getElementById('select-dir-btn'); const selectedDirEl = document.getElementById('selected-dir'); const searchInput = document.getElementById('search-input'); const searchResultsEl = document.getElementById('search-results'); const fileListEl = document.getElementById('file-list'); const showDetailsEl = document.getElementById('show-details'); // Current state let currentDirectory = null; let currentFiles = []; let currentShow = null; let currentSeasons = []; let currentEpisodes = []; // Event Listeners selectDirBtn.addEventListener('click', selectDirectory); searchInput.addEventListener('input', debounce(searchShows, 300)); document.getElementById('test-api-btn').addEventListener('click', testTVDBAPI); // Select directory function async function selectDirectory() { try { // Use IPC to handle directory selection const result = await ipcRenderer.invoke('select-directory'); if (result.success) { const directory = result.directory; currentDirectory = directory; selectedDirEl.textContent = `Selected: ${directory}`; // Scan the directory for media files await scanDirectory(directory); } else { throw new Error(result.error); } } catch (error) { console.error('Error selecting directory:', error); alert(`Error: ${error.message}`); } } // Scan directory for media files async function scanDirectory(directoryPath) { try { const result = await ipcRenderer.invoke('scan-directory', directoryPath); if (result.success) { currentFiles = result.files; displayFiles(currentFiles); } else { throw new Error(result.error); } } catch (error) { console.error('Error scanning directory:', error); alert(`Error scanning directory: ${error.message}`); } } // Display files in the UI function displayFiles(files) { fileListEl.innerHTML = ''; if (files.length === 0) { fileListEl.innerHTML = '
No media files found in this directory.
'; return; } files.forEach(file => { const fileItem = document.createElement('div'); fileItem.className = 'file-item'; // Use actual duration from file metadata const duration = file.duration || '00:00'; const quality = file.quality || 'unknown'; const fps = file.fps || 'unknown'; // Add label for problematic files const problemLabel = file.isProblematic ? '⚠️ ' : ''; fileItem.innerHTML = `Error: ${error.message}
`; } } // Test TVDB API connectivity async function testTVDBAPI() { try { const result = await ipcRenderer.invoke('test-tvdb-api'); console.log('TVDB API Test:', result); if (result.success) { console.log('TVDB API is working:', result.message); alert('TVDB API Test Successful!\n' + result.message); } else { console.error('TVDB API test failed:', result.error); alert('TVDB API Test Failed!\n' + result.error); } } catch (error) { console.error('Error testing TVDB API:', error); alert('Error testing TVDB API: ' + error.message); } } // Add a test button to the UI (you can add this to the HTML or call it manually) // For now, we'll just make it available in the console console.log('TVDB API test function available: testTVDBAPI()'); // Debug function to log problematic file info async function debugProblematicFile(filePath) { try { const result = await ipcRenderer.invoke('log-file-info', filePath); if (result.success) { console.log('File info:', result.fileInfo); } else { console.error('Failed to get file info:', result.error); } } catch (error) { console.error('Error debugging file:', error); } } // Display search results function displaySearchResults(results) { searchResultsEl.innerHTML = ''; if (results.length === 0) { searchResultsEl.innerHTML = 'No shows found.
'; return; } results.forEach(show => { const resultItem = document.createElement('div'); resultItem.className = 'search-result-item'; // Create a more detailed display let resultText = show.seriesName || show.name; if (show.firstAired) { resultText += ` (${show.firstAired})`; } resultItem.textContent = resultText; resultItem.addEventListener('click', () => selectShow(show)); searchResultsEl.appendChild(resultItem); }); } // Select a show and display more details async function selectShow(show) { console.log('Selected show:', show); currentShow = show; // Display show title document.getElementById('show-title').textContent = show.seriesName || show.name; // Fetch show details including seasons try { const result = await ipcRenderer.invoke('get-show-details', show.id); if (result.success && result.data) { const showData = result.data; currentSeasons = showData.seasons || []; // Display seasons - since we're not getting seasons from the API directly, // we'll show a message indicating we need to fetch seasons separately if (currentSeasons.length === 0) { document.getElementById('seasons-container').innerHTML = 'Seasons will be loaded when you click on a season.
'; } else { displaySeasons(currentSeasons); } } else { console.error('Failed to fetch show details:', result.error); document.getElementById('seasons-container').innerHTML = 'Error loading seasons: ' + (result.error || 'Unknown error') + '
'; } } catch (error) { console.error('Error fetching show details:', error); document.getElementById('seasons-container').innerHTML = 'Error loading seasons: ' + error.message + '
'; } } // Display seasons with episode counts function displaySeasons(seasons) { const seasonsContainer = document.getElementById('seasons-container'); seasonsContainer.innerHTML = ''; if (!seasons || seasons.length === 0) { seasonsContainer.innerHTML = 'No seasons available.
'; return; } // Create a container for seasons const seasonsList = document.createElement('div'); seasonsList.style.marginTop = '10px'; seasons.forEach(season => { const seasonItem = document.createElement('div'); seasonItem.className = 'season-item'; seasonItem.style.padding = '12px'; seasonItem.style.margin = '8px 0'; seasonItem.style.border = '1px solid #ddd'; seasonItem.style.borderRadius = '6px'; seasonItem.style.cursor = 'pointer'; seasonItem.style.backgroundColor = '#f8f9fa'; seasonItem.style.display = 'flex'; seasonItem.style.justifyContent = 'space-between'; seasonItem.style.alignItems = 'center'; // Format season display with episode count let seasonDisplay = `Season ${season.number}`; if (season.type && season.type !== 'Unknown') { seasonDisplay += ` (${season.type})`; } const episodeCount = season.episodeCount || 0; seasonItem.innerHTML = ` ${seasonDisplay} ${episodeCount} episodes `; // Add click event to fetch episodes seasonItem.addEventListener('click', () => { fetchAndDisplayEpisodes(currentShow.id, season.number); }); seasonsList.appendChild(seasonItem); }); seasonsContainer.appendChild(seasonsList); } // Fetch and display episodes for a season async function fetchAndDisplayEpisodes(showId, seasonNumber) { try { // Show loading message while fetching document.getElementById('seasons-container').innerHTML = 'Loading episodes...
'; const result = await ipcRenderer.invoke('get-season-episodes', showId, seasonNumber); if (result.success && result.data) { const episodes = result.data.episodes || []; displayEpisodes(episodes); } else { console.error('Failed to fetch episodes:', result.error); document.getElementById('seasons-container').innerHTML = 'Error loading episodes: ' + (result.error || 'Unknown error') + '
'; } } catch (error) { console.error('Error fetching episodes:', error); // Show a more user-friendly error message document.getElementById('seasons-container').innerHTML = `Error loading episodes: ${error.message || 'Failed to load episodes'}
Note: This may be due to API limitations with the TVDB v4 API.
No episodes available.
'; return; } // Create a container for episodes table const episodesTable = document.createElement('div'); episodesTable.style.marginTop = '10px'; episodesTable.style.border = '1px solid #ddd'; episodesTable.style.borderRadius = '6px'; episodesTable.style.overflow = 'hidden'; // Create table header const tableHeader = document.createElement('div'); tableHeader.style.display = 'grid'; tableHeader.style.gridTemplateColumns = '1fr 1fr'; tableHeader.style.backgroundColor = '#f8f9fa'; tableHeader.style.padding = '10px'; tableHeader.style.fontWeight = 'bold'; tableHeader.style.borderBottom = '1px solid #ddd'; tableHeader.innerHTML = `