Feat: Fav channel in localstorage
This commit is contained in:
+29
-16
@@ -10,24 +10,35 @@ function makePlaceholder(name) {
|
||||
return el;
|
||||
}
|
||||
|
||||
function makeChannelCell(ch) {
|
||||
const cell = document.createElement('div');
|
||||
cell.className = 'channel-cell';
|
||||
if (ch.icon) {
|
||||
const img = document.createElement('img');
|
||||
img.className = 'channel-logo'; img.src = ch.icon;
|
||||
img.onerror = () => img.replaceWith(makePlaceholder(ch.name));
|
||||
cell.appendChild(img);
|
||||
} else { cell.appendChild(makePlaceholder(ch.name)); }
|
||||
const name = document.createElement('div');
|
||||
name.className = 'channel-name'; name.textContent = ch.name; name.title = ch.name;
|
||||
cell.appendChild(name);
|
||||
cell.appendChild(makeFavBtn(ch.id));
|
||||
cell.addEventListener('click', () => openPip(ch.name, getNowPlaying(ch.id)));
|
||||
return cell;
|
||||
}
|
||||
|
||||
function renderChannels() {
|
||||
const list = document.getElementById('channelsList');
|
||||
list.innerHTML = '';
|
||||
channels.forEach(ch => {
|
||||
const cell = document.createElement('div');
|
||||
cell.className = 'channel-cell';
|
||||
if (ch.icon) {
|
||||
const img = document.createElement('img');
|
||||
img.className = 'channel-logo'; img.src = ch.icon;
|
||||
img.onerror = () => img.replaceWith(makePlaceholder(ch.name));
|
||||
cell.appendChild(img);
|
||||
} else { cell.appendChild(makePlaceholder(ch.name)); }
|
||||
const name = document.createElement('div');
|
||||
name.className = 'channel-name'; name.textContent = ch.name; name.title = ch.name;
|
||||
cell.appendChild(name);
|
||||
cell.addEventListener('click', () => openPip(ch.name, getNowPlaying(ch.id)));
|
||||
list.appendChild(cell);
|
||||
});
|
||||
const { favs, rest } = sortedChannels(channels);
|
||||
|
||||
if (favs.length) {
|
||||
favs.forEach(ch => list.appendChild(makeChannelCell(ch)));
|
||||
const sep = document.createElement('div');
|
||||
sep.className = 'fav-separator';
|
||||
list.appendChild(sep);
|
||||
}
|
||||
rest.forEach(ch => list.appendChild(makeChannelCell(ch)));
|
||||
}
|
||||
|
||||
function renderRuler() {
|
||||
@@ -70,7 +81,9 @@ function renderPrograms() {
|
||||
|
||||
const now = new Date();
|
||||
|
||||
channels.forEach((ch, i) => {
|
||||
const { favs: _f, rest: _r } = sortedChannels(channels);
|
||||
const orderedChannels = [..._f, ..._r];
|
||||
orderedChannels.forEach((ch, i) => {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'program-row';
|
||||
row.style.cssText = `top:${i*ROW_H}px;position:absolute;left:0;right:0;`;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// ── FAVORITES ─────────────────────────────────────────────────────────────────
|
||||
let favorites = new Set(JSON.parse(localStorage.getItem('gridtv-favorites') || '[]'));
|
||||
|
||||
function saveFavorites() {
|
||||
localStorage.setItem('gridtv-favorites', JSON.stringify([...favorites]));
|
||||
}
|
||||
|
||||
function toggleFavorite(chId, btn) {
|
||||
if (favorites.has(chId)) {
|
||||
favorites.delete(chId);
|
||||
btn.classList.remove('is-fav');
|
||||
btn.title = L.fav_add;
|
||||
} else {
|
||||
favorites.add(chId);
|
||||
btn.classList.add('is-fav');
|
||||
btn.title = L.fav_remove;
|
||||
}
|
||||
saveFavorites();
|
||||
renderAll();
|
||||
}
|
||||
|
||||
function makeFavBtn(chId) {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'fav-btn' + (favorites.has(chId) ? ' is-fav' : '');
|
||||
btn.title = favorites.has(chId) ? L.fav_remove : L.fav_add;
|
||||
btn.textContent = '★';
|
||||
btn.addEventListener('click', e => { e.stopPropagation(); toggleFavorite(chId, btn); });
|
||||
return btn;
|
||||
}
|
||||
|
||||
function sortedChannels(list) {
|
||||
const favs = list.filter(ch => favorites.has(ch.id));
|
||||
const rest = list.filter(ch => !favorites.has(ch.id));
|
||||
return { favs, rest };
|
||||
}
|
||||
+3
-1
@@ -6,7 +6,9 @@ function renderMobile() {
|
||||
const winStart = new Date(now.getTime() - 30*60000);
|
||||
const winEnd = new Date(now.getTime() + 4*3600000);
|
||||
|
||||
channels.forEach(ch => {
|
||||
const { favs: _f, rest: _r } = sortedChannels(channels);
|
||||
const orderedChannels = [..._f, ..._r];
|
||||
orderedChannels.forEach(ch => {
|
||||
const progs = (programs[ch.id]||[]).filter(p => p.stop>winStart && p.start<winEnd);
|
||||
if (!progs.length) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user