fix(offline): surface degraded/missing preloads, join re-entrant runs, cache manifest to IDB
- loadManifest() goes through DataCache.fetchWithFallback: the file list is written to IDB and survives SW-cache eviction; a run with the reduced fallback set is flagged and shown as degraded (new i18n en/ru/cu). - 404 answers are counted as 'missing' (deployment drift) with a preload-missing diag entry, instead of silently reporting Done. - preload() is re-entrancy safe: concurrent calls join the in-flight run. - versions.json is loaded once per session (was fetched per translation). - Write-through failures in fetchWithFallback()/fetch() log idb-write-fail. - preload-manifest.json SW route is NetworkFirst (fresh coverage online). - Manifest now also covers the shared/lives + shared/commands fallbacks.
This commit is contained in:
1 parent
1201e16d5e
commit
8c442bf7b6
7 files changed
+184
-55
No files matched your search
+18
-21
@@ -3,11 +3,26 @@
|
||||
*/
|
||||
|
||||
import { getTranslations, type LanguageCode } from '../core/i18n';
|
||||
import { OfflineManager } from '../core/offline-manager';
|
||||
import { OfflineManager, type PreloadProgress } from '../core/offline-manager';
|
||||
import { DataCache } from '../core/data-cache';
|
||||
import { diagTail } from '../core/diag-log';
|
||||
import { isPwaInstalled } from '../core/pwa-install';
|
||||
|
||||
/** Human message for a finished preload run (shared by manual + auto preload). */
|
||||
function preloadResultText(
|
||||
prog: PreloadProgress,
|
||||
s: { offlineAborted: string; offlineDone: string; offlineFailed: string; offlineDegraded: string; offlineMissing: string },
|
||||
): string {
|
||||
if (prog.aborted) return s.offlineAborted;
|
||||
if (prog.manifestMissing) return s.offlineDegraded;
|
||||
if (prog.failed > 0) {
|
||||
const failList = prog.failedFiles?.length ? `: ${prog.failedFiles.join(', ')}` : '';
|
||||
return `${s.offlineDone} ${prog.failed} ${s.offlineFailed}${failList}`;
|
||||
}
|
||||
if ((prog.missing ?? 0) > 0) return s.offlineMissing.replace('{0}', String(prog.missing));
|
||||
return s.offlineDone;
|
||||
}
|
||||
|
||||
const LANGUAGES = [
|
||||
{ code: 'en', name: 'English', local: 'English' },
|
||||
{ code: 'ru', name: 'Russian', local: 'Русский' },
|
||||
@@ -563,16 +578,7 @@ export class SettingsView {
|
||||
bibleTranslations: bibleTrans,
|
||||
}).then((prog) => {
|
||||
if (progressBar) progressBar.style.width = '100%';
|
||||
if (progressText) {
|
||||
if (prog.aborted) {
|
||||
progressText.textContent = t.settings.offlineAborted;
|
||||
} else if (prog.failed > 0) {
|
||||
const failList = prog.failedFiles?.length ? `: ${prog.failedFiles.join(', ')}` : '';
|
||||
progressText.textContent = `${t.settings.offlineDone} ${prog.failed} ${t.settings.offlineFailed}${failList}`;
|
||||
} else {
|
||||
progressText.textContent = t.settings.offlineDone;
|
||||
}
|
||||
}
|
||||
if (progressText) progressText.textContent = preloadResultText(prog, t.settings);
|
||||
const diagEl = document.getElementById('diag-log');
|
||||
if (diagEl) diagEl.textContent = diagTail();
|
||||
OfflineManager.getStats().then(stats => {
|
||||
@@ -696,16 +702,7 @@ export class SettingsView {
|
||||
bibleTranslations: 'all',
|
||||
}).then((prog) => {
|
||||
if (progressBar) progressBar.style.width = '100%';
|
||||
if (progressText) {
|
||||
if (prog.aborted) {
|
||||
progressText.textContent = t.settings.offlineAborted;
|
||||
} else if (prog.failed > 0) {
|
||||
const failList = prog.failedFiles?.length ? `: ${prog.failedFiles.join(', ')}` : '';
|
||||
progressText.textContent = `${t.settings.offlineDone} ${prog.failed} ${t.settings.offlineFailed}${failList}`;
|
||||
} else {
|
||||
progressText.textContent = t.settings.offlineDone;
|
||||
}
|
||||
}
|
||||
if (progressText) progressText.textContent = preloadResultText(prog, t.settings);
|
||||
const diagEl = document.getElementById('diag-log');
|
||||
if (diagEl) diagEl.textContent = diagTail();
|
||||
OfflineManager.getStats().then(stats => {
|
||||
|
||||
Reference in new issue
Block a user