fix: make partial search pagination lossless (Closes #807)
CI / lint (pull_request) Successful in 1m34s
CI / build-release (pull_request) Successful in 5s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-14 07:32:45 +00:00
1 parent e5f37a866c
commit 10f7cc832a
7 files changed
+239 -32

No files matched your search

+16 -3
View File
@@ -15,6 +15,15 @@
return current;
};
filterCommands.searchUrl = function searchUrl(query, page, scope, continuation) {
const streamPages = continuation ?
(continuation.issues ? '&issues_page=' + encodeURIComponent(continuation.issues) : '') +
(continuation.pulls ? '&pulls_page=' + encodeURIComponent(continuation.pulls) : '') : '';
return 'api/v1/search?q=' + encodeURIComponent(query) + '&limit=10&page=' + page +
'&kind=' + encodeURIComponent(scope.kind) + '&state=' + encodeURIComponent(scope.state) +
(scope.repository ? '&repository=' + encodeURIComponent(scope.repository) : '') + streamPages;
};
filterCommands.createGlobalSearchController = function createGlobalSearchController(options) {
const search = options.search;
const onState = options.onState;
@@ -31,12 +40,14 @@
return state;
}
async function requestPage(query, page, current, append) {
async function requestPage(query, page, current, append, continuation) {
const requestController = new AbortController();
activeController = requestController;
try {
const requestScope = { ...scope };
const result = await search(query, requestController.signal, page, requestScope);
const result = await search(
query, requestController.signal, page, requestScope, continuation
);
const partial = result.partial === true;
const incoming = result.items || result;
const combined = append ? state.items.concat(incoming) : incoming;
@@ -47,6 +58,8 @@
status: 'ready', query, items, partial,
more: !!result.has_more,
next: result.next_page,
continuation:result.continuation,
failedStreams:result.failed_streams || [],
scope:requestScope,
});
} catch (error) {
@@ -93,7 +106,7 @@
if (state.status !== 'ready' || !state.more || activeController) return Promise.resolve(state);
const current = generation;
const page = state.next;
return requestPage(state.query, page, current, true);
return requestPage(state.query, page, current, true, state.continuation);
},
};
};
+3 -4
View File
@@ -4293,10 +4293,8 @@
let commandSearchState = { status:'idle', query:'', items:[] };
let commandItems = [];
let commandSelection = -1;
async function searchGlobalWork(query, signal, page = 1, scope = {kind:'all', state:'all'}) {
const response = await fetch('api/v1/search?q=' + encodeURIComponent(query) + '&limit=10&page=' + page +
'&kind=' + encodeURIComponent(scope.kind) + '&state=' + encodeURIComponent(scope.state) +
(scope.repository ? '&repository=' + encodeURIComponent(scope.repository) : ''), {
async function searchGlobalWork(query, signal, page = 1, scope = {kind:'all', state:'all'}, continuation) {
const response = await fetch(filterCommands.searchUrl(query, page, scope, continuation), {
headers: { Accept:'application/json' },
signal,
});
@@ -4531,6 +4529,7 @@
else if (String(filter || '').trim().length >= 2 && !remote.length) html += '<div class="cmd-status">No matching issues or pull requests.</div>';
el.innerHTML = html;
loadMore.hidden = !commandSearchState.more;
loadMore.textContent = commandSearchState.partial ? 'Retry missing results' : 'More results';
el.querySelectorAll('.cmd-item').forEach((item) => {
item.addEventListener('click', () => runCommandItem(commandItems[Number(item.dataset.idx)]));
});