Spaces:
Running on Zero
Running on Zero
File size: 4,304 Bytes
76e0bfa 623f6f8 76e0bfa 623f6f8 76e0bfa 623f6f8 76e0bfa 623f6f8 76e0bfa 623f6f8 76e0bfa | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | /* Read-only public reference library. No cookies or browser-persistent storage. */
(function(root,factory){
if(typeof module==='object'&&module.exports)module.exports=factory();
else root.TrackLibrary=factory();
})(typeof window==='undefined'?this:window,function(){
function create({fetch,digest,upload}){
let entries=[],selected='',cached=null;
return {
async load(){
const response=await fetch('/api/tracks',{cache:'no-store',credentials:'same-origin'});
if(!response.ok)throw Error('Built-in track catalog unavailable');
const catalog=await response.json();
if(!Array.isArray(catalog.tracks)||catalog.tracks.length>128)throw Error('Invalid track catalog');
const ids=new Set();
for(const entry of catalog.tracks){
if(!/^[a-z0-9-]{1,80}$/.test(entry.id)||ids.has(entry.id)||
typeof entry.display_name!=='string'||!entry.display_name.length||entry.display_name.length>100||
!Number.isInteger(entry.bytes)||entry.bytes<1||entry.bytes>1048576||
!/^[a-f0-9]{64}$/.test(entry.sha256))throw Error('Invalid track catalog');
ids.add(entry.id);
}
entries=catalog.tracks.map(entry=>({...entry}));
return this.entries();
},
entries:()=>entries.map(entry=>({...entry})),
selected:()=>selected,
select(id){
if(id&&!entries.some(entry=>entry.id===id))throw Error('Unknown built-in track');
if(id!==selected)cached=null;
selected=id;
},
info(){const entry=entries.find(entry=>entry.id===selected);return entry?{source:'builtin',...entry}:{source:'upload'};},
async file(){
if(!selected)return upload();
const entry=entries.find(entry=>entry.id===selected);
if(cached?.id===selected)return cached.blob;
const response=await fetch('/api/tracks/'+encodeURIComponent(selected)+'/file',
{cache:'no-store',credentials:'same-origin'});
if(!response.ok)throw Error('Built-in track unavailable; retry or choose an upload');
const bytes=await response.arrayBuffer();
if(bytes.byteLength!==entry.bytes||await digest(bytes)!==entry.sha256)
throw Error('Built-in track validation failed');
const blob=new Blob([bytes],{type:'application/octet-stream'});
cached={id:entry.id,blob};return blob;
}
};
}
function mount({document,fetch,digest}){
const selects=Array.from(document.querySelectorAll('[data-track-library]'));
const statuses=Array.from(document.querySelectorAll('[data-track-status]'));
const input=document.getElementById('track');
const picker=create({fetch,digest,upload:()=>input.files[0]});
let ready=false,busy=false;
function changed(){
if(typeof document.dispatchEvent==='function'&&document.defaultView?.Event)
document.dispatchEvent(new document.defaultView.Event('track-library-change'));
}
function render(message){
for(const select of selects){select.value=picker.selected();select.disabled=busy||!ready;}
const info=picker.info();
for(const status of statuses)status.textContent=message??(info.source==='builtin'?
info.display_name+' selected. It remains selected after a run.':
'Upload mode selected. Built-in replicas can be selected instead.');
}
for(const select of selects)select.addEventListener('change',()=>{
picker.select(select.value);if(select.value)input.value='';render();changed();
});
input.addEventListener('change',()=>{picker.select('');render();changed();});
picker.setBusy=value=>{busy=value;render();};
picker.load().then(()=>{
for(const select of selects){
for(const entry of picker.entries()){
const option=document.createElement('option');option.value=entry.id;
option.textContent=entry.display_name;select.append(option);
}
}
ready=picker.entries().length>0;
if(ready)picker.select(picker.entries()[0].id);
render(ready?undefined:'No built-in tracks in this installation. Custom uploads still work.');
changed();
}).catch(()=>render('Built-in catalog unavailable. Custom uploads still work.'));
return picker;
}
return {create,mount};
});
|