fix(live): keep channel search responsive (#25)

Filter projected live channels locally in the browser and apply server-side search and language filters before costly enrichment work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
blomios
2026-10-06 13:08:16 +02:00
parent 5baf8d5a33
commit 45d1fe29d3
7 changed files with 210 additions and 48 deletions

View File

@ -3,6 +3,26 @@
if (typeof module === 'object' && module.exports) module.exports = service;
if (root) root.LiveChannelProjection = service;
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
function normalizeSearch(value) {
return String(value || '')
.normalize('NFKD').replace(/[\u0300-\u036f]/g, '')
.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim()
.split(/\s+/).filter(Boolean)
.map(token => token.length > 3 && token.endsWith('s') ? token.slice(0, -1) : token);
}
function matchesSearch(channel, query) {
const wanted = normalizeSearch(query);
if (!wanted.length) return true;
const corpus = normalizeSearch([
channel.displayName, channel.standardName, channel.fingerprint,
...(channel.variants || []).flatMap(variant => [
variant.name, variant.tvgId, variant.categoryName, variant.groupTitle
])
].filter(Boolean).join(' '));
return wanted.every(token => corpus.some(candidate => candidate.includes(token)));
}
function mapResponse(response, sources = []) {
if (!response || !Array.isArray(response.channels)) {
throw new Error('Invalid live channel projection response');
@ -89,5 +109,5 @@
return response.channels.length > 0 || !expectedChannelCount;
}
return { canUse, mapResponse };
return { canUse, mapResponse, matchesSearch, normalizeSearch };
});