SOURCE / PINNED RELEASE
Made of little things.
Hang On, Fren
- Release
- 8e67c38fa0ed…
- Author-recorded commit
- 11fefa16fa50…
- License
- LICENSE
- Author’s source reference
- nostr://npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2/wss%3A%2F%2Fgit.napplet.soy%2F/n-d6c0308a2a8
Archive hash verified: 06d9523d4a9c1323…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
// Generated by soyLI. Edit napplet.assets.json through soyli assets or the manager.
const assets = {"art-pack": {hash: "802825af873fe63234bdbc06bdff6a0e2fa02f6180bb7102cee54d88f6036842"},
"music-amalfi-coast-coastal-velocity": {hash: "d4a2d2f960a65eba3719a9f229981b6c3f3c1a02d69c91f274194555d8498bbe"},
"music-dawn-of-everything": {hash: "9fd96cf3282e773bcc6d2299bab8cf04e3af02ab04b5da48c2a6e5c9b1b062f7"},
"music-dusk-of-the-dinosaurs": {hash: "0916a93ce0cabe969e4a3ecd0934d354f04f51c454a8371b9ce8de98df512678"},
"music-old-mallorca-tramuntana-motion": {hash: "c60471f581a1f5a778b21f1fa2e907c04412b32f44e81de38491a7579ff6a767"},
"music-old-manchester-loose-gears": {hash: "bab022b60eaaec74ba5e1c6e82cb9ad8495c34e8cf4d9d78af4cc3398b9734cc"},
"music-old-prague-allegretto": {hash: "d354f785316e5ab363474678f8003e34cf96eb0e71c7c830d44e2a06b38f716f"},
"music-taj-mahal-roses-at-dawn": {hash: "f079cc0241d3520b86007a783cb930482fd1649291b8c043758df6e73dc3fbec"},
"music-the-crooked-time-machine": {hash: "d052f3e520f38d569a137343549a1bef3d4d927baf85e6d707b1eaac6e79fbe2"},
"music-the-descent": {hash: "b43faeb6e03c9ea10852d8b8cd21d44a833e94bada71a635ce248b73e39febbf"},
"music-the-longest-night": {hash: "d43d2434a68aa98bf7ba3806031afe37d1a8c889330f053c8ed460d246a7341b"},
"music-timeline-restored": {hash: "c8ae0a7b734171b3347d6f13b1220e1de14589f8695d2f0fa30bb19e03ea4ae1"},
"music-two-cavemen-one-broken-timeline": {hash: "15372ab8d54797b1679928ba5678aac87235aa22d58ac5045ffd3a908ddc3703"}};
const blobs = new Map();
const urls = new Map();
function assetEntry(id) {
const entry = Object.hasOwn(assets, id) ? assets[id] : undefined;
if (!entry) throw new Error('Unknown asset: ' + id);
return entry;
}
function embeddedBlob(entry) {
const comma = entry.url.indexOf(',');
if (!entry.url.startsWith('data:') || comma < 0)
throw new Error('Embedded asset is not a data URL. Rebuild with the single-file plugin.');
const data = entry.url.slice(comma + 1);
let bytes;
if (/;base64$/i.test(entry.url.slice(0, comma))) {
bytes = Uint8Array.from(atob(decodeURIComponent(data)), char => char.charCodeAt(0));
} else {
bytes = new TextEncoder().encode(data);
let length = 0;
for (let offset = 0; offset < bytes.length; offset++) {
if (bytes[offset] === 37) {
const hex = String.fromCharCode(bytes[offset + 1], bytes[offset + 2]);
if (!/^[a-f0-9]{2}$/i.test(hex)) throw new Error('Invalid embedded asset data URL.');
bytes[length++] = parseInt(hex, 16);
offset += 2;
} else bytes[length++] = bytes[offset];
}
bytes = bytes.subarray(0, length);
}
return new Blob([bytes], { type: entry.mime });
}
/** @param {string} id */
export async function assetBlob(id) {
const entry = assetEntry(id);
if (!blobs.has(id)) {
const pending = Promise.resolve().then(() => entry.url
? embeddedBlob(entry)
: window.napplet.resource.bytes('blossom:sha256:' + entry.hash));
blobs.set(id, pending);
pending.catch(() => { if (blobs.get(id) === pending) blobs.delete(id); });
}
return blobs.get(id);
}
/** @param {string} id */
export async function assetUrl(id) {
const entry = assetEntry(id);
if (entry.url) return entry.url;
if (!urls.has(id)) {
const pending = assetBlob(id).then(blob => URL.createObjectURL(blob));
urls.set(id, pending);
pending.catch(() => { if (urls.get(id) === pending) urls.delete(id); });
}
return urls.get(id);
}
export function releaseAssetUrls() {
for (const value of urls.values()) value.then(url => URL.revokeObjectURL(url)).catch(() => {});
urls.clear();
blobs.clear();
}
