From 15098ad6ed3f9051705bba2ce42e0b8346a92f6b Mon Sep 17 00:00:00 2001 From: Trevor Mears Date: Sun, 28 Dec 2025 17:52:40 -0800 Subject: [PATCH] Fixed hidden groups consuming batch slots --- public/index.html | 11 +++++++++++ public/js/components/ChannelList.js | 19 ++++++++++++++++--- public/js/pages/Settings.js | 13 +++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/public/index.html b/public/index.html index a7df279..fad8a46 100644 --- a/public/index.html +++ b/public/index.html @@ -309,6 +309,17 @@ directly. +
+
+ Stream Output Format + Container format for Xtream streams. Try TS if you experience buffering + issues. +
+ +
diff --git a/public/js/components/ChannelList.js b/public/js/components/ChannelList.js index 063ee7e..143af70 100644 --- a/public/js/components/ChannelList.js +++ b/public/js/components/ChannelList.js @@ -216,13 +216,25 @@ class ChannelList { groupedChannels['Favorites'] = favoritedChannels; } - // 4. Sort Groups - this.sortedGroups = Object.keys(groupedChannels).sort((a, b) => { + // 4. Sort Groups and filter to only those with visible channels + const allGroups = Object.keys(groupedChannels).sort((a, b) => { if (a === 'Favorites') return -1; if (b === 'Favorites') return 1; return a.localeCompare(b); }); + // Pre-filter to only include groups with visible channels (so hidden groups don't consume batch slots) + this.sortedGroups = allGroups.filter(groupName => { + if (groupName === 'Favorites') return true; + const channels = groupedChannels[groupName]; + // Check if any channel in this group is visible + return channels.some(channel => { + const rawChannelId = channel.streamId || channel.id; + const isHidden = this.isHidden('channel', channel.sourceId, rawChannelId); + return !isHidden || showHidden; + }); + }); + this.groupedChannels = groupedChannels; this.showHidden = showHidden; @@ -819,7 +831,8 @@ class ChannelList { // Get stream URL let streamUrl; if (channel.sourceType === 'xtream') { - const result = await API.proxy.xtream.getStreamUrl(channel.sourceId, channel.streamId, 'live'); + const streamFormat = localStorage.getItem('nodecast_tv_stream_format') || 'm3u8'; + const result = await API.proxy.xtream.getStreamUrl(channel.sourceId, channel.streamId, 'live', streamFormat); streamUrl = result.url; } else { streamUrl = channel.url; diff --git a/public/js/pages/Settings.js b/public/js/pages/Settings.js index 2ced51d..18dc27b 100644 --- a/public/js/pages/Settings.js +++ b/public/js/pages/Settings.js @@ -97,6 +97,19 @@ class SettingsPage { localStorage.setItem('nodecast_tv_epg_refresh_interval', epgRefreshSelect.value); }); } + + // Stream output format + const streamFormatSelect = document.getElementById('setting-stream-format'); + if (streamFormatSelect) { + // Load saved value + const savedFormat = localStorage.getItem('nodecast_tv_stream_format') || 'm3u8'; + streamFormatSelect.value = savedFormat; + + // Save on change + streamFormatSelect.addEventListener('change', () => { + localStorage.setItem('nodecast_tv_stream_format', streamFormatSelect.value); + }); + } } switchTab(tabName) {