diff options
-rw-r--r-- | src/static/js/client.js | 108 | ||||
-rw-r--r-- | src/static/js/search-worker.js | 39 |
2 files changed, 141 insertions, 6 deletions
diff --git a/src/static/js/client.js b/src/static/js/client.js index dab1ea37..769a4212 100644 --- a/src/static/js/client.js +++ b/src/static/js/client.js @@ -3447,6 +3447,17 @@ const wikiSearchInfo = initInfo('wikiSearchInfo', { workerActionCounter: 0, workerActionPromiseResolverMap: new Map(), + + downloads: Object.create(null), + }, + + event: { + whenDownloadBegins: [], + whenDownloadsBegin: [], + + whenDownloadProgresses: [], + + whenDownloadEnds: [], }, }); @@ -3481,6 +3492,18 @@ function handleSearchWorkerMessage(message) { handleSearchWorkerResultMessage(message); break; + case 'download-begun': + handleSearchWorkerDownloadBegunMessage(message); + break; + + case 'download-progress': + handleSearchWorkerDownloadProgressMessage(message); + break; + + case 'download-complete': + handleSearchWorkerDownloadCompleteMessage(message); + break; + default: console.warn(`Unknown message kind "${message.data.kind}" <- from search worker`); break; @@ -3545,6 +3568,70 @@ function handleSearchWorkerResultMessage(message) { state.workerActionPromiseResolverMap.delete(id); } +function handleSearchWorkerDownloadBegunMessage(message) { + const {event} = wikiSearchInfo; + const {context: contextKey, keys} = message.data; + + const context = getSearchWorkerDownloadContext(contextKey, true); + + for (const key of keys) { + context[key] = 0.00; + + dispatchInternalEvent(event, 'whenDownloadBegins', { + context: contextKey, + key, + }); + } + + dispatchInternalEvent(event, 'whenDownloadsBegin', { + context: contextKey, + keys, + }); +} + +function handleSearchWorkerDownloadProgressMessage(message) { + const {event} = wikiSearchInfo; + const {context: contextKey, key, progress} = message.data; + + const context = getSearchWorkerDownloadContext(contextKey); + + context[key] = progress; + + dispatchInternalEvent(event, 'whenDownloadProgresses', { + context: contextKey, + key, + progress, + }); +} + +function handleSearchWorkerDownloadCompleteMessage(message) { + const {event} = wikiSearchInfo; + const {context: contextKey, key} = message.data; + + const context = getSearchWorkerDownloadContext(contextKey); + + context[key] = 1.00; + + dispatchInternalEvent(event, 'whenDownloadEnds', { + context: contextKey, + key, + }); +} + +function getSearchWorkerDownloadContext(context, initialize = false) { + const {state} = wikiSearchInfo; + + if (context in state.downloads) { + return state.downloads[context]; + } + + if (!initialize) { + return null; + } + + return state.downloads[context] = Object.create(null); +} + async function postSearchWorkerAction(action, options) { const {state} = wikiSearchInfo; @@ -3643,6 +3730,16 @@ function getSidebarSearchReferences() { findString('group-result-kind'); } +function addSidebarSearchInternalListeners() { + const info = sidebarSearchInfo; + + if (!info.searchBox) return; + + wikiSearchInfo.event.whenDownloadsBegin.push(updateSidebarSearchStatus); + wikiSearchInfo.event.whenDownloadProgresses.push(updateSidebarSearchStatus); + wikiSearchInfo.event.whenDownloadEnds.push(updateSidebarSearchStatus); +} + function mutateSidebarSearchContent() { const info = sidebarSearchInfo; @@ -3787,6 +3884,16 @@ function clearSidebarSearch() { hideSidebarSearchResults(); } +function updateSidebarSearchStatus() { + const info = sidebarSearchInfo; + const {state} = info; + + const searchIndexDownloads = + getSearchWorkerDownloadContext('search-indexes'); + + console.log('Display:', searchIndexDownloads); +} + function showSidebarSearchResults(results) { const info = sidebarSearchInfo; @@ -4002,6 +4109,7 @@ function hideSidebarSearchResults() { } clientSteps.getPageReferences.push(getSidebarSearchReferences); +clientSteps.addInternalListeners.push(addSidebarSearchInternalListeners); clientSteps.mutatePageContent.push(mutateSidebarSearchContent); clientSteps.addPageListeners.push(addSidebarSearchListeners); clientSteps.initializeState.push(initializeSidebarSearchState); diff --git a/src/static/js/search-worker.js b/src/static/js/search-worker.js index c2bdcaee..9a7827da 100644 --- a/src/static/js/search-worker.js +++ b/src/static/js/search-worker.js @@ -14,6 +14,7 @@ import { } from '../shared-util/sugar.js'; import {loadDependency} from './module-import-shims.js'; +import {fetchWithProgress} from './xhr-util.js'; // Will be loaded from dependencies. let decompress; @@ -24,7 +25,7 @@ let idb; let status = null; let indexes = null; -globalThis.onmessage = handleWindowMessage; +onmessage = handleWindowMessage; postStatus('alive'); Promise.all([ @@ -158,6 +159,8 @@ async function main() { const [indexData, idbIndexData] = await background; + delete idbIndexData.generic; + const keysNeedingFetch = (idbIndexData ? Object.keys(indexData) @@ -170,10 +173,34 @@ async function main() { Object.keys(indexData) .filter(key => !keysNeedingFetch.includes(key)) + if (!empty(keysNeedingFetch)) { + postMessage({ + kind: 'download-begun', + context: 'search-indexes', + keys: keysNeedingFetch, + }); + } + const fetchPromises = - keysNeedingFetch - .map(key => rebase(key + '.json.msgpack')) - .map(url => fetch(url)); + keysNeedingFetch.map(key => + fetchWithProgress( + rebase(key + '.json.msgpack'), + progress => { + postMessage({ + kind: 'download-progress', + context: 'search-indexes', + progress: progress / 1.00, + key, + }); + }).then(response => { + postMessage({ + kind: 'download-complete', + context: 'search-indexes', + key, + }); + + return response; + })); const fetchBlobPromises = fetchPromises @@ -316,14 +343,14 @@ async function handleWindowActionMessage(message) { function postStatus(newStatus) { status = newStatus; - globalThis.postMessage({ + postMessage({ kind: 'status', status: newStatus, }); } function postActionResult(id, status, value) { - globalThis.postMessage({ + postMessage({ kind: 'result', id, status, |