Search: server-known videos first with YouTube results appended as they arrive; On server badge on cards the server holds a copy of
This commit is contained in:
@@ -8014,15 +8014,24 @@ function wireUI() {
|
||||
scrollListIntoViewPortrait();
|
||||
const metaBtn = $('searchUpdateBtn');
|
||||
if (metaBtn) { metaBtn.disabled = true; metaBtn.textContent = 'Updating…'; }
|
||||
let networkDone = false, paintedLocal = false;
|
||||
let networkDone = false, paintedLocal = false, localHits = [];
|
||||
// The server's own matches stay at the top; YouTube's answer is appended
|
||||
// below them (no duplicates), so the list grows instead of being swapped.
|
||||
const merged = (yt) => {
|
||||
if (!localHits.length) return yt;
|
||||
const seen = new Set(localHits.map((v) => v.id));
|
||||
return [...localHits, ...yt.filter((v) => !seen.has(v.id))];
|
||||
};
|
||||
if (!instant && !refresh) {
|
||||
// Known videos from the server's metadata store, painted until YouTube answers.
|
||||
// Known videos from the server's metadata store, shown while YouTube searches.
|
||||
API.searchLocal(q).then((lr) => {
|
||||
if (networkDone || mySeq !== searchSeq || !lr || !lr.ok || !(lr.results || []).length) return;
|
||||
paintedLocal = true;
|
||||
localHits = lr.results;
|
||||
searchResults = lr.results;
|
||||
searchAttempted = true;
|
||||
renderList();
|
||||
if (els.status) { els.status.classList.remove('hidden'); els.status.textContent = 'Searching YouTube for more…'; }
|
||||
}).catch(() => {});
|
||||
}
|
||||
try {
|
||||
@@ -8030,7 +8039,8 @@ function wireUI() {
|
||||
networkDone = true;
|
||||
if (mySeq !== searchSeq) return; // superseded by a newer search
|
||||
if (!res || !res.ok) throw new Error(res?.error || 'Search failed');
|
||||
const results = res.results || [];
|
||||
const results = merged(res.results || []);
|
||||
if (els.status && paintedLocal) els.status.classList.add('hidden');
|
||||
searchResults = results;
|
||||
searchAttempted = true;
|
||||
renderList();
|
||||
@@ -8047,17 +8057,18 @@ function wireUI() {
|
||||
if (mySeq !== searchSeq || view.type !== 'search') return;
|
||||
try {
|
||||
const more = await API.search(q);
|
||||
if (mySeq !== searchSeq || !more?.ok || (more.results || []).length <= results.length) return;
|
||||
searchResults = more.results;
|
||||
const full = merged(more?.results || []);
|
||||
if (mySeq !== searchSeq || !more?.ok || full.length <= results.length) return;
|
||||
searchResults = full;
|
||||
renderList();
|
||||
RecentSearches.cacheResults(q, more.results, Date.now());
|
||||
RecentSearches.cacheResults(q, full, Date.now());
|
||||
showSearchMeta(q, Date.now());
|
||||
} catch { /* keep the first page */ }
|
||||
}, 10000);
|
||||
} catch (err) {
|
||||
networkDone = true;
|
||||
if (mySeq !== searchSeq) return;
|
||||
if (paintedLocal) return; // keep the server's known videos
|
||||
if (paintedLocal) { if (els.status) els.status.classList.add('hidden'); toast('YouTube search failed — showing videos this server knows'); return; } // keep the server's known videos
|
||||
if (instant) { showSearchMeta(q, instant.ts); if (refresh) toast('Could not update: ' + err.message); return; } // keep the saved copy
|
||||
els.cards.innerHTML = '';
|
||||
els.status.classList.remove('hidden');
|
||||
|
||||
Reference in New Issue
Block a user