@sphoro/bugcatch-web-sdk 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,7 +55,7 @@ BugCatch.init({
55
55
  ```html
56
56
  <!-- Pin the version. Without one the CDN serves whatever is latest, so a
57
57
  future release changes behaviour on a site nobody redeployed. -->
58
- <script src="https://unpkg.com/@sphoro/bugcatch-web-sdk@0.19.0/dist/bugcatch.umd.js"></script>
58
+ <script src="https://unpkg.com/@sphoro/bugcatch-web-sdk@0.20.0/dist/bugcatch.umd.js"></script>
59
59
  <script>
60
60
  BugCatch.init({ apiBase: '…', apiKey: 'bc_live_…', projectId: '…' });
61
61
  </script>
@@ -731,6 +731,21 @@ tells them it was fixed, so whichever they answer is the one that counts.
731
731
  Rating again replaces the earlier score. Whether a project asks at all is
732
732
  **Project Settings → Resolutions → Ask the reporter to rate it**, on by default.
733
733
 
734
+ The reporter does not have to go looking for it. The next time they open the
735
+ widget, the latest report settled for them in the last 30 days waits above the
736
+ form as a **How did we do?** card: one tap on a star rates it. How firmly it
737
+ asks is **Project Settings → Resolutions → Where the widget asks**:
738
+
739
+ | Setting | The first screen |
740
+ | --- | --- |
741
+ | Only on the report | Nothing. The stars are on the report's own screen, under Your reports. |
742
+ | When they next open the widget (default) | The card, with **Not now**, which hides that report's card on this device. |
743
+ | Before they can report again | The card, and Send and Talk to the team wait until they have rated. One rating unlocks the form; if the rating cannot be sent, **Skip for now** appears so an outage never blocks a report. |
744
+
745
+ `myReports()` rows carry it as `ratingDue`: `'ask'`, `'require'` or `null`,
746
+ with `resolvedAt` beside it. Only the widget's own form is held —
747
+ `BugCatch.report()` from your code never is.
748
+
734
749
  To drive it from your own UI:
735
750
 
736
751
  ```js
@@ -1,2 +1,2 @@
1
- (function(){"use strict";function it(e=8e3){const r=window.AudioContext||window.webkitAudioContext;try{return new r({sampleRate:e})}catch{return new r}}async function st(e){if(e.state==="suspended")try{await e.resume()}catch{}}function lt(e,r,o){const a=r/o,s=new Float32Array(Math.floor(e.length/a));for(let f=0;f<s.length;f++){const l=Math.floor(f*a),m=Math.min(Math.floor((f+1)*a),e.length);let g=0;for(let i=l;i<m;i++)g+=e[i];s[f]=m>l?g/(m-l):0}return s}const ut=132,j=32635;function ft(e){const r=new Uint8Array(e.length);for(let o=0;o<e.length;o++){const a=Math.max(-1,Math.min(1,e[o]));let s=Math.round(a*32767);const f=s<0?128:0;f&&(s=-s),s>j&&(s=j),s+=ut;let l=7;for(let g=16384;!(s&g)&&l>0;l--,g>>=1);const m=s>>l+3&15;r[o]=~(f|l<<4|m)&255}return r}const dt=512;function pt(e,r,o,a=8e3){const s=e.createMediaStreamSource(r),f=e.createScriptProcessor(dt,1,1);f.onaudioprocess=m=>{const g=m.inputBuffer.getChannelData(0),i=e.sampleRate===a?g:lt(g,e.sampleRate,a);o(ft(i))},s.connect(f);const l=e.createGain();return l.gain.value=0,f.connect(l),l.connect(e.destination),{stop(){f.onaudioprocess=null;try{s.disconnect()}catch{}try{f.disconnect()}catch{}try{l.disconnect()}catch{}}}}const mt="voiceai.realtime.v1",yt=[{urls:"stun:stun.l.google.com:19302"}];function z(){return navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:1}})}function F(){var e;return typeof window<"u"&&typeof window.RTCPeerConnection=="function"&&!!((e=navigator.mediaDevices)!=null&&e.getUserMedia)}async function gt({realtimeUrl:e,stream:r,ringsUntil:o,onState:a,onAudioBlocked:s,onMicrophone:f}){const l=(t,n)=>{try{a==null||a(t,n)}catch{}},m=t=>{try{s==null||s(t)}catch{}},g=t=>{try{f==null||f(t)}catch{}};if(!F()){const t=new Error("[BugCatch] this browser cannot make live calls.");throw l("failed",{reason:"unsupported"}),t}let i=r;if(!i)try{i=await z()}catch(t){throw l("failed",{reason:"microphone",error:String((t==null?void 0:t.name)||t)}),t}let y;try{y=await ht(e)}catch(t){throw W(i),l("failed",{reason:"connect"}),t}let c=null,u=null,p=!1,w=null,h=null,E=null,S=!1,b=null,C=null,O=!1;const x=[];let M=!1,D=!1,P=!1,R=null,I=null,B=0;const Ot=2e3,K=5e3,_t=3e4,At=4,k=(t,n)=>{if(!p){p=!0,w&&(clearTimeout(w),w=null),et(),C==null||C(),C=null,Mt(),b==null||b(),b=null;try{c==null||c.close()}catch{}W(i),u&&(u.srcObject=null,u.remove(),u=null);try{y.readyState===WebSocket.OPEN&&y.close(1e3,"call over")}catch{}l(t,n)}},_=t=>{y.readyState===WebSocket.OPEN&&y.send(JSON.stringify(t))},q=async()=>{if(O||E||p||!h||!h.audio&&!h.transcript)return;O=!0;const t=h.encoding||"mulaw";if(t!=="mulaw"){V(`this call is kept as ${t}, which this SDK cannot produce.`);return}const n=Number(h.sample_rate)||8e3;try{const d=it(n);if(await st(d),p){try{d.close()}catch{}return}const v=pt(d,i,T=>{y.readyState===WebSocket.OPEN&&y.send(T)},n);E={context:d,tap:v}}catch(d){V(`could not send the copy this call is keeping: ${String((d==null?void 0:d.message)||d)}`)}};function Mt(){if(O=!1,!E)return;const{context:t,tap:n}=E;E=null;try{n.stop()}catch{}try{t.close()}catch{}}function X(){var n;if(!u||p)return;let t;try{t=(n=u.play)==null?void 0:n.call(u)}catch{Q();return}if(!t||typeof t.then!="function"){H();return}t.then(H,Q)}function H(){b==null||b(),b=null,S&&(S=!1,m(!1))}function Q(){p||(S||(S=!0,m(!0)),It())}function It(){if(b||typeof window>"u"||typeof window.addEventListener!="function")return;const t=()=>X(),n=["pointerdown","keydown","touchstart"];for(const d of n)window.addEventListener(d,t,{capture:!0,passive:!0});b=()=>{for(const d of n)try{window.removeEventListener(d,t,{capture:!0})}catch{}}}const $t=t=>{c=new RTCPeerConnection({iceServers:t!=null&&t.length?t:yt});for(const n of i.getAudioTracks())c.addTrack(n,i);C=Nt(),c.onicecandidate=n=>{n.candidate&&_({type:"signal",signal:{kind:"candidate",payload:n.candidate.toJSON()}})},c.ontrack=n=>{var v;const[d]=n.streams;d&&(u||(u=document.createElement("audio"),u.autoplay=!0,u.playsInline=!0,(v=u.setAttribute)==null||v.call(u,"playsinline",""),u.style.cssText="position:fixed;width:0;height:0;opacity:0;pointer-events:none",document.body.appendChild(u)),u.srcObject=d,X())},c.onconnectionstatechange=Z,c.oniceconnectionstatechange=Z};function Z(){if(!c||p)return;const t=c.connectionState||c.iceConnectionState;if(t==="connected"||t==="completed"){D=!0,B=0,et(),P=!1,l("connected");return}if(t==="disconnected"){if(!D)return;tt(Ot);return}if(t==="failed"){if(!D){k("failed",{reason:"ice"});return}tt(0)}}function tt(t){p||(P||(P=!0,l("reconnecting"),I=setTimeout(()=>k("failed",{reason:"network"}),_t)),!R&&(R=setTimeout(U,t)))}function et(){R&&(clearTimeout(R),R=null),I&&(clearTimeout(I),I=null)}async function U(){if(R=null,p||!c)return;const t=c.connectionState||c.iceConnectionState;if(!(t==="connected"||t==="completed")){if(!M){_({type:"signal",signal:{kind:"restart",payload:{}}}),R=setTimeout(U,K);return}B>=At||(B+=1,await nt(),R=setTimeout(U,K))}}async function nt(){if(!(p||!c))try{const t=await c.createOffer({iceRestart:!0});await c.setLocalDescription(t),_({type:"signal",signal:{kind:"offer",payload:c.localDescription.toJSON()}})}catch{}}function Nt(){let n=null,d=!1;const v=T=>{if(n&&(clearTimeout(n),n=null),T){if(!d)return;d=!1,g(!0);return}d||(n=setTimeout(()=>{n=null,!p&&(d=!0,g(!1))},600))};for(const T of i.getAudioTracks())T.onmute=()=>v(!1),T.onunmute=()=>v(!0),T.onended=()=>{n&&(clearTimeout(n),n=null),!d&&(d=!0,g(!1))};return()=>{n&&(clearTimeout(n),n=null);for(const T of i.getAudioTracks())T.onmute=null,T.onunmute=null,T.onended=null}}const Lt=async()=>{try{const t=await c.createOffer();await c.setLocalDescription(t),_({type:"signal",signal:{kind:"offer",payload:c.localDescription.toJSON()}})}catch{k("failed",{reason:"negotiation"})}},Dt=async t=>{try{await c.setRemoteDescription(new RTCSessionDescription(t));const n=await c.createAnswer();await c.setLocalDescription(n),_({type:"signal",signal:{kind:"answer",payload:c.localDescription.toJSON()}}),await ot()}catch{k("failed",{reason:"negotiation"})}},ot=async()=>{for(;x.length;){const t=x.shift();try{await c.addIceCandidate(new RTCIceCandidate(t))}catch{}}};let rt=Promise.resolve();y.onmessage=t=>{rt=rt.then(()=>Pt(t)).catch(()=>{})};const Pt=async t=>{var d,v,T,at,ct;if(typeof t.data!="string")return;let n;try{n=JSON.parse(t.data)}catch{return}switch(n.type){case"session.created":{if($t((d=n.data)==null?void 0:d.ice_servers),h=((v=n.data)==null?void 0:v.capture)||null,(T=n.data)!=null&&T.peer_present){l("connecting"),q();break}l("ringing"),Bt();break}case"peer.joined":{w&&(clearTimeout(w),w=null),l("connecting"),M=!!((at=n.data)!=null&&at.should_offer),M&&await Lt(),q();break}case"signal":{if(!c)break;const{kind:$,payload:N}=n.data||{};if($==="offer")await Dt(N);else if($==="answer")try{await c.setRemoteDescription(new RTCSessionDescription(N)),await ot()}catch{k("failed",{reason:"negotiation"})}else if($==="candidate")if(c.remoteDescription)try{await c.addIceCandidate(new RTCIceCandidate(N))}catch{}else x.push(N);else $==="restart"&&M&&await nt();break}case"peer.left":k("ended",{reason:"peer_left"});break;case"error":k("failed",{reason:"server",detail:(ct=n.error)==null?void 0:ct.detail});break;case"session.ended":k("ended",{reason:"server"});break}};y.onclose=()=>k("ended",{reason:"disconnected"}),y.onerror=()=>k("failed",{reason:"socket"});function Bt(){if(!o)return;const t=new Date(o).getTime()-Date.now();Number.isFinite(t)&&(w=setTimeout(()=>k("missed"),Math.max(0,t)))}return{hangUp(){_({type:"session.end"}),k("ended",{reason:"hung_up"})},setMuted(t){for(const n of i.getAudioTracks())n.enabled=!t;return t},isMuted(){return i.getAudioTracks().every(t=>!t.enabled)}}}function ht(e){return new Promise((r,o)=>{let a;try{a=new WebSocket(e,mt)}catch(s){o(s);return}a.onopen=()=>{a.onopen=null,a.onerror=null,r(a)},a.onerror=()=>{a.onopen=null,a.onerror=null,o(new Error("[BugCatch] could not connect the call."))}})}function V(e){try{console.warn(`[BugCatch] ${e}`)}catch{}}function W(e){var r;for(const o of((r=e==null?void 0:e.getTracks)==null?void 0:r.call(e))??[])try{o.stop()}catch{}}const J="#0e0e10",L="#ffffff";function wt(e){const r=bt(e);if(!r)return L;const[o,a,s]=r.map(l=>{const m=l/255;return m<=.03928?m/12.92:((m+.055)/1.055)**2.4});return .2126*o+.7152*a+.0722*s>.179?J:L}function bt(e){const r=String(e||"").trim();let o=/^#([0-9a-f]{3})$/i.exec(r);return o?[...o[1]].map(a=>parseInt(a+a,16)):(o=/^#([0-9a-f]{6})$/i.exec(r),o?[0,2,4].map(a=>parseInt(o[1].slice(a,a+2),16)):(o=/^rgba?\(\s*(\d+)[\s,]+(\d+)[\s,]+(\d+)/i.exec(r),o?[o[1],o[2],o[3]].map(Number):null))}const A={cycleMs:3e3,peak:.045,bursts:[{at:0,seconds:.4,hz:[440,660]},{at:.55,seconds:.4,hz:[440,660]}]};function Tt(){var e;try{return!!((e=navigator.userActivation)!=null&&e.hasBeenActive)}catch{return!1}}function kt(e){if(!e()&&!Tt())return()=>{};const r=typeof window<"u"&&(window.AudioContext||window.webkitAudioContext);if(!r)return()=>{};let o;try{o=new r}catch{return()=>{}}let a=!1,s=null;const f=[],l=({at:i,seconds:y,hz:c})=>{const u=o.currentTime+i,p=o.createGain();p.connect(o.destination),p.gain.setValueAtTime(0,u),p.gain.linearRampToValueAtTime(A.peak,u+.02),p.gain.setValueAtTime(A.peak,u+y-.06),p.gain.linearRampToValueAtTime(0,u+y);for(const w of c){const h=o.createOscillator();h.type="sine",h.frequency.value=w,h.connect(p),h.start(u),h.stop(u+y+.02),f.push(h)}},m=()=>{if(!a)try{A.bursts.forEach(l)}catch{}},g=()=>{a||(m(),s=setInterval(m,A.cycleMs))};return o.state==="running"?g():o.resume().then(g).catch(()=>{}),()=>{a=!0,s&&clearInterval(s);for(const i of f)try{i.stop()}catch{}try{o.close()}catch{}}}function xt(e){const r=Date.parse(e||"");return Number.isNaN(r)?0:Math.max(0,Math.round((r-Date.now())/1e3))}const Y=["flex:1","padding:9px 12px","border:0","border-radius:999px","font:560 13px/1.4 inherit","cursor:pointer"].join(";");function Ct({call:e,accent:r=null,position:o="bottom-right",onAnswer:a,onDecline:s,onExpire:f,touched:l=()=>!1}){if(typeof document>"u"||!document.body)return()=>{};const[m,g]=String(o).split("-"),i=document.createElement("div");i.setAttribute("role","alertdialog"),i.setAttribute("aria-live","assertive"),i.setAttribute("aria-label",`${e.from||"Support"} is calling about ${e.reference}`),i.style.cssText=["position:fixed",`${m==="top"?"top":"bottom"}:20px`,`${g==="left"?"left":"right"}:20px`,"z-index:2147483647","width:300px","max-width:calc(100vw - 40px)","padding:16px","border-radius:16px","background:#111113","color:#f3f2ef",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',`box-shadow:0 0 0 1px ${r?`color-mix(in srgb, ${r} 55%, transparent)`:"rgba(255,255,255,.12)"},0 24px 50px -12px rgba(0,0,0,.6)`,"opacity:0","transform:translateY(8px)","transition:opacity .2s ease,transform .2s ease"].join(";");const y=document.createElement("div");y.style.cssText="font-weight:600;font-size:14px;margin-bottom:2px",y.textContent=`${e.from||"Support"} is calling`;const c=document.createElement("div");c.style.cssText="color:#b3b0aa;margin-bottom:10px",c.textContent=e.project?`About your report ${e.reference} · ${e.project}`:`About your report ${e.reference}`;const u=document.createElement("div");u.style.cssText="color:#8f8c86;font-size:12px;margin-bottom:10px";const p=document.createElement("button");p.type="button",p.textContent="Answer",p.style.cssText=`${Y};background:${r||L};color:${r?wt(r):J}`;const w=document.createElement("button");w.type="button",w.textContent="Not now",w.style.cssText=`${Y};background:rgba(255,255,255,.08);color:#f3f2ef`;const h=document.createElement("div");if(h.style.cssText="display:flex;gap:8px",h.append(p,w),i.append(y,c,u),e.recorded){const x=document.createElement("div");x.style.cssText="color:#8f8c86;font-size:12px;margin-bottom:10px",x.textContent="This call will be recorded.",i.append(x)}i.append(h),document.body.appendChild(i);const E=kt(l);let S=!1,b=null;const C=()=>{S||(S=!0,b&&clearInterval(b),E(),i.style.opacity="0",i.style.transform="translateY(8px)",setTimeout(()=>i.remove(),250))},O=()=>{const x=xt(e.ringsUntil);if(u.textContent=x?`Ringing — ${x}s`:"The call has stopped ringing.",!x){C();try{f==null||f()}catch{}}};return O(),b=setInterval(O,1e3),p.addEventListener("click",()=>{C();try{a==null||a()}catch{}}),w.addEventListener("click",()=>{C();try{s==null||s()}catch{}}),requestAnimationFrame(()=>{i.style.opacity="1",i.style.transform="translateY(0)"}),C}const vt=Object.freeze(Object.defineProperty({__proto__:null,joinLiveCall:gt,liveCallSupported:F,openMicrophone:z,showIncomingCall:Ct},Symbol.toStringTag,{value:"Module"})),Rt="0.19.0",G="__bugcatchChunks",Et=e=>`${e}@${Rt}`;function St(e,r){const o=window[G]||(window[G]={});o[Et(e)]=r}St("call",vt)})();
1
+ (function(){"use strict";function it(e=8e3){const r=window.AudioContext||window.webkitAudioContext;try{return new r({sampleRate:e})}catch{return new r}}async function st(e){if(e.state==="suspended")try{await e.resume()}catch{}}function lt(e,r,o){const a=r/o,s=new Float32Array(Math.floor(e.length/a));for(let f=0;f<s.length;f++){const l=Math.floor(f*a),m=Math.min(Math.floor((f+1)*a),e.length);let g=0;for(let i=l;i<m;i++)g+=e[i];s[f]=m>l?g/(m-l):0}return s}const ut=132,j=32635;function ft(e){const r=new Uint8Array(e.length);for(let o=0;o<e.length;o++){const a=Math.max(-1,Math.min(1,e[o]));let s=Math.round(a*32767);const f=s<0?128:0;f&&(s=-s),s>j&&(s=j),s+=ut;let l=7;for(let g=16384;!(s&g)&&l>0;l--,g>>=1);const m=s>>l+3&15;r[o]=~(f|l<<4|m)&255}return r}const dt=512;function pt(e,r,o,a=8e3){const s=e.createMediaStreamSource(r),f=e.createScriptProcessor(dt,1,1);f.onaudioprocess=m=>{const g=m.inputBuffer.getChannelData(0),i=e.sampleRate===a?g:lt(g,e.sampleRate,a);o(ft(i))},s.connect(f);const l=e.createGain();return l.gain.value=0,f.connect(l),l.connect(e.destination),{stop(){f.onaudioprocess=null;try{s.disconnect()}catch{}try{f.disconnect()}catch{}try{l.disconnect()}catch{}}}}const mt="voiceai.realtime.v1",yt=[{urls:"stun:stun.l.google.com:19302"}];function z(){return navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:1}})}function F(){var e;return typeof window<"u"&&typeof window.RTCPeerConnection=="function"&&!!((e=navigator.mediaDevices)!=null&&e.getUserMedia)}async function gt({realtimeUrl:e,stream:r,ringsUntil:o,onState:a,onAudioBlocked:s,onMicrophone:f}){const l=(t,n)=>{try{a==null||a(t,n)}catch{}},m=t=>{try{s==null||s(t)}catch{}},g=t=>{try{f==null||f(t)}catch{}};if(!F()){const t=new Error("[BugCatch] this browser cannot make live calls.");throw l("failed",{reason:"unsupported"}),t}let i=r;if(!i)try{i=await z()}catch(t){throw l("failed",{reason:"microphone",error:String((t==null?void 0:t.name)||t)}),t}let y;try{y=await ht(e)}catch(t){throw W(i),l("failed",{reason:"connect"}),t}let c=null,u=null,p=!1,w=null,h=null,E=null,S=!1,b=null,C=null,O=!1;const x=[];let M=!1,D=!1,P=!1,R=null,I=null,B=0;const Ot=2e3,K=5e3,_t=3e4,At=4,k=(t,n)=>{if(!p){p=!0,w&&(clearTimeout(w),w=null),et(),C==null||C(),C=null,Mt(),b==null||b(),b=null;try{c==null||c.close()}catch{}W(i),u&&(u.srcObject=null,u.remove(),u=null);try{y.readyState===WebSocket.OPEN&&y.close(1e3,"call over")}catch{}l(t,n)}},_=t=>{y.readyState===WebSocket.OPEN&&y.send(JSON.stringify(t))},q=async()=>{if(O||E||p||!h||!h.audio&&!h.transcript)return;O=!0;const t=h.encoding||"mulaw";if(t!=="mulaw"){V(`this call is kept as ${t}, which this SDK cannot produce.`);return}const n=Number(h.sample_rate)||8e3;try{const d=it(n);if(await st(d),p){try{d.close()}catch{}return}const v=pt(d,i,T=>{y.readyState===WebSocket.OPEN&&y.send(T)},n);E={context:d,tap:v}}catch(d){V(`could not send the copy this call is keeping: ${String((d==null?void 0:d.message)||d)}`)}};function Mt(){if(O=!1,!E)return;const{context:t,tap:n}=E;E=null;try{n.stop()}catch{}try{t.close()}catch{}}function X(){var n;if(!u||p)return;let t;try{t=(n=u.play)==null?void 0:n.call(u)}catch{Q();return}if(!t||typeof t.then!="function"){H();return}t.then(H,Q)}function H(){b==null||b(),b=null,S&&(S=!1,m(!1))}function Q(){p||(S||(S=!0,m(!0)),It())}function It(){if(b||typeof window>"u"||typeof window.addEventListener!="function")return;const t=()=>X(),n=["pointerdown","keydown","touchstart"];for(const d of n)window.addEventListener(d,t,{capture:!0,passive:!0});b=()=>{for(const d of n)try{window.removeEventListener(d,t,{capture:!0})}catch{}}}const $t=t=>{c=new RTCPeerConnection({iceServers:t!=null&&t.length?t:yt});for(const n of i.getAudioTracks())c.addTrack(n,i);C=Nt(),c.onicecandidate=n=>{n.candidate&&_({type:"signal",signal:{kind:"candidate",payload:n.candidate.toJSON()}})},c.ontrack=n=>{var v;const[d]=n.streams;d&&(u||(u=document.createElement("audio"),u.autoplay=!0,u.playsInline=!0,(v=u.setAttribute)==null||v.call(u,"playsinline",""),u.style.cssText="position:fixed;width:0;height:0;opacity:0;pointer-events:none",document.body.appendChild(u)),u.srcObject=d,X())},c.onconnectionstatechange=Z,c.oniceconnectionstatechange=Z};function Z(){if(!c||p)return;const t=c.connectionState||c.iceConnectionState;if(t==="connected"||t==="completed"){D=!0,B=0,et(),P=!1,l("connected");return}if(t==="disconnected"){if(!D)return;tt(Ot);return}if(t==="failed"){if(!D){k("failed",{reason:"ice"});return}tt(0)}}function tt(t){p||(P||(P=!0,l("reconnecting"),I=setTimeout(()=>k("failed",{reason:"network"}),_t)),!R&&(R=setTimeout(U,t)))}function et(){R&&(clearTimeout(R),R=null),I&&(clearTimeout(I),I=null)}async function U(){if(R=null,p||!c)return;const t=c.connectionState||c.iceConnectionState;if(!(t==="connected"||t==="completed")){if(!M){_({type:"signal",signal:{kind:"restart",payload:{}}}),R=setTimeout(U,K);return}B>=At||(B+=1,await nt(),R=setTimeout(U,K))}}async function nt(){if(!(p||!c))try{const t=await c.createOffer({iceRestart:!0});await c.setLocalDescription(t),_({type:"signal",signal:{kind:"offer",payload:c.localDescription.toJSON()}})}catch{}}function Nt(){let n=null,d=!1;const v=T=>{if(n&&(clearTimeout(n),n=null),T){if(!d)return;d=!1,g(!0);return}d||(n=setTimeout(()=>{n=null,!p&&(d=!0,g(!1))},600))};for(const T of i.getAudioTracks())T.onmute=()=>v(!1),T.onunmute=()=>v(!0),T.onended=()=>{n&&(clearTimeout(n),n=null),!d&&(d=!0,g(!1))};return()=>{n&&(clearTimeout(n),n=null);for(const T of i.getAudioTracks())T.onmute=null,T.onunmute=null,T.onended=null}}const Lt=async()=>{try{const t=await c.createOffer();await c.setLocalDescription(t),_({type:"signal",signal:{kind:"offer",payload:c.localDescription.toJSON()}})}catch{k("failed",{reason:"negotiation"})}},Dt=async t=>{try{await c.setRemoteDescription(new RTCSessionDescription(t));const n=await c.createAnswer();await c.setLocalDescription(n),_({type:"signal",signal:{kind:"answer",payload:c.localDescription.toJSON()}}),await ot()}catch{k("failed",{reason:"negotiation"})}},ot=async()=>{for(;x.length;){const t=x.shift();try{await c.addIceCandidate(new RTCIceCandidate(t))}catch{}}};let rt=Promise.resolve();y.onmessage=t=>{rt=rt.then(()=>Pt(t)).catch(()=>{})};const Pt=async t=>{var d,v,T,at,ct;if(typeof t.data!="string")return;let n;try{n=JSON.parse(t.data)}catch{return}switch(n.type){case"session.created":{if($t((d=n.data)==null?void 0:d.ice_servers),h=((v=n.data)==null?void 0:v.capture)||null,(T=n.data)!=null&&T.peer_present){l("connecting"),q();break}l("ringing"),Bt();break}case"peer.joined":{w&&(clearTimeout(w),w=null),l("connecting"),M=!!((at=n.data)!=null&&at.should_offer),M&&await Lt(),q();break}case"signal":{if(!c)break;const{kind:$,payload:N}=n.data||{};if($==="offer")await Dt(N);else if($==="answer")try{await c.setRemoteDescription(new RTCSessionDescription(N)),await ot()}catch{k("failed",{reason:"negotiation"})}else if($==="candidate")if(c.remoteDescription)try{await c.addIceCandidate(new RTCIceCandidate(N))}catch{}else x.push(N);else $==="restart"&&M&&await nt();break}case"peer.left":k("ended",{reason:"peer_left"});break;case"error":k("failed",{reason:"server",detail:(ct=n.error)==null?void 0:ct.detail});break;case"session.ended":k("ended",{reason:"server"});break}};y.onclose=()=>k("ended",{reason:"disconnected"}),y.onerror=()=>k("failed",{reason:"socket"});function Bt(){if(!o)return;const t=new Date(o).getTime()-Date.now();Number.isFinite(t)&&(w=setTimeout(()=>k("missed"),Math.max(0,t)))}return{hangUp(){_({type:"session.end"}),k("ended",{reason:"hung_up"})},setMuted(t){for(const n of i.getAudioTracks())n.enabled=!t;return t},isMuted(){return i.getAudioTracks().every(t=>!t.enabled)}}}function ht(e){return new Promise((r,o)=>{let a;try{a=new WebSocket(e,mt)}catch(s){o(s);return}a.onopen=()=>{a.onopen=null,a.onerror=null,r(a)},a.onerror=()=>{a.onopen=null,a.onerror=null,o(new Error("[BugCatch] could not connect the call."))}})}function V(e){try{console.warn(`[BugCatch] ${e}`)}catch{}}function W(e){var r;for(const o of((r=e==null?void 0:e.getTracks)==null?void 0:r.call(e))??[])try{o.stop()}catch{}}const J="#0e0e10",L="#ffffff";function wt(e){const r=bt(e);if(!r)return L;const[o,a,s]=r.map(l=>{const m=l/255;return m<=.03928?m/12.92:((m+.055)/1.055)**2.4});return .2126*o+.7152*a+.0722*s>.179?J:L}function bt(e){const r=String(e||"").trim();let o=/^#([0-9a-f]{3})$/i.exec(r);return o?[...o[1]].map(a=>parseInt(a+a,16)):(o=/^#([0-9a-f]{6})$/i.exec(r),o?[0,2,4].map(a=>parseInt(o[1].slice(a,a+2),16)):(o=/^rgba?\(\s*(\d+)[\s,]+(\d+)[\s,]+(\d+)/i.exec(r),o?[o[1],o[2],o[3]].map(Number):null))}const A={cycleMs:3e3,peak:.045,bursts:[{at:0,seconds:.4,hz:[440,660]},{at:.55,seconds:.4,hz:[440,660]}]};function Tt(){var e;try{return!!((e=navigator.userActivation)!=null&&e.hasBeenActive)}catch{return!1}}function kt(e){if(!e()&&!Tt())return()=>{};const r=typeof window<"u"&&(window.AudioContext||window.webkitAudioContext);if(!r)return()=>{};let o;try{o=new r}catch{return()=>{}}let a=!1,s=null;const f=[],l=({at:i,seconds:y,hz:c})=>{const u=o.currentTime+i,p=o.createGain();p.connect(o.destination),p.gain.setValueAtTime(0,u),p.gain.linearRampToValueAtTime(A.peak,u+.02),p.gain.setValueAtTime(A.peak,u+y-.06),p.gain.linearRampToValueAtTime(0,u+y);for(const w of c){const h=o.createOscillator();h.type="sine",h.frequency.value=w,h.connect(p),h.start(u),h.stop(u+y+.02),f.push(h)}},m=()=>{if(!a)try{A.bursts.forEach(l)}catch{}},g=()=>{a||(m(),s=setInterval(m,A.cycleMs))};return o.state==="running"?g():o.resume().then(g).catch(()=>{}),()=>{a=!0,s&&clearInterval(s);for(const i of f)try{i.stop()}catch{}try{o.close()}catch{}}}function xt(e){const r=Date.parse(e||"");return Number.isNaN(r)?0:Math.max(0,Math.round((r-Date.now())/1e3))}const Y=["flex:1","padding:9px 12px","border:0","border-radius:999px","font:560 13px/1.4 inherit","cursor:pointer"].join(";");function Ct({call:e,accent:r=null,position:o="bottom-right",onAnswer:a,onDecline:s,onExpire:f,touched:l=()=>!1}){if(typeof document>"u"||!document.body)return()=>{};const[m,g]=String(o).split("-"),i=document.createElement("div");i.setAttribute("role","alertdialog"),i.setAttribute("aria-live","assertive"),i.setAttribute("aria-label",`${e.from||"Support"} is calling about ${e.reference}`),i.style.cssText=["position:fixed",`${m==="top"?"top":"bottom"}:20px`,`${g==="left"?"left":"right"}:20px`,"z-index:2147483647","width:300px","max-width:calc(100vw - 40px)","padding:16px","border-radius:16px","background:#111113","color:#f3f2ef",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',`box-shadow:0 0 0 1px ${r?`color-mix(in srgb, ${r} 55%, transparent)`:"rgba(255,255,255,.12)"},0 24px 50px -12px rgba(0,0,0,.6)`,"opacity:0","transform:translateY(8px)","transition:opacity .2s ease,transform .2s ease"].join(";");const y=document.createElement("div");y.style.cssText="font-weight:600;font-size:14px;margin-bottom:2px",y.textContent=`${e.from||"Support"} is calling`;const c=document.createElement("div");c.style.cssText="color:#b3b0aa;margin-bottom:10px",c.textContent=e.project?`About your report ${e.reference} · ${e.project}`:`About your report ${e.reference}`;const u=document.createElement("div");u.style.cssText="color:#8f8c86;font-size:12px;margin-bottom:10px";const p=document.createElement("button");p.type="button",p.textContent="Answer",p.style.cssText=`${Y};background:${r||L};color:${r?wt(r):J}`;const w=document.createElement("button");w.type="button",w.textContent="Not now",w.style.cssText=`${Y};background:rgba(255,255,255,.08);color:#f3f2ef`;const h=document.createElement("div");if(h.style.cssText="display:flex;gap:8px",h.append(p,w),i.append(y,c,u),e.recorded){const x=document.createElement("div");x.style.cssText="color:#8f8c86;font-size:12px;margin-bottom:10px",x.textContent="This call will be recorded.",i.append(x)}i.append(h),document.body.appendChild(i);const E=kt(l);let S=!1,b=null;const C=()=>{S||(S=!0,b&&clearInterval(b),E(),i.style.opacity="0",i.style.transform="translateY(8px)",setTimeout(()=>i.remove(),250))},O=()=>{const x=xt(e.ringsUntil);if(u.textContent=x?`Ringing — ${x}s`:"The call has stopped ringing.",!x){C();try{f==null||f()}catch{}}};return O(),b=setInterval(O,1e3),p.addEventListener("click",()=>{C();try{a==null||a()}catch{}}),w.addEventListener("click",()=>{C();try{s==null||s()}catch{}}),requestAnimationFrame(()=>{i.style.opacity="1",i.style.transform="translateY(0)"}),C}const vt=Object.freeze(Object.defineProperty({__proto__:null,joinLiveCall:gt,liveCallSupported:F,openMicrophone:z,showIncomingCall:Ct},Symbol.toStringTag,{value:"Module"})),Rt="0.20.0",G="__bugcatchChunks",Et=e=>`${e}@${Rt}`;function St(e,r){const o=window[G]||(window[G]={});o[Et(e)]=r}St("call",vt)})();
2
2
  //# sourceMappingURL=bugcatch-call.umd.js.map
@@ -2071,7 +2071,7 @@ function li(t) {
2071
2071
  }
2072
2072
  const D = {
2073
2073
  name: "@sphoro/bugcatch-web-sdk",
2074
- version: "0.19.0"
2074
+ version: "0.20.0"
2075
2075
  }, U = {
2076
2076
  apiBase: "http://localhost:3000",
2077
2077
  apiKey: null,