56 lines
2.0 KiB
TypeScript
56 lines
2.0 KiB
TypeScript
/**
|
|||
|
|
* [Gitea #120] What this device stores for Lotus, from the APIs that are cheap
|
||
|
|
* to ask. `estimate()` is the total the browser accounts for; Chromium adds a
|
||
|
|
* per-bucket breakdown (`usageDetails`), Firefox/Safari don't. Media files are
|
||
|
|
* not in here at all: they live in the browser's own HTTP cache, which manages
|
||
|
|
* and evicts them itself.
|
||
|
|
*/
|
||
|
|
export type StorageUsage = {
|
||
|
|
usage: number;
|
||
|
|
quota: number;
|
||
|
|
/** Chromium only: IndexedDB (sync store, crypto store, search index) bytes. */
|
||
|
|
indexedDB?: number;
|
||
|
|
/** Chromium only: Cache Storage (offline app shell) bytes. */
|
||
|
|
caches?: number;
|
||
|
|
/** Whether the browser granted persistent storage (won't evict under pressure). */
|
||
|
|
persisted: boolean | undefined;
|
||
|
|
};
|
||
|
|
|
||
|
|
type EstimateWithDetails = StorageEstimate & {
|
||
|
|
usageDetails?: { indexedDB?: number; caches?: number; serviceWorkerRegistrations?: number };
|
||
|
|
};
|
||
|
|
|
||
|
|
export const storageUsageSupported = (): boolean =>
|
||
|
|
typeof navigator !== 'undefined' && !!navigator.storage && !!navigator.storage.estimate;
|
||
|
|
|
||
|
|
export async function readStorageUsage(): Promise<StorageUsage | undefined> {
|
||
|
|
if (!storageUsageSupported()) return undefined;
|
||
|
|
const est = (await navigator.storage.estimate()) as EstimateWithDetails;
|
||
|
|
let persisted: boolean | undefined;
|
||
|
|
try {
|
||
|
|
persisted = navigator.storage.persisted ? await navigator.storage.persisted() : undefined;
|
||
|
|
} catch {
|
||
|
|
persisted = undefined;
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
usage: est.usage ?? 0,
|
||
|
|
quota: est.quota ?? 0,
|
||
|
|
indexedDB: est.usageDetails?.indexedDB,
|
||
|
|
caches: est.usageDetails?.caches,
|
||
|
|
persisted,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Ask the browser to keep this origin's storage; returns the new state. */
|
||
|
|
export async function requestPersistentStorage(): Promise<boolean | undefined> {
|
||
|
|
if (!navigator.storage?.persist) return undefined;
|
||
|
|
try {
|
||
|
|
return await navigator.storage.persist();
|
||
|
|
} catch {
|
||
|
|
return undefined;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export const percentOf = (usage: number, quota: number): number =>
|
||
|
|
quota > 0 ? Math.min(100, Math.round((usage / quota) * 100)) : 0;
|