@@ -71,10 +71,17 @@ async function loadStorageInfo() {
7171 * Renders the table of scheduled and in-progress recording jobs.
7272 */
7373function renderScheduledJobs ( ) {
74- const tbody = UIElements . dvrJobsTbody ;
7574 const jobs = dvrState . scheduledJobs || [ ] ;
75+ const hasJobs = jobs . length > 0 ;
76+
77+ // FIX: Toggle visibility of the entire table container vs the message
78+ UIElements . noDvrJobsMessage . classList . toggle ( 'hidden' , hasJobs ) ;
79+ UIElements . dvrJobsTableContainer . classList . toggle ( 'hidden' , ! hasJobs ) ;
80+
81+ // FIX: Show/hide the "Clear All" button
82+ UIElements . clearScheduledDvrBtn . classList . toggle ( 'hidden' , ! hasJobs ) ;
7683
77- UIElements . noDvrJobsMessage . classList . toggle ( 'hidden' , jobs . length === 0 ) ;
84+ const tbody = UIElements . dvrJobsTbody ;
7885 tbody . innerHTML = '' ;
7986
8087 jobs . forEach ( job => {
@@ -85,7 +92,6 @@ function renderScheduledJobs() {
8592 ? `<button class="status-badge ${ job . status } view-error-btn" data-job-id="${ job . id } ">${ job . status } </button>`
8693 : `<span class="status-badge ${ job . status } ">${ job . status } </span>` ;
8794
88- // NEW: Conflict Icon
8995 const conflictIcon = job . isConflicting ?
9096 `<svg class="h-5 w-5 text-yellow-400" fill="currentColor" viewBox="0 0 20 20" title="This recording conflicts with another scheduled recording."><path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.21 3.03-1.742 3.03H4.42c-1.532 0-2.492-1.696-1.742-3.03l5.58-9.92zM10 13a1 1 0 110-2 1 1 0 010 2zm-1.75-5.25a.75.75 0 00-1.5 0v3.5a.75.75 0 001.5 0v-3.5z" clip-rule="evenodd" /></svg>` : '' ;
9197
@@ -97,7 +103,6 @@ function renderScheduledJobs() {
97103 <td>${ startTime } </td>
98104 <td>${ endTime } </td>
99105 <td>${ statusHTML } </td>
100- <!-- NEW: Conflict Cell -->
101106 <td class="text-center">${ conflictIcon } </td>
102107 <td class="text-right">
103108 <div class="flex items-center justify-end gap-3">
@@ -124,14 +129,22 @@ function renderScheduledJobs() {
124129 } ) ;
125130}
126131
132+
127133/**
128134 * Renders the table of completed recordings.
129135 */
130136function renderCompletedRecordings ( ) {
131- const tbody = UIElements . dvrRecordingsTbody ;
132137 const recordings = dvrState . completedRecordings || [ ] ;
138+ const hasRecordings = recordings . length > 0 ;
133139
134- UIElements . noDvrRecordingsMessage . classList . toggle ( 'hidden' , recordings . length === 0 ) ;
140+ // FIX: Toggle visibility of the entire table container vs the message
141+ UIElements . noDvrRecordingsMessage . classList . toggle ( 'hidden' , hasRecordings ) ;
142+ UIElements . dvrRecordingsTableContainer . classList . toggle ( 'hidden' , ! hasRecordings ) ;
143+
144+ // FIX: Show/hide the "Clear All" button
145+ UIElements . clearCompletedDvrBtn . classList . toggle ( 'hidden' , ! hasRecordings ) ;
146+
147+ const tbody = UIElements . dvrRecordingsTbody ;
135148 tbody . innerHTML = '' ;
136149
137150 recordings . forEach ( rec => {
@@ -159,6 +172,7 @@ function renderCompletedRecordings() {
159172 } ) ;
160173}
161174
175+
162176/**
163177 * NEW: Renders the storage usage bar.
164178 * @param {object } storageData - Object with total, used, and percentage properties.
@@ -315,10 +329,8 @@ export function setupDvrEventListeners() {
315329 }
316330 } ) ;
317331
318- // NEW: Manual Recording Form Handler
319332 UIElements . manualRecordingForm . addEventListener ( 'submit' , async ( e ) => {
320333 e . preventDefault ( ) ;
321- // MODIFIED: Read channel info from hidden inputs
322334 const channelId = UIElements . manualRecChannelId . value ;
323335 const channelName = UIElements . manualRecChannelName . value ;
324336 const startTime = UIElements . manualRecStart . value ;
@@ -348,7 +360,6 @@ export function setupDvrEventListeners() {
348360 if ( res . ok ) {
349361 showNotification ( 'Manual recording scheduled successfully.' ) ;
350362 UIElements . manualRecordingForm . reset ( ) ;
351- // MODIFIED: Reset the channel display text and hidden inputs
352363 UIElements . manualRecSelectedChannelName . textContent = 'No channel selected' ;
353364 UIElements . manualRecChannelId . value = '' ;
354365 UIElements . manualRecChannelName . value = '' ;
@@ -360,18 +371,42 @@ export function setupDvrEventListeners() {
360371 }
361372 } ) ;
362373
363- // MODIFIED: Add event listener for the new "Select Channel" button
364374 if ( UIElements . manualRecChannelSelectBtn ) {
365375 UIElements . manualRecChannelSelectBtn . addEventListener ( 'click' , ( ) => {
366- // Use a data attribute to signal that the modal is opened for DVR
367376 document . body . dataset . channelSelectorContext = 'dvr' ;
368- populateChannelSelector ( ) ; // Populate the modal with channels
377+ populateChannelSelector ( ) ;
369378 openModal ( UIElements . multiviewChannelSelectorModal ) ;
370379 } ) ;
371380 }
372381
373- // MODIFIED: The specific listeners for the channel selector modal list and cancel button
374- // have been removed from this file. They will be handled by the central listener in main.js.
382+ // NEW: Event listeners for the "Clear All" buttons
383+ UIElements . clearScheduledDvrBtn . addEventListener ( 'click' , ( ) => {
384+ showConfirm (
385+ 'Clear All Jobs?' ,
386+ 'This will delete all scheduled, completed, and error jobs from your history. This action cannot be undone and will not delete recorded files.' ,
387+ async ( ) => {
388+ const res = await apiFetch ( '/api/dvr/jobs/all' , { method : 'DELETE' } ) ;
389+ if ( res && res . ok ) {
390+ showNotification ( 'All scheduled jobs have been cleared.' ) ;
391+ await loadScheduledJobs ( ) ;
392+ }
393+ }
394+ ) ;
395+ } ) ;
396+
397+ UIElements . clearCompletedDvrBtn . addEventListener ( 'click' , ( ) => {
398+ showConfirm (
399+ 'Clear All Recordings?' ,
400+ 'This will permanently delete all completed recording files and remove them from your history. This action cannot be undone.' ,
401+ async ( ) => {
402+ const res = await apiFetch ( '/api/dvr/recordings/all' , { method : 'DELETE' } ) ;
403+ if ( res && res . ok ) {
404+ showNotification ( 'All completed recordings have been deleted.' ) ;
405+ await loadCompletedRecordings ( ) ;
406+ }
407+ }
408+ ) ;
409+ } ) ;
375410}
376411
377412export function findDvrJobForProgram ( program ) {
0 commit comments