web/storage: more stringent opfs check

This commit is contained in:
jj
2025-05-29 19:31:01 +00:00
parent 1c304457e2
commit d6e2f3cb12
4 changed files with 28 additions and 9 deletions

View File

@ -2,12 +2,12 @@ import type { AbstractStorage } from "./storage";
import { MemoryStorage } from "./memory"; import { MemoryStorage } from "./memory";
import { OPFSStorage } from "./opfs"; import { OPFSStorage } from "./opfs";
export function init(expectedSize?: number): Promise<AbstractStorage> { export async function init(expectedSize?: number): Promise<AbstractStorage> {
if (OPFSStorage.isAvailable()) { if (await OPFSStorage.isAvailable()) {
return OPFSStorage.init(); return OPFSStorage.init();
} }
if (MemoryStorage.isAvailable()) { if (await MemoryStorage.isAvailable()) {
return MemoryStorage.init(expectedSize || 0); return MemoryStorage.init(expectedSize || 0);
} }

View File

@ -85,7 +85,7 @@ export class MemoryStorage extends AbstractStorage {
this.#chunks = []; this.#chunks = [];
} }
static isAvailable() { static async isAvailable() {
return true; return true;
} }
} }

View File

@ -7,6 +7,8 @@ export class OPFSStorage extends AbstractStorage {
#handle; #handle;
#io; #io;
static #isAvailable?: boolean;
constructor(root: FileSystemDirectoryHandle, handle: FileSystemFileHandle, reader: FileSystemSyncAccessHandle) { constructor(root: FileSystemDirectoryHandle, handle: FileSystemFileHandle, reader: FileSystemSyncAccessHandle) {
super(); super();
this.#root = root; this.#root = root;
@ -38,16 +40,33 @@ export class OPFSStorage extends AbstractStorage {
await this.#root.removeEntry(this.#handle.name); await this.#root.removeEntry(this.#handle.name);
} }
static isAvailable() { static async #computeIsAvailable() {
if (typeof navigator === 'undefined') if (typeof navigator === 'undefined')
return false; return false;
return 'storage' in navigator && 'getDirectory' in navigator.storage; if ('storage' in navigator && 'getDirectory' in navigator.storage) {
try {
await navigator.storage.getDirectory();
return true;
} catch {
return false;
}
}
return false;
}
static async isAvailable() {
if (this.#isAvailable === undefined) {
this.#isAvailable = await this.#computeIsAvailable();
}
return this.#isAvailable;
} }
} }
export const removeFromFileStorage = async (filename: string) => { export const removeFromFileStorage = async (filename: string) => {
if (OPFSStorage.isAvailable()) { if (await OPFSStorage.isAvailable()) {
const root = await navigator.storage.getDirectory(); const root = await navigator.storage.getDirectory();
try { try {
@ -60,7 +79,7 @@ export const removeFromFileStorage = async (filename: string) => {
} }
export const clearFileStorage = async () => { export const clearFileStorage = async () => {
if (OPFSStorage.isAvailable()) { if (await OPFSStorage.isAvailable()) {
const root = await navigator.storage.getDirectory(); const root = await navigator.storage.getDirectory();
try { try {
await root.removeEntry(COBALT_PROCESSING_DIR, { recursive: true }); await root.removeEntry(COBALT_PROCESSING_DIR, { recursive: true });

View File

@ -3,7 +3,7 @@ export abstract class AbstractStorage {
throw "init() call on abstract implementation"; throw "init() call on abstract implementation";
} }
static isAvailable(): boolean { static async isAvailable(): Promise<boolean> {
return false; return false;
} }