diff --git a/src/main/resources/web/assets/app.js b/src/main/resources/web/assets/app.js index a1338a9..d7e7aa5 100644 --- a/src/main/resources/web/assets/app.js +++ b/src/main/resources/web/assets/app.js @@ -900,11 +900,34 @@ function renderFavorites() { const search = el.favoritesSearch.value.trim().toLowerCase(); + const matchesText = (value) => String(value || "").toLowerCase().includes(search); const filtered = state.favorites.filter((item) => { const title = String(item?.title || "").toLowerCase(); const type = String(item?.mode || "").toLowerCase(); const url = String(item?.url || "").toLowerCase(); - return !search || title.includes(search) || type.includes(search) || url.includes(search); + if (!search || title.includes(search) || type.includes(search) || url.includes(search)) { + return true; + } + const mode = String(item?.mode || ""); + if (mode === "live_category") { + const categoryId = String(item?.id || ""); + const entry = state.favoriteLiveCategoryStreamsById[categoryId]; + const streams = Array.isArray(entry?.episodes) ? entry.episodes : []; + return streams.some((stream) => matchesText(stream?.name) || matchesText(stream?.stream_id)); + } + if (mode === "vod_category") { + const categoryId = String(item?.id || ""); + const entry = state.favoriteVodCategoryStreamsById[categoryId]; + const streams = Array.isArray(entry?.episodes) ? entry.episodes : []; + return streams.some((stream) => matchesText(stream?.name) || matchesText(stream?.stream_id)); + } + if (mode === "series_category") { + const categoryId = String(item?.id || ""); + const entry = state.favoriteSeriesCategoryItemsById[categoryId]; + const seriesItems = Array.isArray(entry?.episodes) ? entry.episodes : []; + return seriesItems.some((seriesItem) => matchesText(seriesItem?.name) || matchesText(seriesItem?.series_id)); + } + return false; }); if (filtered.length === 0) { @@ -1067,7 +1090,15 @@ wrap.className = "series-inline-episodes-wrap"; if (isLiveCategory) { const liveStreams = Array.isArray(episodesEntry.episodes) ? episodesEntry.episodes : []; - liveStreams.forEach((stream) => { + const visibleLiveStreams = search + ? liveStreams.filter((stream) => matchesText(stream?.name) || matchesText(stream?.stream_id)) + : liveStreams; + if (visibleLiveStreams.length === 0) { + episodesLi.innerHTML = `
No matching streams in this category.
`; + el.favoritesList.appendChild(episodesLi); + return; + } + visibleLiveStreams.forEach((stream) => { const streamFavorite = makeFavoriteLive(stream); const row = document.createElement("div"); row.className = "stream-item"; @@ -1103,7 +1134,15 @@ } if (isVodCategory) { const vodStreams = Array.isArray(episodesEntry.episodes) ? episodesEntry.episodes : []; - vodStreams.forEach((stream) => { + const visibleVodStreams = search + ? vodStreams.filter((stream) => matchesText(stream?.name) || matchesText(stream?.stream_id)) + : vodStreams; + if (visibleVodStreams.length === 0) { + episodesLi.innerHTML = `
No matching streams in this category.
`; + el.favoritesList.appendChild(episodesLi); + return; + } + visibleVodStreams.forEach((stream) => { const streamFavorite = makeFavoriteVod(stream); const row = document.createElement("div"); row.className = "stream-item"; @@ -1134,7 +1173,16 @@ } if (isSeriesCategory) { const seriesItems = Array.isArray(episodesEntry.episodes) ? episodesEntry.episodes : []; - seriesItems.forEach((seriesItem) => { + const visibleSeriesItems = search + ? seriesItems.filter((seriesItem) => matchesText(seriesItem?.name) + || matchesText(seriesItem?.series_id)) + : seriesItems; + if (visibleSeriesItems.length === 0) { + episodesLi.innerHTML = `
No matching streams in this category.
`; + el.favoritesList.appendChild(episodesLi); + return; + } + visibleSeriesItems.forEach((seriesItem) => { const seriesItemFavorite = makeFavoriteSeriesItem(seriesItem); const localSeriesId = String(seriesItem?.series_id || ""); const isLocalExpanded = Boolean(state.expandedFavoriteSeriesById[localSeriesId]);