From 6b213f085e54c27f773c97fa9020e532a77da59e Mon Sep 17 00:00:00 2001 From: Thomas Cravey Date: Sun, 17 Aug 2025 16:26:29 -0500 Subject: [PATCH] feat(ui): add collapse/expand buttons for link cards and summaries --- internal/httpapi/static/app.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/internal/httpapi/static/app.js b/internal/httpapi/static/app.js index 54c92ef..64b12b2 100644 --- a/internal/httpapi/static/app.js +++ b/internal/httpapi/static/app.js @@ -36,28 +36,35 @@ function processLinks(scope){ const links = scope.querySelectorAll('a[href]:not( fetch('/api/linkcard?url='+encodeURIComponent(a.href)).then(r=>r.json()).then(card=>{ if(!card) return; if(card.title||card.description||card.image||card.html){ - const c=document.createElement('div'); c.className='card'; var html=''; + const c=document.createElement('div'); c.className='card'; + const details=document.createElement('div'); details.className='card-details'; + var html=''; if(card.image){ html += '
'; } html += '
'; if(card.title){ html += '
'+escapeHtml(card.title)+'
'; } if(card.description){ html += '
'+escapeHtml(card.description)+'
'; } html += '
'; const row = document.createElement('div'); row.style.display='flex'; row.style.alignItems='flex-start'; row.style.gap='.5rem'; row.innerHTML = html; - c.appendChild(row); - c.querySelectorAll('img').forEach(img=> img.addEventListener('load', ()=> pinBottomMulti())); - if(card.html){ const wrap=document.createElement('div'); wrap.innerHTML=card.html; c.appendChild(wrap); ensureTwitterWidgets(); } - // Summary control row + details.appendChild(row); + details.querySelectorAll('img').forEach(img=> img.addEventListener('load', ()=> pinBottomMulti())); + if(card.html){ const wrap=document.createElement('div'); wrap.innerHTML=card.html; details.appendChild(wrap); ensureTwitterWidgets(); } + c.appendChild(details); + // Controls const ctrl = document.createElement('div'); ctrl.style.marginTop='.25rem'; const btn = document.createElement('button'); btn.type='button'; btn.title='Summarize this link'; btn.textContent='\u25B6'; btn.style.padding='0 .4rem'; btn.style.fontSize='.9rem'; const spinner = document.createElement('span'); spinner.textContent=''; spinner.style.marginLeft='.5rem'; const sum = document.createElement('div'); sum.className='link-summary'; sum.style.whiteSpace='pre-wrap'; sum.style.marginTop='.25rem'; + const toggleCard = document.createElement('button'); toggleCard.type='button'; toggleCard.title='Collapse/expand card'; toggleCard.textContent='−'; toggleCard.style.padding='0 .4rem'; toggleCard.style.fontSize='.9rem'; toggleCard.style.marginLeft='.5rem'; + const toggleSum = document.createElement('button'); toggleSum.type='button'; toggleSum.title='Collapse/expand summary'; toggleSum.textContent='−'; toggleSum.style.padding='0 .4rem'; toggleSum.style.fontSize='.9rem'; toggleSum.style.marginLeft='.25rem'; + toggleCard.onclick = ()=>{ const hidden = details.style.display==='none'; details.style.display = hidden? '' : 'none'; toggleCard.textContent = hidden? '−' : '+'; pinBottomMulti(); }; + toggleSum.onclick = ()=>{ const hidden = sum.style.display==='none'; sum.style.display = hidden? '' : 'none'; toggleSum.textContent = hidden? '−' : '+'; pinBottomMulti(); }; btn.onclick = async ()=>{ - btn.disabled=true; spinner.textContent='…'; sum.textContent=''; + btn.disabled=true; spinner.textContent='…'; sum.textContent=''; sum.style.display=''; toggleSum.textContent='−'; try{ const data = await api('/api/linksummary',{query:{url:a.href}}); sum.textContent = (data && data.summary) ? data.summary : '(no summary)'; } catch(e){ sum.textContent = 'error: '+e; } - spinner.textContent=''; btn.disabled=false; + spinner.textContent=''; btn.disabled=false; pinBottomMulti(); }; - ctrl.appendChild(btn); ctrl.appendChild(spinner); + ctrl.appendChild(btn); ctrl.appendChild(spinner); ctrl.appendChild(toggleCard); ctrl.appendChild(toggleSum); c.appendChild(ctrl); c.appendChild(sum); a.parentNode.insertBefore(c, a.nextSibling);