feat(ui): surface live language filters and built-in EPG sources (#23)
Add language filter controls for projected live channels, preserve backend language views in the browser, and separate built-in EPG sources from custom sources. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -8,6 +8,7 @@ class SourceManager {
|
||||
this.xtreamList = document.getElementById('xtream-list');
|
||||
this.m3uList = document.getElementById('m3u-list');
|
||||
this.epgList = document.getElementById('epg-list');
|
||||
this.builtinEpgList = document.getElementById('builtin-epg-list');
|
||||
|
||||
// Content browser state
|
||||
this.contentType = 'channels'; // 'channels' or 'movies'
|
||||
@ -114,7 +115,9 @@ class SourceManager {
|
||||
|
||||
this.renderSourceList(this.xtreamList, sources.filter(s => s.type === 'xtream'), 'xtream');
|
||||
this.renderSourceList(this.m3uList, sources.filter(s => s.type === 'm3u'), 'm3u');
|
||||
this.renderSourceList(this.epgList, sources.filter(s => s.type === 'epg'), 'epg');
|
||||
const epgSources = sources.filter(s => s.type === 'epg');
|
||||
this.renderBuiltinEpgSources(epgSources.filter(source => source.builtinKey));
|
||||
this.renderSourceList(this.epgList, epgSources.filter(source => !source.builtinKey), 'epg');
|
||||
} catch (err) {
|
||||
console.error('Error loading sources:', err);
|
||||
}
|
||||
@ -162,6 +165,33 @@ class SourceManager {
|
||||
});
|
||||
}
|
||||
|
||||
renderBuiltinEpgSources(sources) {
|
||||
if (!this.builtinEpgList) return;
|
||||
if (!sources.length) {
|
||||
this.builtinEpgList.innerHTML = '<p class="hint">No built-in EPG sources available</p>';
|
||||
return;
|
||||
}
|
||||
this.builtinEpgList.innerHTML = sources.map(source => {
|
||||
const coverage = [source.language?.toUpperCase(), source.country].filter(Boolean).join(' · ');
|
||||
return `<div class="source-item builtin-source ${source.enabled ? '' : 'disabled'}" data-id="${source.id}">
|
||||
<span class="source-icon">${Icons.series}</span>
|
||||
<div class="source-info">
|
||||
<div class="source-name">${source.name} <span class="source-badge">Built-in</span></div>
|
||||
<div class="source-meta">Free EPG data${coverage ? ` · ${coverage}` : ''}</div>
|
||||
</div>
|
||||
<div class="source-actions">
|
||||
<button class="btn btn-sm btn-secondary" data-action="refresh" title="Refresh Data" aria-label="Refresh ${source.name}">${Icons.refresh}</button>
|
||||
<button class="btn btn-sm btn-secondary" data-action="toggle" aria-pressed="${source.enabled}" title="${source.enabled ? 'Disable' : 'Enable'}">${source.enabled ? 'Disable' : 'Enable'}</button>
|
||||
</div>
|
||||
</div>`;
|
||||
}).join('');
|
||||
this.builtinEpgList.querySelectorAll('.source-item').forEach(item => {
|
||||
const id = Number(item.dataset.id);
|
||||
item.querySelector('[data-action="refresh"]')?.addEventListener('click', () => this.refreshSource(id, 'epg'));
|
||||
item.querySelector('[data-action="toggle"]')?.addEventListener('click', () => this.toggleSource(id));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show add source modal
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user