Add program reminders and category filtering to the guide UI
Enhance health diagnostics with EPG quality and source metrics
This commit is contained in:
+34
-1
@@ -10,6 +10,7 @@ let channels = [];
|
||||
let programs = {};
|
||||
let m3uStreams = {}; // Normalized slug -> stream URL.
|
||||
let scrollListenerAdded = false; // Keeps the channel column vertically synced with the timeline.
|
||||
let availableCategories = [];
|
||||
|
||||
function pad(n) { return String(n).padStart(2,'0'); }
|
||||
|
||||
@@ -123,6 +124,27 @@ function formatCategories(categories) {
|
||||
return Array.isArray(categories) && categories.length ? categories.join(' · ') : '';
|
||||
}
|
||||
|
||||
function normalizeCategory(value) {
|
||||
return String(value || '').trim().toLowerCase();
|
||||
}
|
||||
|
||||
function collectAvailableCategories() {
|
||||
const seen = new Set();
|
||||
const list = [];
|
||||
Object.values(programs).forEach(items => {
|
||||
items.forEach(program => {
|
||||
(program.categories || []).forEach(category => {
|
||||
const label = String(category || '').trim();
|
||||
const key = normalizeCategory(label);
|
||||
if (!label || seen.has(key)) return;
|
||||
seen.add(key);
|
||||
list.push(label);
|
||||
});
|
||||
});
|
||||
});
|
||||
availableCategories = list.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }));
|
||||
}
|
||||
|
||||
function parseAirDate(value) {
|
||||
if (!value) return null;
|
||||
const match = String(value).trim().match(/^(\d{4})/);
|
||||
@@ -162,11 +184,22 @@ function parseAndRender(doc) {
|
||||
});
|
||||
Object.keys(programs).forEach(id => programs[id].sort((a,b) => a.start - b.start));
|
||||
|
||||
collectAvailableCategories();
|
||||
if (typeof refreshCategoryFilterOptions === 'function') refreshCategoryFilterOptions();
|
||||
renderAll();
|
||||
if (typeof refreshReminderSchedules === 'function') refreshReminderSchedules();
|
||||
startLiveUpdates();
|
||||
}
|
||||
|
||||
function renderAll() {
|
||||
function renderUnfiltered() {
|
||||
if (isMobile()) { renderMobile(); }
|
||||
else { renderGrid(); setTimeout(centerNow, 150); }
|
||||
}
|
||||
|
||||
function renderAll() {
|
||||
if (typeof applyFilters === 'function') {
|
||||
applyFilters();
|
||||
return;
|
||||
}
|
||||
renderUnfiltered();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user