add offline support
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
globalThis.Wegwichtel ??= {};
|
||||
(function (ns) {
|
||||
'use strict';
|
||||
const LOCAL_REFERENCE = 5 * 1024 * 1024;
|
||||
let initialized = false;
|
||||
let lastError = '';
|
||||
let refreshTask = null;
|
||||
|
||||
function format(bytes) {
|
||||
return `${(bytes / 1024 / 1024).toLocaleString('de-DE', { maximumFractionDigits: 1 })} MiB`;
|
||||
}
|
||||
|
||||
function localBytes() {
|
||||
const storage = globalThis.localStorage;
|
||||
if (!storage) return null;
|
||||
let bytes = 0;
|
||||
for (let index = 0; index < storage.length; index += 1) {
|
||||
const key = storage.key(index);
|
||||
if (key != null) bytes += 2 * (key.length + (storage.getItem(key) || '').length);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function show(selector, usage, quota, text) {
|
||||
for (const panel of document.querySelectorAll('[data-storage-usage]')) {
|
||||
const meter = panel.querySelector(`[data-storage-${selector}-meter]`);
|
||||
const label = panel.querySelector(`[data-storage-${selector}-text]`);
|
||||
if (meter) {
|
||||
meter.hidden = !quota;
|
||||
if (quota) { meter.max = quota; meter.value = Math.min(usage, quota); }
|
||||
}
|
||||
if (label) label.textContent = text;
|
||||
}
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
if (refreshTask) return refreshTask;
|
||||
refreshTask = (async () => {
|
||||
let estimate = null;
|
||||
try { estimate = await navigator.storage?.estimate?.(); } catch { /* Display unknown rather than a guessed quota. */ }
|
||||
const usage = estimate?.usage;
|
||||
const quota = estimate?.quota;
|
||||
const known = Number.isFinite(usage) && Number.isFinite(quota) && quota > 0;
|
||||
show('site', usage, known ? quota : null, known
|
||||
? `Website-Speicher: ${format(usage)} von ${format(quota)} belegt (${Math.round(usage / quota * 100)} %). Etwa ${format(Math.max(0, quota - usage))} verfügbar.${usage / quota >= .9 ? ' Speicher fast voll.' : ''}`
|
||||
: 'Der Browser meldet keine Speicherkapazität.');
|
||||
let local = null;
|
||||
try { local = localBytes(); } catch { /* Storage can be blocked by browser settings. */ }
|
||||
show('local', local, local == null ? null : LOCAL_REFERENCE, local == null
|
||||
? 'Local Storage ist nicht verfügbar.'
|
||||
: `Local Storage: ungefähr ${format(local)} belegt. Balken bezogen auf einen Richtwert von 5 MiB; die tatsächliche Grenze hängt vom Browser ab.${local >= LOCAL_REFERENCE * .9 ? ' Richtwert fast erreicht: Große Bilder können das Speichern verhindern.' : ''}`);
|
||||
for (const panel of document.querySelectorAll('[data-storage-usage]')) {
|
||||
const warning = panel.querySelector('[data-storage-warning]');
|
||||
if (warning) { warning.hidden = !lastError; warning.textContent = lastError; }
|
||||
}
|
||||
})().finally(() => { refreshTask = null; });
|
||||
return refreshTask;
|
||||
}
|
||||
|
||||
function reportError(error) {
|
||||
let current = error;
|
||||
while (current) {
|
||||
if (current.name === 'QuotaExceededError') {
|
||||
lastError = 'Speicher voll: Entferne nicht mehr benötigte Offline-Strecken oder lokale Entwürfe. Eine Browser-Quote oder die separate Local-Storage-Grenze kann erreicht sein.';
|
||||
break;
|
||||
}
|
||||
current = current.cause;
|
||||
}
|
||||
void refresh();
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
if (initialized) return;
|
||||
initialized = true;
|
||||
document.addEventListener('wegwichtel:local-routes-changed', () => { lastError = ''; void refresh(); });
|
||||
document.addEventListener('wegwichtel:storage-error', event => reportError(event.detail));
|
||||
document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') void refresh(); });
|
||||
globalThis.addEventListener?.('storage', () => { void refresh(); });
|
||||
globalThis.addEventListener?.('focus', () => { void refresh(); });
|
||||
for (const button of document.querySelectorAll('[data-storage-refresh]')) button.addEventListener('click', () => { void refresh(); });
|
||||
void refresh();
|
||||
}
|
||||
|
||||
ns.StorageUsage = Object.freeze({ initialize, refresh, reportError });
|
||||
}(globalThis.Wegwichtel));
|
||||
Reference in New Issue
Block a user