diff --git a/src/main/assets/calls/index.html b/src/main/assets/calls/index.html index 8bc4fa78f..2ff25831e 100644 --- a/src/main/assets/calls/index.html +++ b/src/main/assets/calls/index.html @@ -13,21 +13,21 @@ - +`)}function J(e,t){if(!t.trim()){console.error(e,"No SDP content provided");return}try{const n=hn(t);n&&console.log(bn(e,n))}catch(n){const o=n instanceof Error?n.message:"Unknown error";console.error(e,`Error parsing SDP: ${o}`)}}const ot={iceServers:[],iceTransportPolicy:"all",bundlePolicy:"max-bundle",iceCandidatePoolSize:1},fe=class fe{constructor(t,n,o){M(this,"peerConnection");M(this,"setIceServersPromise");M(this,"state");M(this,"resolveCallAcceptedPromise");M(this,"iceTricklingDataChannel");M(this,"iceTricklingBuffer");this.outStreamPromise=t,this.onStateChanged=o,this.peerConnection=new RTCPeerConnection(ot);const r=c=>{this.peerConnection.setConfiguration({...ot,iceServers:c})},i=window.calls.getIceServers();typeof i=="string"?(r(JSON.parse(i)),this.setIceServersPromise=Promise.resolve()):this.setIceServersPromise=i.then(c=>{r(JSON.parse(c))}),this.state=fe.initialState,this.iceTricklingBuffer=[],this.iceTricklingDataChannel=this.peerConnection.createDataChannel("iceTrickling",{negotiated:!0,id:1}),this.iceTricklingDataChannel.onmessage=c=>{console.log("received ICE candidate from remote peer",c.data),this.peerConnection.addIceCandidate(JSON.parse(c.data))},this.iceTricklingDataChannel.onopen=()=>{console.log("iceTricklingDataChannel open: sending buffered ICE candidates",this.iceTricklingBuffer);for(const c of this.iceTricklingBuffer)it(this.iceTricklingDataChannel,c);this.iceTricklingBuffer=[]},this.peerConnection.ontrack=c=>{const h=c.streams[0];n(h),this.state="in-call",this.onStateChanged(this.state)};const l=async c=>{this.state="connecting",this.onStateChanged(this.state),await this.setIceServersPromise;const h=rt(this.peerConnection),a={type:"offer",sdp:c},m=new RTCSessionDescription(a);this.peerConnection.setRemoteDescription(m);const v=await t;console.log("getUserMedia() completed"),v.getTracks().forEach(s=>this.peerConnection.addTrack(s,v)),this.peerConnection.setLocalDescription(await this.peerConnection.createAnswer()),await h;const N=this.peerConnection.localDescription.sdp;this.peerConnection.onicecandidate=this.trickleIceOverDataChannel.bind(this),J("Answering incoming call with answer:",N),window.calls.acceptCall(N)},_=c=>{const h={type:"answer",sdp:c},a=new RTCSessionDescription(h);this.peerConnection.setRemoteDescription(a)},u=async()=>{var h;const c=decodeURIComponent(window.location.hash.substring(1));if(!c||c.length===0){console.log("empty URL hash: ",window.location.href);return}if((h=this.resolveCallAcceptedPromise)==null||h.call(this,!1),c==="startCall")console.log("URL hash CMD: ",c),await this.startCall();else if(c.startsWith("offerIncomingCall=")){const a=window.atob(c.split("offerIncomingCall=",2)[1]);J("Incoming call (with user prompt) with offer:",a),this.state="promptingUserToAcceptCall",this.onStateChanged(this.state);const m=await new Promise(v=>{const N=s=>{v(s),this.resolveCallAcceptedPromise===N&&(this.resolveCallAcceptedPromise=void 0)};this.resolveCallAcceptedPromise=N});if(console.log("Accept call prompt resolved: "+(m?"accepted":"not accepted")),!m)return;await l(a)}else if(c.startsWith("acceptCall=")){const a=window.atob(c.substring(11));J("Incoming call with offer:",a),await l(a)}else if(c.startsWith("onAnswer=")){const a=window.atob(c.substring(9));J("Outgoing call was accepted with answer:",a),_(a)}else console.log("unexpected URL hash: ",c)};u(),window.addEventListener("hashchange",u)}async startCall(){await this.setIceServersPromise;const t=rt(this.peerConnection),n=await this.outStreamPromise;console.log("getUserMedia() completed"),n.getTracks().forEach(r=>this.peerConnection.addTrack(r,n)),this.peerConnection.setLocalDescription(await this.peerConnection.createOffer()),await t;const o=this.peerConnection.localDescription.sdp;this.peerConnection.onicecandidate=this.trickleIceOverDataChannel.bind(this),J("Start outgoing call with offer:",o),window.calls.startCall(o),this.state="ringing",this.onStateChanged(this.state)}acceptCall(){if(this.resolveCallAcceptedPromise==null){console.warn("acceptCall invoked, but we were not waiting for it");return}this.resolveCallAcceptedPromise(!0)}async endCall(){var t;this.peerConnection.close(),window.calls.endCall(),(t=this.resolveCallAcceptedPromise)==null||t.call(this,!1)}getState(){return this.state}trickleIceOverDataChannel(t){if(this.iceTricklingDataChannel.readyState!=="open"){console.log("Gathered new ICE candidate, but iceTricklingDataChannel is not yet open, will buffer it",t.candidate),this.iceTricklingBuffer.push(t.candidate);return}it(this.iceTricklingDataChannel,t.candidate)}};M(fe,"initialState","connecting");let de=fe;function rt(e){(e.localDescription!=null||e.remoteDescription!=null)&&console.warn("gatheredEnoughIce called after setLocalDescription or setRemoteDescription: it might not have captured all ICE candidate events");const t=new Promise(o=>{const r=i=>{i.candidate!=null&&i.candidate.type==="relay"&&(setTimeout(o,0),e.removeEventListener("icecandidate",r))};e.addEventListener("icecandidate",r)}),n=new Promise(o=>{const r=()=>{e.iceGatheringState==="complete"&&(o(),e.removeEventListener("icegatheringstatechange",r))};e.addEventListener("icegatheringstatechange",r)});return Promise.race([t,n])}function it(e,t){console.log("sending ICE candidate to remote peer",t),e.send(JSON.stringify(t===null?t:t.toJSON()))}var gn=0;function b(e,t,n,o,r,i){t||(t={});var l,_,u=t;if("ref"in u)for(_ in u={},t)_=="ref"?l=t[_]:u[_]=t[_];var c={type:e,props:u,key:n,ref:l,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--gn,__i:-1,__u:0,__source:r,__self:i};if(typeof e=="function"&&(l=e.defaultProps))for(_ in l)u[_]===void 0&&(u[_]=l[_]);return p.vnode&&p.vnode(c),c}var at="/home/adbenitez/projects/deltachat/call/src/components/VideoThumbnail.tsx";const wn={position:"absolute",right:"15px",top:"15px",height:"100px",width:"100px",zIndex:1,imageRendering:"crisp-edges",borderRadius:"5px",boxShadow:"rgba(0, 0, 0, 0.29) 0px 2px 8px 0px, rgba(0, 0, 0, 0.28) 0px 2px 8px 0px"};function Nn({videoRef:e}){return b("div",{style:wn,children:b("video",{poster:"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",style:{borderRadius:"5px",objectFit:"cover",transform:"scaleX(-1)"},width:"100%",height:"100%",muted:!0,autoPlay:!0,playsInline:!0,ref:e},void 0,!1,{fileName:at,lineNumber:21,columnNumber:7},this)},void 0,!1,{fileName:at,lineNumber:20,columnNumber:5},this)}var lt="/home/adbenitez/projects/deltachat/call/src/components/FullscreenVideo.tsx";const kn={imageRendering:"crisp-edges",width:"100%",height:"100%"};function Cn({videoRef:e}){return b("div",{style:kn,children:b("video",{poster:"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",width:"100%",height:"100%",autoPlay:!0,playsInline:!0,ref:e},void 0,!1,{fileName:lt,lineNumber:14,columnNumber:7},this)},void 0,!1,{fileName:lt,lineNumber:13,columnNumber:5},this)}var st="/home/adbenitez/projects/deltachat/call/~icons/material-symbols/call-end.jsx";const Tn=(e,t)=>b("svg",{viewBox:"0 0 24 24",width:"1.2em",height:"1.2em",ref:t,...e,children:b("path",{fill:"currentColor",d:"M12 8q2.95 0 5.813 1.188T22.9 12.75q.3.3.3.7t-.3.7l-2.3 2.25q-.275.275-.638.3t-.662-.2l-2.9-2.2q-.2-.15-.3-.35t-.1-.45v-2.85q-.95-.3-1.95-.475T12 10t-2.05.175T8 10.65v2.85q0 .25-.1.45t-.3.35l-2.9 2.2q-.3.225-.663.2t-.637-.3l-2.3-2.25q-.3-.3-.3-.7t.3-.7q2.2-2.375 5.075-3.562T12 8"},void 0,!1,{fileName:st,lineNumber:3,columnNumber:123},void 0)},void 0,!1,{fileName:st,lineNumber:3,columnNumber:48},void 0),An=B(Tn),Sn="_btn_2u459_1",$n={btn:Sn};var En="/home/adbenitez/projects/deltachat/call/src/components/Button.tsx";function se({children:e,className:t,...n}){return b("button",{className:(t??"")+" "+$n.btn,...n,children:e},void 0,!1,{fileName:En,lineNumber:10,columnNumber:5},this)}var ct="/home/adbenitez/projects/deltachat/call/src/components/EndCallButton.tsx";const ut={background:"#f01d2c"};function Pn({...e}){return e.style={...ut,...e.style||{}},b(se,{"aria-label":"End call",title:"End call",style:ut,...e,children:b(An,{},void 0,!1,{fileName:ct,lineNumber:22,columnNumber:7},this)},void 0,!1,{fileName:ct,lineNumber:16,columnNumber:5},this)}var _t="/home/adbenitez/projects/deltachat/call/~icons/material-symbols/person.jsx";const xn=(e,t)=>b("svg",{viewBox:"0 0 24 24",width:"1.2em",height:"1.2em",ref:t,...e,children:b("path",{fill:"currentColor",d:"M12 12q-1.65 0-2.825-1.175T8 8t1.175-2.825T12 4t2.825 1.175T16 8t-1.175 2.825T12 12m-8 8v-2.8q0-.85.438-1.562T5.6 14.55q1.55-.775 3.15-1.162T12 13t3.25.388t3.15 1.162q.725.375 1.163 1.088T20 17.2V20z"},void 0,!1,{fileName:_t,lineNumber:3,columnNumber:122},void 0)},void 0,!1,{fileName:_t,lineNumber:3,columnNumber:47},void 0),In=B(xn);var On="/home/adbenitez/projects/deltachat/call/src/components/AvatarCircle.tsx";const dt={display:"inline-flex",flexDirection:"row",alignItems:"center",padding:"0.5em",color:"white",background:"#c8c7cd",borderRadius:"50%",fontSize:"1.5em"};function Rn({children:e,...t}){return t.style={...dt,...t.style||{}},b("div",{style:dt,...t,children:e},void 0,!1,{fileName:On,lineNumber:20,columnNumber:5},this)}var ft="/home/adbenitez/projects/deltachat/call/src/components/AvatarPlaceholder.tsx";function Dn({...e}){return b(Rn,{style:{padding:"0.2em",fontSize:"5em"},...e,children:b(In,{},void 0,!1,{fileName:ft,lineNumber:12,columnNumber:7},this)},void 0,!1,{fileName:ft,lineNumber:11,columnNumber:5},this)}var jn="/home/adbenitez/projects/deltachat/call/src/components/AvatarImage.tsx";function Un({url:e,...t}){return t.style={borderRadius:"50%",backgroundImage:`url(${e})`,backgroundSize:"cover",backgroundPosition:"center",...t.style||{}},b("div",{...t},void 0,!1,{fileName:jn,lineNumber:14,columnNumber:10},this)}var pt="/home/adbenitez/projects/deltachat/call/~icons/material-symbols/call.jsx";const Ln=(e,t)=>b("svg",{viewBox:"0 0 24 24",width:"1.2em",height:"1.2em",ref:t,...e,children:b("path",{fill:"currentColor",d:"M19.95 21q-3.125 0-6.175-1.362t-5.55-3.863t-3.862-5.55T3 4.05q0-.45.3-.75t.75-.3H8.1q.35 0 .625.238t.325.562l.65 3.5q.05.4-.025.675T9.4 8.45L6.975 10.9q.5.925 1.187 1.787t1.513 1.663q.775.775 1.625 1.438T13.1 17l2.35-2.35q.225-.225.588-.337t.712-.063l3.45.7q.35.1.575.363T21 15.9v4.05q0 .45-.3.75t-.75.3"},void 0,!1,{fileName:pt,lineNumber:3,columnNumber:120},void 0)},void 0,!1,{fileName:pt,lineNumber:3,columnNumber:45},void 0),Hn=B(Ln);var ht="/home/adbenitez/projects/deltachat/call/~icons/material-symbols/videocam.jsx";const qn=(e,t)=>b("svg",{viewBox:"0 0 24 24",width:"1.2em",height:"1.2em",ref:t,...e,children:b("path",{fill:"currentColor",d:"M4 20q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4h12q.825 0 1.413.588T18 6v4.5l4-4v11l-4-4V18q0 .825-.587 1.413T16 20z"},void 0,!1,{fileName:ht,lineNumber:3,columnNumber:124},void 0)},void 0,!1,{fileName:ht,lineNumber:3,columnNumber:49},void 0),Vn=B(qn);var mt="/home/adbenitez/projects/deltachat/call/~icons/material-symbols/videocam-off.jsx";const Fn=(e,t)=>b("svg",{viewBox:"0 0 24 24",width:"1.2em",height:"1.2em",ref:t,...e,children:b("path",{fill:"currentColor",d:"m22 17.5l-4-4v1.675L6.825 4H16q.825 0 1.413.588T18 6v4.5l4-4zm-1.45 5.85L.65 3.45l1.4-1.4l19.9 19.9zM4 4l14 14q0 .825-.587 1.413T16 20H4q-.825 0-1.412-.587T2 18V6q0-.825.588-1.412T4 4"},void 0,!1,{fileName:mt,lineNumber:3,columnNumber:127},void 0)},void 0,!1,{fileName:mt,lineNumber:3,columnNumber:52},void 0),Mn=B(Fn);var vt="/home/adbenitez/projects/deltachat/call/~icons/material-symbols/mic.jsx";const zn=(e,t)=>b("svg",{viewBox:"0 0 24 24",width:"1.2em",height:"1.2em",ref:t,...e,children:b("path",{fill:"currentColor",d:"M12 14q-1.25 0-2.125-.875T9 11V5q0-1.25.875-2.125T12 2t2.125.875T15 5v6q0 1.25-.875 2.125T12 14m-1 7v-3.075q-2.6-.35-4.3-2.325T5 11h2q0 2.075 1.463 3.538T12 16t3.538-1.463T17 11h2q0 2.625-1.7 4.6T13 17.925V21z"},void 0,!1,{fileName:vt,lineNumber:3,columnNumber:119},void 0)},void 0,!1,{fileName:vt,lineNumber:3,columnNumber:44},void 0),Bn=B(zn);var yt="/home/adbenitez/projects/deltachat/call/~icons/material-symbols/mic-off.jsx";const Wn=(e,t)=>b("svg",{viewBox:"0 0 24 24",width:"1.2em",height:"1.2em",ref:t,...e,children:b("path",{fill:"currentColor",d:"M17.75 14.95L16.3 13.5q.35-.575.525-1.2T17 11h2q0 1.1-.325 2.088t-.925 1.862m-2.95-3L9 6.15V5q0-1.25.875-2.125T12 2t2.125.875T15 5v6q0 .275-.062.5t-.138.45M11 21v-3.1q-2.6-.35-4.3-2.312T5 11h2q0 2.075 1.463 3.538T12 16q.85 0 1.613-.262T15 15l1.425 1.425q-.725.575-1.588.963T13 17.9V21zm8.8 1.6L1.4 4.2l1.4-1.4l18.4 18.4z"},void 0,!1,{fileName:yt,lineNumber:3,columnNumber:122},void 0)},void 0,!1,{fileName:yt,lineNumber:3,columnNumber:47},void 0),Yn=B(Wn);var P="/home/adbenitez/projects/deltachat/call/src/App.tsx";function Gn(){const[e,t]=U(re(de.initialState),"state"),n=U(Y(null),"outVidRef"),o=U(Y(null),"incVidRef"),r=U(Y(null),"disableVideoCompletelyRef");r.current==null&&(r.current=location.search.includes("disableVideoCompletely"));const i=r.current,l=U(Y(null),"enableVideoInitiallyRef");l.current==null&&(l.current=!location.search.includes("noOutgoingVideoInitially"));const _=l.current,[u,c]=U(re(!0),"isOutAudioEnabled"),[h,a]=U(re(_),"isOutVideoEnabled_"),m=i?!1:h,v=U(Y(u),"isOutAudioEnabledRef");v.current=u;const N=U(Y(m),"isOutVideoEnabledRef");N.current=m;const s=U(_e(async()=>{let w;try{w=await navigator.mediaDevices.getUserMedia({video:!i,audio:!0})}catch{console.warn("Failed to getUserMedia with video, will try just audio"),w=await navigator.mediaDevices.getUserMedia({audio:!0})}return w.getAudioTracks().forEach(E=>E.enabled=v.current),w.getVideoTracks().forEach(E=>E.enabled=N.current),w},[i]),"outStreamPromise"),[d,f]=U(re(null),"outStream");Me(()=>{let w=!1;return f(null),s.then(E=>{w||f(E)}),()=>{w=!0}},[s]),d&&n.current&&n.current.srcObject!==d&&(n.current.srcObject=d);const y=U(_e(()=>{const w=E=>{i&&(E.getVideoTracks().forEach(ne=>E.removeTrack(ne)),E.addEventListener("addtrack",ne=>{ne.track.kind==="video"&&E.removeTrack(ne.track)}));const H=o.current;H.srcObject!==E&&(H.srcObject=E);const te=()=>{H.paused?(console.log("incoming video not playing, will .play() it"),H.play()):(console.log("incoming video is playing"),clearInterval(Ht))},Ht=setInterval(te,100);te()};return new de(s,w,t)},[s,i]),"manager");Me(()=>{if(d==null)return;const w=()=>{d.getAudioTracks().forEach(E=>E.enabled=u),d.getVideoTracks().forEach(E=>E.enabled=m)};return w(),d.addEventListener("addtrack",w),d.addEventListener("removetrack",w),()=>{d.removeEventListener("addtrack",w),d.removeEventListener("removetrack",w)}},[d,u,m]);const k=!i&&(d==null||d.getVideoTracks().length>=1),g=e==="promptingUserToAcceptCall"?()=>y.acceptCall():null,A=Zt(()=>{y.endCall()},[y]);let S;switch(e){case"promptingUserToAcceptCall":S="Incoming call";break;case"connecting":S="Connecting...";break;case"ringing":S="Ringing...";break;case"in-call":S="";break}const D=e==="in-call",j={display:D?"block":"none",height:"100%"},I=u?"Mute microphone":"Unmute microphone",O=m?"Stop camera":"Start camera",C={color:"white",borderRadius:"50%",fontSize:"1.5em",margin:"0.25em 0.625em"};return b("div",{style:{height:"100vh",overflow:"hidden"},children:[b("div",{style:j,children:[b(Cn,{videoRef:o},void 0,!1,{fileName:P,lineNumber:205,columnNumber:9},this),b(Nn,{videoRef:n},void 0,!1,{fileName:P,lineNumber:206,columnNumber:9},this)]},void 0,!0,{fileName:P,lineNumber:204,columnNumber:7},this),b("div",{role:"status",style:{position:"absolute",top:0,width:"100%",paddingTop:"1em",textAlign:"center"},children:S},void 0,!1,{fileName:P,lineNumber:209,columnNumber:7},this),b("div",{style:{display:D?"none":"flex",alignItems:"center",textAlign:"center",justifyContent:"center",height:"100%"},children:b("div",{style:{position:"relative"},children:[b(Dn,{},void 0,!1,{fileName:P,lineNumber:231,columnNumber:11},this),window.calls.getAvatar&&b(Un,{url:window.calls.getAvatar(),style:{position:"absolute",inset:0}},void 0,!1,{fileName:P,lineNumber:233,columnNumber:13},this)]},void 0,!0,{fileName:P,lineNumber:230,columnNumber:9},this)},void 0,!1,{fileName:P,lineNumber:221,columnNumber:7},this),b("div",{style:{position:"absolute",bottom:"0.75em",width:"100%",textAlign:"center"},children:[g!=null&&b(se,{"aria-label":"Answer call",title:"Answer call",onClick:g,className:"acceptCallButton",style:{backgroundColor:"#00b000",...C},children:b(Hn,{},void 0,!1,{fileName:P,lineNumber:259,columnNumber:13},this)},void 0,!1,{fileName:P,lineNumber:249,columnNumber:11},this),b(se,{"aria-label":I,title:I,onClick:()=>c(w=>!w),style:C,children:u?b(Bn,{},void 0,!1,{fileName:P,lineNumber:269,columnNumber:13},this):b(Yn,{},void 0,!1,{fileName:P,lineNumber:271,columnNumber:13},this)},void 0,!1,{fileName:P,lineNumber:262,columnNumber:9},this),k&&b(se,{"aria-label":O,title:O,onClick:()=>a(w=>!w),style:C,children:m?b(Vn,{},void 0,!1,{fileName:P,lineNumber:282,columnNumber:15},this):b(Mn,{},void 0,!1,{fileName:P,lineNumber:284,columnNumber:15},this)},void 0,!1,{fileName:P,lineNumber:275,columnNumber:11},this),b(Pn,{onClick:A,style:C},void 0,!1,{fileName:P,lineNumber:288,columnNumber:9},this)]},void 0,!0,{fileName:P,lineNumber:240,columnNumber:7},this)]},void 0,!0,{fileName:P,lineNumber:203,columnNumber:5},this)}var Jn="/home/adbenitez/projects/deltachat/call/src/index.tsx";Yt(b(Gn,{},void 0,!1,{fileName:Jn,lineNumber:4,columnNumber:8},void 0),document.getElementById("root"));