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));