iOS remote support: Share Screen -> Connect Screen over LiveKit (core)

Rebuild the iOS remote-support screen share the RIGHT way: keep the exact
Share/Connect UX + session (consent + symmetric session-ended), swap only the
media to LiveKit since WKWebView can't getDisplayMedia. (Replaces the earlier
"route to a meeting" detour, which was reverted.)

Flow: customer taps Share Screen -> gets a 6-digit code (unchanged UI) -> helper
enters it in Connect Screen -> on the customer's "Allow", the app publishes the
screen natively (ReplayKit -> LiveKit) into a per-session room and tells the
agent it's a LiveKit session -> connect.html joins that room and shows the screen
in its existing viewer (recording/controls intact). Chat runs over the session
socket (no P2P data channel in this mode). Either side ending fires the existing
session-ended -> both tear down (symmetric disconnect).

- signaling.js: relay 'rs-livekit' + 'rs-chat' between the two ends.
- home.html: parent bridge so the /share iframe can drive startMeetingScreenShare/
  stop on the native plugin (+ a capability handshake).
- share.html (iOS): publish via native LiveKit instead of getDisplayMedia; chat
  over WS; hide mic (voice = next iteration) + remote-control (impossible on iOS).
- connect.html: LiveKit viewer for iOS-shared sessions, reusing the P2P viewer.

Web-only, no new build (reuses the shipped startMeetingScreenShare). Desktop
Share/Connect P2P unchanged. Two-way voice is the planned follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-22 13:16:06 +05:30
parent 224a2800c5
commit 620039a2ff
4 changed files with 70 additions and 6 deletions
+6
View File
@@ -6587,6 +6587,12 @@ async function doRegister(){
window.addEventListener('message',(e)=>{
if(e.origin!==location.origin) return; const d=e.data||{}; const n=window.bizConnectNative;
if(d.type==='rc-ping'){ const desktop=!!(n&&n.rcAvailable&&n.rcAvailable()); try{ e.source&&e.source.postMessage({type:'rc-pong', desktop}, location.origin); }catch(_){} return; }
// iOS remote-support: the /share iframe can't reach the native plugin, so it asks THIS top frame to
// publish the screen over LiveKit (WKWebView can't getDisplayMedia). Answer the capability handshake and
// drive startMeetingScreenShare/stopMeetingScreenShare (the same native method meetings use).
if(d.type==='bzc-native-ping'){ const ok=bzIsIOS() && !!(nativeCallPlugin() && nativeCallPlugin().startMeetingScreenShare); try{ e.source&&e.source.postMessage({type:'bzc-native', ok}, location.origin); }catch(_){} return; }
if(d.type==='rs-native-share'){ (async()=>{ try{ const NC=nativeCallPlugin(); if(!NC||!NC.startMeetingScreenShare||!d.room) return; const tk=await postJSON('/api/meetings/token',{ room:d.room, screen:true }); await NC.startMeetingScreenShare({ url:(tk.url||SFU.url), token:tk.token }); }catch(_){} })(); return; }
if(d.type==='rs-native-stop'){ try{ const NC=nativeCallPlugin(); if(NC&&NC.stopMeetingScreenShare) NC.stopMeetingScreenShare(); }catch(_){} return; }
if(!n) return;
if(d.type==='rc-arm'){ try{ n.rcArm&&n.rcArm(!!d.on); }catch(_){} return; }
if(d.type==='rc-input'){ try{ n.rcInput&&n.rcInput(d.evt); }catch(_){} return; }