A music player that connects to your cloud/distributed storage. diffuse.sh
Something went wrong. Try again.
2.8 kB · 131 lines
JavaScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132import * as IDB from "idb-keyval";
import { ostiary, rpc } from "~/common/worker.js";import { CACHE_KEY_PREFIX, SCHEME } from "./constants.js";
/** * @import { InputActions as Actions } from "@specs/components/input/types.d.ts" * @import { Track } from "~/definitions/types.d.ts" */
////////////////////////////////////////////// STATE////////////////////////////////////////////
/** @type {Map<string, string>} */const blobUrls = new Map();
////////////////////////////////////////////// ACTIONS////////////////////////////////////////////
/** * @type {Actions['artwork']} */export async function artwork(_uri) { return null;}
/** * @type {Actions['consult']} */export async function consult(uriOrScheme) { if (!uriOrScheme.includes("://")) { return { supported: true, consult: "undetermined" }; }
const cached = await IDB.get(CACHE_KEY_PREFIX + uriOrScheme); return { supported: true, consult: cached !== undefined ? "yes" : "no" };}
/** * @type {Actions['detach']} */export async function detach({ fileUriOrScheme, tracks }) { if (!fileUriOrScheme.includes("://")) { if (fileUriOrScheme === SCHEME) { await removeBlobs(tracks.map((t) => t.uri)); return []; } return tracks; }
const remaining = tracks.filter((t) => t.uri !== fileUriOrScheme); await removeBlobs([fileUriOrScheme]); return remaining;}
/** * @type {Actions['groupConsult']} */export async function groupConsult(uris) { const cached = await Promise.all( uris.map((uri) => IDB.get(CACHE_KEY_PREFIX + uri)), );
return { [SCHEME]: { available: "yes", scheme: SCHEME, uris: uris.filter((_, i) => cached[i] !== undefined), }, };}
/** * @type {Actions['list']} */export async function list(tracks) { return tracks;}
/** * @type {Actions['resolve']} */export async function resolve({ uri }) { const blob = /** @type {Blob | undefined} */ (await IDB.get(CACHE_KEY_PREFIX + uri)); if (!blob) return undefined;
let blobUrl = blobUrls.get(uri);
if (!blobUrl) { blobUrl = URL.createObjectURL(blob); blobUrls.set(uri, blobUrl); }
return { expiresAt: Infinity, url: blobUrl };}
////////////////////////////////////////////// 🛠️////////////////////////////////////////////
/** * @param {string[]} uris */async function removeBlobs(uris) { await Promise.all(uris.map(async (uri) => { const blobUrl = blobUrls.get(uri); if (blobUrl) { URL.revokeObjectURL(blobUrl); blobUrls.delete(uri); } await IDB.del(CACHE_KEY_PREFIX + uri); }));}
////////////////////////////////////////////// ⚡️////////////////////////////////////////////
ostiary((context) => { rpc(context, { artwork, consult, detach, groupConsult, list, resolve, });});