@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 +16 -1
- package/dist/bugcatch-call.umd.js +1 -1
- package/dist/bugcatch-core.es.js +1 -1
- package/dist/bugcatch-panel.es.js +1057 -916
- package/dist/bugcatch-panel.es.js.map +1 -1
- package/dist/bugcatch-panel.umd.js +192 -151
- package/dist/bugcatch-panel.umd.js.map +1 -1
- package/dist/bugcatch.standalone.umd.js +178 -137
- package/dist/bugcatch.standalone.umd.js.map +1 -1
- package/dist/bugcatch.umd.js +2 -2
- package/package.json +1 -1
- package/src/index.d.ts +9 -0
- package/src/panel/call.js +3 -2
- package/src/panel/compose.js +7 -3
- package/src/panel/index.js +9 -0
- package/src/panel/rate-due.js +155 -0
- package/src/panel/rating.js +87 -0
- package/src/panel/signin.js +1 -1
- package/src/panel/styles.js +28 -0
- package/src/panel/thread.js +3 -72
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.
|
|
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
|