diff --git a/internal/httpapi/static/app.js b/internal/httpapi/static/app.js index 04f9c19..bfeb7e1 100644 --- a/internal/httpapi/static/app.js +++ b/internal/httpapi/static/app.js @@ -28,7 +28,7 @@ async function api(path, params){ return res.text(); } -function ensureTwitterWidgets(){ if(st.twLoaded) return; st.twLoaded = true; const s=document.createElement('script'); s.async=true; s.src='https://platform.twitter.com/widgets.js'; document.head.appendChild(s); } +function ensureTwitterWidgets(){ if(st.twLoaded) { if(window.twttr && twttr.widgets && typeof twttr.widgets.load==='function'){ /* keep for later calls */ } return; } st.twLoaded = true; const s=document.createElement('script'); s.async=true; s.src='https://platform.twitter.com/widgets.js'; document.head.appendChild(s); } function appendBatch(arr){ const el=document.getElementById('tail'); const frag=document.createDocumentFragment(); arr.forEach(m=>{ const key=msgKey(m); if(st.seen.has(key)) return; st.seen.add(key); const div=document.createElement('div'); div.className='msg'; div.dataset.key=key; div.innerHTML=lineHTML(m); frag.appendChild(div); processLinks(div); }); el.appendChild(frag); pinBottomMulti(); } function prependBatch(arr){ const el=document.getElementById('tail'); const oldTop=el.firstChild; const beforeTop = oldTop ? oldTop.getBoundingClientRect().top : 0; const frag=document.createDocumentFragment(); arr.forEach(m=>{ const key=msgKey(m); if(st.seen.has(key)) return; st.seen.add(key); const div=document.createElement('div'); div.className='msg'; div.dataset.key=key; div.innerHTML=lineHTML(m); frag.appendChild(div); processLinks(div); }); el.insertBefore(frag, el.firstChild); if(oldTop){ const afterTop = oldTop.getBoundingClientRect().top; const delta = afterTop - beforeTop; window.scrollBy(0, delta); } } @@ -48,7 +48,17 @@ function processLinks(scope){ const links = scope.querySelectorAll('a[href]:not( html += ''; const row=document.createElement('div'); row.style.display='flex'; row.style.alignItems='flex-start'; row.style.gap='.5rem'; row.innerHTML=html; details.appendChild(row); - if(card.html){ const wrap=document.createElement('div'); wrap.innerHTML=card.html; details.appendChild(wrap); ensureTwitterWidgets(); } + if(card.html){ + const wrap=document.createElement('div'); + wrap.innerHTML=card.html; + // Tweak YouTube iframe sizing + const ifr=wrap.querySelector('iframe'); + if(ifr){ ifr.removeAttribute('width'); ifr.removeAttribute('height'); ifr.style.width='100%'; ifr.style.maxWidth='640px'; ifr.style.aspectRatio='16/9'; ifr.style.height='auto'; ifr.style.borderRadius='.5rem'; } + details.appendChild(wrap); + // Twitter embed render pass + ensureTwitterWidgets(); + if(window.twttr && twttr.widgets && typeof twttr.widgets.load==='function'){ try{ twttr.widgets.load(wrap); }catch(e){} } + } details.querySelectorAll('img').forEach(img=> img.addEventListener('load', ()=> pinBottomMulti())); c.appendChild(details); const sum=document.createElement('div'); sum.className='link-summary'; sum.style.whiteSpace='pre-wrap'; sum.style.marginTop='.25rem'; sum.style.display='none'; c.appendChild(sum);