A music player that connects to your cloud/distributed storage. diffuse.sh
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112import foundation from "~/common/foundation.js";import * as CID from "~/common/cid.js";import * as Output from "~/common/output.js";import { createLoader, linkTileResources, renderError } from "~/common/loader.js";import { insertPreludes } from "~/common/facets/prelude.js";import { computed, effect } from "~/common/signal.js";
// Containerconst container = /** @type {HTMLDivElement} */ ( document.querySelector("#container"));
// The loader relies on features that only work in a secure context.// Fail fast with a helpful message instead of letting those APIs throw cryptically.if (!window.isSecureContext) { renderError( container, "Diffuse requires a secure context (HTTPS or localhost)", ); throw new Error("Insecure context: Diffuse loader requires a secure context");}
// Output elementconst output = await foundation.orchestrator.output();
// Preludesconst facets = await Output.data(output.facets);let preludesInserted = false;
// Reload when the prelude facets change after initial load.// initialPreludeKey is captured the first time the collection finishes loading// (not at startup when it's still pending), so the effect never fires on the// very first load and causes an infinite reload loop.const preludeKey = computed(() => { const col = output.facets.collection(); if (col.state !== "loaded") return null; return col.data .filter((f) => f.kind === "prelude") .map((f) => `${f.id}:${f.enabled !== false}:${JSON.stringify(f.resources ?? null)}`) .join(",");});
let initialPreludeKey = /** @type {string | null} */ (null);
effect(() => { // Never reload mid-OAuth-callback: a prelude change (e.g. synthesized // recovery preludes being replaced by the real synced set) would otherwise // abort the in-flight `finalizeAuthorization` token exchange. const params = new URLSearchParams(window.location.hash.slice(1)); if (params.has("code") || params.has("state")) return;
const key = preludeKey(); if (key === null) return; if (initialPreludeKey === null) { initialPreludeKey = key; return; } if (key !== initialPreludeKey) { const lastReload = Number(sessionStorage.getItem("diffuse/l/last-reload") ?? 0); if (Date.now() - lastReload < 60_000) return; sessionStorage.setItem("diffuse/l/last-reload", String(Date.now())); window.location.reload(); }});
// LoadcreateLoader({ $type: "sh.diffuse.output.facet", label: "Facet", source: () => output.facets, async render(facet) { // Tile facets are content addressed: `facet.cid` is resolved during loading // from the MASL `resources["/"].src` CID, so the loaded root HTML is // verified against it. Plain HTML facets carry no `cid`, so nothing to // verify. if (facet.cid) { const valid = await CID.verify( new TextEncoder().encode(facet.html ?? ""), facet.cid, );
if (!valid) { renderError( container, "CID mismatch: HTML content does not match the CID", ); return; } }
if (!preludesInserted) { preludesInserted = true; await insertPreludes(facets, document.body); }
const range = document.createRange(); range.selectNode(container); const documentFragment = range.createContextualFragment(facet.html ?? "");
// Rewrite absolute `/…` resource URLs to Blob URLs on the detached fragment // BEFORE inserting it, so the browser never starts a request for the raw // (un-rewritten) path — attaching first would intermittently fetch e.g. // `/styles.css` from the build root and 404. If linking fails for any // reason, still render the facet rather than leaving the page blank. if (facet.tile) { try { linkTileResources(documentFragment, facet.tile.resources, facet.tile.blocks); } catch (err) { console.error("Failed to link tile resources", err); } } container.append(documentFragment); },});