diff --git a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/CompanionServer.kt b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/CompanionServer.kt index ce96e8c4..fbc0b9c6 100644 --- a/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/CompanionServer.kt +++ b/core/src/main/kotlin/me/eternal/purrfectsnap/core/features/impl/global/CompanionServer.kt @@ -722,189 +722,6 @@ function closeDetail(){ q('ne').querySelectorAll('.net-row').forEach(function(r){r.classList.remove('selected');}); } // ---- Shared ---- -function filter(listId,filterId){ - var f=q(filterId).value.toLowerCase(); - q(listId).querySelectorAll('.log-+e).toISOString().slice(11,23)} -function q(id){return document.getElementById(id)} -function loadHistory(){ - fetch('/logs').then(function(r){return r.json();}).then(function(a){a.forEach(function(e){addLog(e,false);});}); - fetch('/network').then(function(r){return r.json();}).then(function(a){a.forEach(function(e){addNet(e,false);});}); -} -function startSSE(){ - var es=new EventSource('/events'); - es.onopen=function(){q('dot').textContent='● connected';q('dot').className='on';}; - es.onerror=function(){q('dot').textContent='● disconnected';q('dot').className='off';}; - es.addEventListener('log',function(e){addLog(JSON.parse(e.data),true);}); - es.addEventListener('network',function(e){addNet(JSON.parse(e.data),true);}); - es.addEventListener('network_update',function(e){updateNet(JSON.parse(e.data));}); -} -// ---- Logs ---- -function addLog(e,live){ - lc++; - var el=document.createElement('div'); - el.className='log-row '+(e.level||'I'); - el.textContent='['+ts(e.ts)+'] '+(e.level||'I')+' '+(e.tag||'')+': '+(e.msg||''); - el.dataset.t=el.textContent.toLowerCase(); - applyLogFilter(el); - q('le').appendChild(el); - if(live&&q('ls').checked)el.scrollIntoView(); - upd(); -} -function applyLogFilter(el){ - var f=q('lf').value.toLowerCase(); - el.style.display=(!f||el.dataset.t.includes(f))?'':'none'; -} -// ---- Network rows ---- -function methodClass(m){return m||'GET';} -function statusSpan(e){ - if(!e.done)return ''; - if(e.status&&e.status>=400)return ''+e.status+''; - return ''+(e.status||'ok')+''; -} -function sizeStr(bytes){ - if(bytes==null)return ''; - if(bytes<1024)return bytes+'B'; - return (bytes/1024).toFixed(1)+'K'; -} -function addNet(e,live){ - nc++; - netMap[e.id]=e; - var el=document.createElement('div'); - el.className='net-row'; - el.id='nr-'+e.id; - el.dataset.t=(e.uri||'').toLowerCase(); - el.innerHTML=''+(e.method||'?')+''+ - statusSpan(e)+ - ''+(e.uri||'')+''+ - ''+(e.resSize!=null?sizeStr(e.resSize):'')+''; - el.onclick=function(){openDetail(e.id);}; - applyNetFilter(el); - q('ne').appendChild(el); - if(live&&q('ns').checked)el.scrollIntoView(); - upd(); -} -function updateNet(e){ - netMap[e.id]=Object.assign(netMap[e.id]||{},e); - var row=q('nr-'+e.id); - if(!row)return; - var m=netMap[e.id]; - row.innerHTML=''+(m.method||'?')+''+ - statusSpan(m)+ - ''+(m.uri||'')+''+ - ''+(m.resSize!=null?sizeStr(m.resSize):'')+''; - row.onclick=function(){openDetail(m.id);}; - if(detailId===e.id)refreshDetail(); -} -function applyNetFilter(el){ - var f=q('nf').value.toLowerCase(); - el.style.display=(!f||el.dataset.t.includes(f))?'':'none'; -} -function filterNet(){ - q('ne').querySelectorAll('.net-row').forEach(applyNetFilter); -} -// ---- Detail panel ---- -function openDetail(id){ - detailId=id; - detailFull=null; - var sum=netMap[id]; - if(!sum)return; - q('detail').style.display='flex'; - q('ne').querySelectorAll('.net-row').forEach(function(r){r.classList.remove('selected');}); - var row=q('nr-'+id); - if(row)row.classList.add('selected'); - renderDetailMeta(sum); - q('d-body').textContent='Loading…'; - fetch('/network/'+id).then(function(r){return r.json();}).then(function(full){ - detailFull=full; - renderDetailMeta(full); - renderBody(); - }).catch(function(){q('d-body').textContent='Failed to load details.';}); -} -function refreshDetail(){ - if(!detailId)return; - var sum=netMap[detailId]; - if(!sum)return; - renderDetailMeta(sum); - if(detailFull)renderBody(); -} -function renderDetailMeta(e){ - var m=e.method||'?'; - q('d-badge').className='badge '+methodClass(m); - q('d-badge').textContent=m; - q('d-badge').style.cssText=''; - q('d-status').textContent=e.status||(e.done?'ok':'…'); - q('d-status').className=e.status&&e.status>=400?'status-err':'status-ok'; - q('d-uri').textContent=e.uri||''; -} -function showTab(tab){ - detailTab=tab; - q('tab-req').className='tab-btn'+(tab==='req'?' active':''); - q('tab-res').className='tab-btn'+(tab==='res'?' active':''); - renderBody(); -} -function toggleHex(){ - hexMode=!hexMode; - q('btn-hex').className='tab-btn'+(hexMode?' active':''); - renderBody(); -} -function renderBody(){ - if(!detailFull){q('d-body').textContent='Loading…';return;} - var b64=detailTab==='res'?detailFull.resBody:detailFull.reqBody; - if(!b64){q('d-body').textContent='(empty)';return;} - var truncated=b64.endsWith('==TRUNCATED=='); - if(truncated)b64=b64.slice(0,b64.length-13); - var bytes=b64ToBytes(b64); - var suffix=truncated?'\n\n[truncated at 48 KB]':''; - if(hexMode){q('d-body').textContent=hexDump(bytes)+suffix;return;} - var text=tryUtf8(bytes); - if(text){ - var pretty=tryJsonPretty(text); - q('d-body').textContent=(pretty||text)+suffix; - }else{ - q('d-body').textContent=hexDump(bytes)+suffix; - } -} -function b64ToBytes(b64){ - var bin=atob(b64),bytes=new Uint8Array(bin.length); - for(var i=0;i=32||c===10||c===13||c===9)printable++;} - return(printable/Math.min(text.length,200))>0.85?text:null; - }catch(e){return null;} -} -function tryJsonPretty(text){ - try{return JSON.stringify(JSON.parse(text),null,2);}catch(e){return null;} -} -function hexDump(bytes){ - var lines=[]; - for(var i=0;i=32&&b<127?String.fromCharCode(b):'.';}).join(''); - lines.push(i.toString(16).padStart(8,'0')+' '+hex.padEnd(48)+' '+asc); - } - return lines.join('\n'); -} -function copyBody(){ - if(!detailFull)return; - var b64=detailTab==='res'?detailFull.resBody:detailFull.reqBody; - if(!b64)return; - if(b64.endsWith('==TRUNCATED=='))b64=b64.slice(0,b64.length-13); - var text=tryUtf8(b64ToBytes(b64))||b64; - navigator.clipboard&&navigator.clipboard.writeText(text); -} -function closeDetail(){ - detailId=null; - detailFull=null; - q('detail').style.display='none'; - q('ne').querySelectorAll('.net-row').forEach(function(r){r.classList.remove('selected');}); -} -// ---- Shared ---- function filter(listId,filterId){ var f=q(filterId).value.toLowerCase(); q(listId).querySelectorAll('.log-row').forEach(function(el){