diff --git a/server/public/home.html b/server/public/home.html index d69fe93..ec176ff 100644 --- a/server/public/home.html +++ b/server/public/home.html @@ -2654,7 +2654,7 @@ function meetParticipantsList(){ const a=[{id:'__local', name:((ME&&ME.name)||(M let meetChatLog=[], meetChatUnread=0, meetChatTo=''; function resetMeetChat(){ meetChatLog=[]; meetChatUnread=0; meetChatTo=''; const c=document.getElementById('meetChat'); if(c) c.remove(); updateMeetChatBadge(); } function meetChatRecipients(){ const a=[]; meetPeers.forEach((pp,pid)=>a.push({id:pid, name:meetNames.get(pid)||pp.name||'Guest'})); return a; } -function toggleMeetChat(){ const ex=document.getElementById('meetChat'); if(ex){ ex.remove(); return; } const meet=document.querySelector('.meet'); if(!meet) return; const p=document.createElement('div'); p.id='meetChat'; p.className='meet-panel meet-chat'; meet.appendChild(p); meetChatUnread=0; updateMeetChatBadge(); renderMeetChat(); } +function toggleMeetChat(){ const ex=document.getElementById('meetChat'); if(ex){ ex.remove(); try{ bzNativeSyncTiles(); }catch(_){} return; } const meet=document.querySelector('.meet'); if(!meet) return; const p=document.createElement('div'); p.id='meetChat'; p.className='meet-panel meet-chat'; meet.appendChild(p); meetChatUnread=0; updateMeetChatBadge(); renderMeetChat(); try{ bzNativeSyncTiles(); }catch(_){} } function updateMeetChatBadge(){ const b=document.getElementById('meetChatBadge'); if(!b) return; if(meetChatUnread>0){ b.textContent=meetChatUnread>9?'9+':meetChatUnread; b.style.display='grid'; } else b.style.display='none'; } function renderMeetChat(){ const p=document.getElementById('meetChat'); if(!p) return; @@ -2719,7 +2719,7 @@ function copyMeetingLink(){ function fallbackCopy(text,cb){ try{ const ta=document.createElement('textarea'); ta.value=text; ta.style.position='fixed'; ta.style.opacity='0'; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); ta.remove(); cb&&cb(); }catch(_){ prompt('Copy this link:', text); } } let meetPanelTab='people'; // 'people' | 'add' let _addPool=null; // cached candidates for "Add people" (group members for a group call) -function toggleMeetPanel(){ const ex=document.getElementById('meetPanel'); if(ex){ ex.remove(); return; } const meet=document.querySelector('.meet'); if(!meet) return; meetPanelTab='people'; const p=document.createElement('div'); p.id='meetPanel'; p.className='meet-panel'; meet.appendChild(p); renderMeetPanel(); } +function toggleMeetPanel(){ const ex=document.getElementById('meetPanel'); if(ex){ ex.remove(); try{ bzNativeSyncTiles(); }catch(_){} return; } const meet=document.querySelector('.meet'); if(!meet) return; meetPanelTab='people'; const p=document.createElement('div'); p.id='meetPanel'; p.className='meet-panel'; meet.appendChild(p); renderMeetPanel(); try{ bzNativeSyncTiles(); }catch(_){} } function renderMeetPanel(){ const p=document.getElementById('meetPanel'); if(!p) return; const list=meetParticipantsList(); @@ -5060,9 +5060,10 @@ function openMeetMore(anchor){ const r=anchor.getBoundingClientRect(); menu.style.left=Math.max(8,Math.min(r.left-100, window.innerWidth-menu.offsetWidth-8))+'px'; menu.style.top=Math.max(8,(r.top-menu.offsetHeight-10))+'px'; - menu.querySelectorAll('.mm-opt').forEach(b=>b.onclick=()=>{ const it=items[+b.dataset.i]; menu.remove(); try{ it.fn(); }catch(_){} }); - const close=(e)=>{ if(!menu.contains(e.target) && !anchor.contains(e.target)){ menu.remove(); document.removeEventListener('mousedown',close); document.removeEventListener('touchstart',close); } }; + menu.querySelectorAll('.mm-opt').forEach(b=>b.onclick=()=>{ const it=items[+b.dataset.i]; menu.remove(); try{ it.fn(); }catch(_){} try{ if(meetNative) bzNativeSyncTiles(); }catch(_){} }); + const close=(e)=>{ if(!menu.contains(e.target) && !anchor.contains(e.target)){ menu.remove(); document.removeEventListener('mousedown',close); document.removeEventListener('touchstart',close); try{ if(meetNative) bzNativeSyncTiles(); }catch(_){} } }; setTimeout(()=>{ document.addEventListener('mousedown',close); document.addEventListener('touchstart',close); },0); + try{ if(meetNative) bzNativeSyncTiles(); }catch(_){} // clear the native video NOW so the menu isn't hidden behind it } async function setSpeakerDevice(id){ meetSinkId=id||''; try{ localStorage.setItem('bzc_sink', meetSinkId); }catch(_){} @@ -5390,9 +5391,14 @@ let meetNative=false, meetNativeUuid=null, _ncEnding=false; // native call: WebV // join-leave / camera-toggle changes; a no-op on web calls. getBoundingClientRect coords are CSS px, which // equal points in the WKWebView, so the plugin can use them directly. let _ncTileTimer=null; +// Any web menu/panel/modal that opens over the meeting would be hidden BEHIND the native video (which draws +// on top of the WebView). While one is open, clear the native video so the web UI is usable; the poll restores +// it when they close. (Covers the More/audio menus, participant panel, meeting chat, modals, image lightbox.) +function bzMeetOverlayOpen(){ return !!document.querySelector('.meet-panel, .spk-menu, .modal-ov, .lightbox'); } function bzNativeSyncTiles(){ if(!meetNative) return; const NC=nativeCallPlugin(); if(!NC||!NC.syncVideoTiles) return; + if(bzMeetOverlayOpen()){ try{ NC.syncVideoTiles({ tiles:[] }); }catch(_){} return; } // a menu/panel is open → don't cover it const tiles=[]; // Native views draw ON TOP of the WebView, so a full-height tile would cover the control bar. Never let a // tile's native video extend past the top of the meeting controls (or, in normal grid mode, below the grid).