pre-push commit
This commit is contained in:
74
battleflow/static/js/board.js
Normal file
74
battleflow/static/js/board.js
Normal file
@@ -0,0 +1,74 @@
|
||||
(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();
|
||||
})();
|
||||
Reference in New Issue
Block a user