diff --git a/server/public/home.html b/server/public/home.html index 51d7f3e..d7f36ed 100644 --- a/server/public/home.html +++ b/server/public/home.html @@ -424,6 +424,7 @@ .meet-bar .meet-ic{width:46px;height:46px;padding:0;border-radius:50%;background:#e8edf5;color:var(--blue);display:inline-flex;align-items:center;justify-content:center;} .meet-bar .meet-ic:hover{background:#dbe4f0;} .meet-bar .meet-ic.off{background:#fee2e2;color:var(--red);} + .meet-bar .meet-ic.on{background:var(--blue);color:#fff;} /* #9: screen-share highlighted while active (record keeps its red pulse via #meetRecBtn.on) */ .meet-bar .meet-ic.leave,.meet-bar .meet-ic.leave.off{background:#dc2626;color:#fff;} .meet-bar .meet-ic.leave:hover{background:#b91c1c;} /* Meetings dashboard (full-width, scrollable) */ @@ -826,7 +827,7 @@ - @@ -1456,6 +1457,8 @@ function convoShellHTML(it){ function senderAvatar(id, name){ const mem=convoMembers.find(x=>x.id===id); const av=mem&&mem.avatar; return ''+(av?'':'')+pEsc(initials(name||'?'))+''; } function bubbleHTML(m){ if(m.evt==='call-start') return '
📞 '+(m.from===ME.id?'You':pEsc(m.byName||'Someone'))+' started a call
'; + // Unanswered 1:1: the caller (message sender) sees "Call not answered"; the callee sees "Missed call". + if(m.evt==='call-end' && /Missed call|not answered/i.test(m.body||'')) return '
📞 '+(m.from===ME.id?'Call not answered':'Missed call')+'
'; if(m.system||m.from==='__system__') return '
'+pEsc(m.body)+'
'; const mine=m.from===ME.id; if(m.deleted) return '
'+ic('trash',12)+' This message was deleted'+pEsc(fmtClock(m.created_at))+'
'; @@ -3000,7 +3003,7 @@ function addTile(id, stream, label, muted){ tile.innerHTML='
'+pEsc(initials(label||'?'))+(av?'':'')+'
'+pEsc(label||'')+''; grid.appendChild(tile); } const v=tile.querySelector('video'); if(v && stream && v.srcObject!==stream) v.srcObject=stream; const hasVid=!!(stream && stream.getVideoTracks && stream.getVideoTracks().some(t=>t.enabled && t.readyState!=='ended')); - tile.classList.toggle('novid', !hasVid || meetCamOff.get(id)===true); // camOff peer → avatar even if a (disabled) track arrives + tile.classList.toggle('novid', !hasVid || (meetCamOff.get(id)===true && !meetSharers.has(id))); // camOff → avatar, UNLESS they're sharing a screen (#9: screen must show even with camera off) if(meetMuted.has(id)) setTileMute(id, meetMuted.get(id)); // apply any known mute state } function setTileMute(id, muted){ meetMuted.set(id, !!muted); const t=document.getElementById('meet-tile-'+id); if(t){ const b=t.querySelector('.meet-mute'); if(b) b.style.display=muted?'grid':'none'; if(muted) t.classList.remove('speaking'); } } @@ -3226,7 +3229,7 @@ async function onMeetMsg(e){ if(meetScreen) meetSend({type:'meeting-screen', on:true}); refreshMeetPanel(); return; } - if(m.type==='meeting-peer-state'){ setTileMute(m.peerId, !!m.muted); meetCamOff.set(m.peerId, !!m.camOff); const _t=document.getElementById('meet-tile-'+m.peerId); if(_t){ const v=_t.querySelector('video'), s=v&&v.srcObject; const hv=!!(s&&s.getVideoTracks&&s.getVideoTracks().some(tr=>tr.enabled&&tr.readyState!=='ended')); _t.classList.toggle('novid', !hv || !!m.camOff); } refreshMeetPanel(); return; } // camOff -> show avatar, not a black tile + if(m.type==='meeting-peer-state'){ setTileMute(m.peerId, !!m.muted); meetCamOff.set(m.peerId, !!m.camOff); const _t=document.getElementById('meet-tile-'+m.peerId); if(_t){ const v=_t.querySelector('video'), s=v&&v.srcObject; const hv=!!(s&&s.getVideoTracks&&s.getVideoTracks().some(tr=>tr.enabled&&tr.readyState!=='ended')); _t.classList.toggle('novid', !hv || (!!m.camOff && !meetSharers.has(m.peerId))); } refreshMeetPanel(); return; } // camOff -> avatar, unless sharing a screen (#9) if(m.type==='meeting-host'){ const was=meetIsHost; meetHostId=m.hostPeerId; meetIsHost=(m.hostPeerId===meetMyId); if(meetIsHost&&!was){ toast('You are now the host'); try{ speak('You are now the host'); }catch(_){} } refreshMeetPanel(); updateHostControls(); return; } if(m.type==='meeting-transcribe-state'){ applyRoomTx(!!m.active); return; } // ≥1 subscriber → transcribe my mic if(m.type==='meeting-recording'){ recNotice(!!m.on, m.by); return; } // someone is recording — show + announce