74 lines
4.0 KiB
JavaScript
74 lines
4.0 KiB
JavaScript
(function(){
|
|
const qs = new URLSearchParams(window.location.search);
|
|
const token = qs.get('token');
|
|
const panel = document.getElementById('panel');
|
|
const list = document.getElementById('list');
|
|
const roundEl = document.getElementById('round');
|
|
const updatedEl = document.getElementById('updated');
|
|
const countEl = document.getElementById('count');
|
|
let ICONS = {}; let EMOJI = {}; let KNOWN = [];
|
|
function fmtAgo(ms){ const d=Date.now()-ms; if(d<1500)return 'just now'; const s=Math.floor(d/1000); if(s<60) return s+'s ago'; const m=Math.floor(s/60); if(m<60) return m+'m ago'; const h=Math.floor(m/60); return h+'h ago'; }
|
|
function avatarSrc(a){ if(!a.avatar) return ''; if(a.avatar.startsWith('http') || a.avatar.startsWith('/')) return a.avatar; return '/avatars/' + encodeURIComponent(a.avatar); }
|
|
function iconSrc(key){ const f = ICONS[key]; return f ? ('/icons/' + encodeURIComponent(f)) : '' }
|
|
function render(state){
|
|
ICONS = state.condition_icons||{}; EMOJI = state.condition_emoji||{}; KNOWN = state.known_conditions||[];
|
|
const deadMode = state.dead_mode || 'normal';
|
|
if(!state.visible){ panel.classList.add('hideall'); return; } else { panel.classList.remove('hideall'); }
|
|
roundEl.textContent = state.round;
|
|
updatedEl.textContent = fmtAgo(state.updated_at);
|
|
list.innerHTML = '';
|
|
(state.actors||[]).forEach((a, idx)=>{
|
|
if(!a.visible) return;
|
|
if(a.dead && deadMode==='hide') return;
|
|
const cls = ['row','type-'+(a.type||'pc')];
|
|
if(idx===state.turn_idx) cls.push('active');
|
|
if(a.dead){ cls.push('dead'); if(deadMode==='shrink') cls.push('shrunk'); }
|
|
const card = document.createElement('div');
|
|
card.className = cls.join(' ');
|
|
|
|
// Portrait
|
|
const portrait = document.createElement(a.avatar? 'img':'div');
|
|
if(a.avatar){ portrait.src = avatarSrc(a); portrait.className='portrait'; portrait.alt=a.name; }
|
|
else{ portrait.className='noavatar'; }
|
|
card.appendChild(portrait);
|
|
|
|
// Death & Concentration badges
|
|
if(a.dead){ const db = document.createElement('div'); db.className='deathBadge'; db.textContent='☠'; card.appendChild(db); }
|
|
if(a.conc){ const cs = document.createElement('div'); cs.className='concStar'; cs.textContent='✦'; card.appendChild(cs); }
|
|
|
|
// Name + meta
|
|
const name = document.createElement('div'); name.className='name';
|
|
const n = document.createElement('div'); n.className='n'; n.textContent=a.name; name.appendChild(n);
|
|
const meta = document.createElement('div'); meta.className='meta';
|
|
const bits = [];
|
|
if(a.hp){ bits.push('HP '+a.hp); }
|
|
if(a.reveal_ac && a.ac){ bits.push('AC '+a.ac); }
|
|
bits.push('Init '+Math.floor(a.init));
|
|
if(a.note){ bits.push(a.note); }
|
|
meta.textContent = bits.join(' · ');
|
|
name.appendChild(meta);
|
|
card.appendChild(name);
|
|
|
|
// Conditions row
|
|
if (Array.isArray(a.effects) && a.effects.length){
|
|
const tags = document.createElement('div'); tags.className='tags';
|
|
a.effects.forEach(e=>{ const t=document.createElement('span'); t.className='tag'; const wrap=document.createElement('span'); wrap.className='ico_wrap'; const src=iconSrc(e); if(src){ const i=document.createElement('img'); i.className='ico'; i.alt=e; i.src=src; wrap.appendChild(i); } else { wrap.textContent='•'; } t.appendChild(wrap); const lbl=document.createElement('span'); lbl.textContent=e; t.appendChild(lbl); tags.appendChild(t); });
|
|
card.appendChild(tags);
|
|
}
|
|
|
|
list.appendChild(card);
|
|
});
|
|
countEl.textContent = list.childElementCount + ' shown';
|
|
}
|
|
let last = null; let since = 0;
|
|
async function poll(){
|
|
try{
|
|
const r = await fetch(`/api/state?since=${since}&token=${encodeURIComponent(token)}`);
|
|
if(!r.ok){ throw new Error('state '+r.status); }
|
|
const s = await r.json(); last = s; render(s); since = s.version;
|
|
}catch(e){ }
|
|
setTimeout(poll, 200);
|
|
}
|
|
setInterval(()=>{ if(last) updatedEl.textContent = fmtAgo(last.updated_at); }, 3000);
|
|
poll();
|
|
})(); |