@sphoro/bugcatch-web-sdk 0.14.1 → 0.14.3
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/dist/bugcatch.es.js +531 -512
- package/dist/bugcatch.es.js.map +1 -1
- package/dist/bugcatch.umd.js +61 -48
- package/dist/bugcatch.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/widget.js +28 -0
package/dist/bugcatch.umd.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
(function(H,te){typeof exports=="object"&&typeof module<"u"?module.exports=te():typeof define=="function"&&define.amd?define(te):(H=typeof globalThis<"u"?globalThis:H||self,H.BugCatch=te())})(this,function(){"use strict";var An=H=>{throw TypeError(H)};var Ea=(H,te,we)=>te.has(H)||An("Cannot "+we);var Rn=(H,te,we)=>te.has(H)?An("Cannot add the same private member more than once"):te instanceof WeakSet?te.add(H):te.set(H,we);var V=(H,te,we)=>(Ea(H,te,"access private method"),we);var B,ye,ct,Qn,jn,zn,lt,On;const H="[REDACTED]",te=new Set(["auth","bearer","session","sid","phpsessid","otp","pass","passwd","pwd","sig","codeverifier"]),we=["token","secret","password","passwd","apikey","signature","credential","sessionid","privatekey","accesskey","authorization"],Hn=new Set(["key","code","state","nonce","salt","hash"]),Bt=[/eyJ[\w-]{8,}\.[\w-]{8,}\.[\w-]+/g,/(?:AKIA|ASIA|AROA|AIDA|AGPA|ANPA|ANVA|APKA)[0-9A-Z]{16}/g,/AIza[\w-]{35}/g,/gh[pousr]_[A-Za-z0-9]{36,}/g,/github_pat_\w{22,}/g,/[sprk]k_(?:live|test)_[0-9A-Za-z]{10,}/g,/xox[abposr]-[A-Za-z0-9-]{10,}/g,/sk-ant-[\w-]{20,}/g,/sk-[\w-]{20,}/g,/glpat-[\w-]{20,}/g,/shp(?:at|ss|ca|pa)_[A-Za-z0-9]{32}/g],qn=/\bBearer\s+[\w.~+/=-]{8,}/gi,Dn=/^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#@]+)@/;function At(t){try{return decodeURIComponent(t.replace(/\+/g," "))}catch{return t}}function Nn(t){return At(t).toLowerCase().replace(/[^a-z0-9]/g,"")}function Un(t){return t.length>=20?!0:Bt.some(e=>(e.lastIndex=0,e.test(t)))}function Vn(t,e){const n=Nn(t);if(!n)return!1;if(te.has(n))return!0;for(const o of we)if(n.includes(o))return!0;return Hn.has(n)?Un(At(e)):!1}function dt(t){return t.split("&").map(e=>{const n=e.indexOf("=");if(n===-1)return e;const o=e.slice(0,n),i=e.slice(n+1);return i&&Vn(o,i)?`${o}=${H}`:e}).join("&")}function Rt(t){let e=t;for(const n of Bt)n.lastIndex=0,e=e.replace(n,H);return e}function Qt(t){if(t==null)return t;let e=String(t);if(!e)return e;e=e.replace(Dn,`$1${H}@`);const n=e.indexOf("#");let o=n===-1?e:e.slice(0,n),i=n===-1?"":e.slice(n);const r=o.indexOf("?");if(r!==-1&&(o=o.slice(0,r+1)+dt(o.slice(r+1))),i.length>1){const s=i.slice(1),l=s.indexOf("?");l!==-1?i=`#${s.slice(0,l+1)}${dt(s.slice(l+1))}`:s.includes("=")&&(i=`#${dt(s)}`)}return Rt(o+i)}function Kn(t){if(t==null)return t;let e=String(t);return e&&(e=e.replace(/[A-Za-z][A-Za-z0-9+.-]{0,30}:\/\/[^\s"'<>)\]]+/g,n=>Qt(n)),e=e.replace(qn,`Bearer ${H}`),Rt(e))}function Pe(t){const e=[];return{push(n){e.push(n),e.length>t&&e.splice(0,e.length-t)},all:()=>e.slice(),clear:()=>{e.length=0},get size(){return e.length}}}const jt=["log","info","warn","error","debug"];function Pn(t,{levels:e=["warn","error","log","info"]}={}){const n={};for(const o of jt)n[o]=console[o],e.includes(o)&&(console[o]=(...i)=>{try{t.push({level:o,text:i.map(Ht).join(" ").slice(0,2e3),at:new Date().toISOString()})}catch{}n[o].apply(console,i)});return()=>{for(const o of jt)console[o]=n[o]}}function _n(t,{slowMs:e=2e3}={}){const n=window.fetch,o=XMLHttpRequest.prototype.open,i=XMLHttpRequest.prototype.send;return n&&(window.fetch=async function(...s){var y,p,b;const l=performance.now(),u=typeof s[0]=="string"?s[0]:(y=s[0])==null?void 0:y.url,g=((p=s[1])==null?void 0:p.method)||(typeof s[0]=="object"?(b=s[0])==null?void 0:b.method:"GET")||"GET";try{const h=await n.apply(this,s);return ut(t,{url:u,method:g,status:h.status,ms:Math.round(performance.now()-l),slowMs:e}),h}catch(h){throw ut(t,{url:u,method:g,status:0,error:String((h==null?void 0:h.message)||h),ms:Math.round(performance.now()-l),slowMs:e}),h}}),XMLHttpRequest.prototype.open=function(s,l,...u){return this.__bc={method:s,url:l,started:0},o.call(this,s,l,...u)},XMLHttpRequest.prototype.send=function(...s){return this.__bc&&(this.__bc.started=performance.now(),this.addEventListener("loadend",()=>{ut(t,{url:this.__bc.url,method:this.__bc.method,status:this.status,ms:Math.round(performance.now()-this.__bc.started),slowMs:e})})),i.apply(this,s)},()=>{n&&(window.fetch=n),XMLHttpRequest.prototype.open=o,XMLHttpRequest.prototype.send=i}}function ut(t,{url:e,method:n,status:o,ms:i,error:r,slowMs:s}){try{t.push({url:Qt(String(e)).slice(0,500),method:n,status:o,ms:i,error:r===void 0?void 0:Kn(r),failed:o===0||o>=400,slow:i>=s,at:new Date().toISOString()})}catch{}}function Fn(t){const e=o=>{const i=String(o.message||"Error"),r=o.filename?` (${o.filename}:${o.lineno}:${o.colno})`:"";t.push({level:"error",text:(/^uncaught/i.test(i)?i:`Uncaught ${i}`)+r,at:new Date().toISOString()})},n=o=>{t.push({level:"error",text:`Unhandled rejection: ${Ht(o.reason)}`,at:new Date().toISOString()})};return window.addEventListener("error",e),window.addEventListener("unhandledrejection",n),()=>{window.removeEventListener("error",e),window.removeEventListener("unhandledrejection",n)}}async function zt(){const t=Ot();try{if(navigator.getBattery){const e=await navigator.getBattery();t.battery=Math.round(e.level*100),t.charging=e.charging}}catch{}return t}function Ot(){var e,n,o,i,r,s,l,u,g;const t=window.navigator||{};return{userAgent:t.userAgent,platform:t.platform,language:t.language,languages:t.languages?[...t.languages]:null,online:t.onLine,cookieEnabled:t.cookieEnabled,maxTouchPoints:t.maxTouchPoints??null,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:(e=window.screen)==null?void 0:e.width,height:(n=window.screen)==null?void 0:n.height,availWidth:(o=window.screen)==null?void 0:o.availWidth,availHeight:(i=window.screen)==null?void 0:i.availHeight,colorDepth:(r=window.screen)==null?void 0:r.colorDepth,orientation:((l=(s=window.screen)==null?void 0:s.orientation)==null?void 0:l.type)||null},devicePixelRatio:window.devicePixelRatio,referrer:document.referrer||null,title:document.title,capturedAt:new Date().toISOString(),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffsetMinutes:new Date().getTimezoneOffset(),browserMode:t.webdriver?"Automated":"Normal",doNotTrack:t.doNotTrack||null,hardwareConcurrency:t.hardwareConcurrency??null,deviceMemory:t.deviceMemory??null,connection:t.connection?{effectiveType:t.connection.effectiveType,downlink:t.connection.downlink,rtt:t.connection.rtt,saveData:t.connection.saveData}:null,prefersColorScheme:(u=window.matchMedia)!=null&&u.call(window,"(prefers-color-scheme: dark)").matches?"dark":"light",prefersReducedMotion:((g=window.matchMedia)==null?void 0:g.call(window,"(prefers-reduced-motion: reduce)").matches)||!1}}function Ht(t){if(typeof t=="string")return t;if(t instanceof Error)return`${t.name}: ${t.message}`;try{return JSON.stringify(t)}catch{return String(t)}}const Wn=typeof window<"u"&&window.fetch?window.fetch.bind(window):null,Yn=typeof XMLHttpRequest<"u"?XMLHttpRequest.prototype.open:null,Xn=typeof XMLHttpRequest<"u"?XMLHttpRequest.prototype.send:null,qt=["image/png","image/jpeg","image/webp","image/gif","video/webm","video/mp4","audio/webm","audio/ogg","audio/mpeg","audio/mp4","audio/wav","application/pdf","text/plain","text/csv","application/json","application/zip","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],_e=["image/png","image/jpeg","image/webp","video/webm","video/mp4"],Zn=()=>{var t;return!!((t=navigator==null?void 0:navigator.mediaDevices)!=null&&t.getUserMedia&&typeof MediaRecorder<"u")},Jn=()=>{var t;return!!((t=navigator==null?void 0:navigator.mediaDevices)!=null&&t.getDisplayMedia&&typeof MediaRecorder<"u")},Gn=()=>{var t;return!!((t=navigator==null?void 0:navigator.mediaDevices)!=null&&t.getDisplayMedia)};function Fe(t,e=qt){const n=String(t||"").split(";")[0].trim().toLowerCase();return e.includes(n)?n:null}async function eo(){const t=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:1},audio:!1});try{const e=t.getVideoTracks()[0],n=document.createElement("video");n.srcObject=t,n.muted=!0,n.playsInline=!0,await n.play(),await new Promise(l=>requestAnimationFrame(()=>requestAnimationFrame(l)));const{width:o,height:i}=e.getSettings(),r=document.createElement("canvas");r.width=o||n.videoWidth,r.height=i||n.videoHeight,r.getContext("2d").drawImage(n,0,0,r.width,r.height);const s=await new Promise(l=>r.toBlob(l,"image/png"));if(!s)throw new Error("The browser returned an empty screenshot.");return{blob:s,mime:"image/png",kind:"SCREENSHOT"}}finally{t.getTracks().forEach(e=>e.stop())}}async function to({maxMs:t=12e4,onTick:e,onAutoStop:n}={}){const o=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:15},audio:!1}),i=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm"].find(h=>MediaRecorder.isTypeSupported(h))||"video/webm",r=new MediaRecorder(o,{mimeType:i,videoBitsPerSecond:25e5}),s=[];r.ondataavailable=h=>{h.data.size&&s.push(h.data)},r.start(1e3);const l=Date.now(),u=setInterval(()=>e==null?void 0:e(Math.floor((Date.now()-l)/1e3)),500),g=()=>{clearInterval(u),clearTimeout(b),o.getTracks().forEach(h=>h.stop())},y=new Promise(h=>{r.onstop=()=>{g(),h(new Blob(s,{type:i}))}}),p=()=>{r.state!=="inactive"&&r.stop(),n==null||n()};o.getVideoTracks()[0].addEventListener("ended",p);const b=setTimeout(p,t);return{mime:i,maxMs:t,async stop(){return clearTimeout(b),r.state!=="inactive"&&r.stop(),{blob:await y,mime:i,kind:"VIDEO"}},cancel(){g(),r.state!=="inactive"&&r.stop()}}}async function no({maxMs:t=12e4,onTick:e,onAutoStop:n}={}){const o=await navigator.mediaDevices.getUserMedia({audio:!0}),i=["audio/webm;codecs=opus","audio/webm","audio/mp4","audio/ogg"].find(h=>MediaRecorder.isTypeSupported(h))||"",r=new MediaRecorder(o,i?{mimeType:i}:void 0),s=[];r.ondataavailable=h=>{h.data.size&&s.push(h.data)},r.start(1e3);const l=Date.now(),u=setInterval(()=>e==null?void 0:e(Math.floor((Date.now()-l)/1e3)),500),g=()=>{clearInterval(u),clearTimeout(b),o.getTracks().forEach(h=>h.stop())},y=new Promise(h=>{r.onstop=()=>{g(),h(new Blob(s,{type:r.mimeType||i}))}}),b=setTimeout(()=>{r.state!=="inactive"&&r.stop(),n==null||n()},t);return{mime:r.mimeType||i,maxMs:t,async stop(){clearTimeout(b),r.state!=="inactive"&&r.stop();const h=await y;return{blob:h,mime:h.type||r.mimeType||i,kind:"AUDIO"}},cancel(){g(),r.state!=="inactive"&&r.stop()}}}async function oo({apiBase:t,apiKey:e,blob:n,mime:o,onProgress:i}){const r=Fe(o||n.type);if(!r)throw new Error(`[BugCatch] ${o||n.type||"that file"} can't be attached.`);const s=await Wn(`${t}/ingest/presign`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":e},body:JSON.stringify({mime:r})});if(!s.ok)throw new Error(`[BugCatch] could not start the upload (HTTP ${s.status}).`);const{key:l,uploadUrl:u}=await s.json();return await ao(u,n,r,i),{storageKey:l,mime:r}}function ao(t,e,n,o){return new Promise((i,r)=>{const s=new XMLHttpRequest;Yn.call(s,"PUT",t,!0),s.setRequestHeader("Content-Type",n),s.upload.onprogress=l=>{l.lengthComputable&&(o==null||o(l.loaded/l.total))},s.onload=()=>{s.status>=200&&s.status<300?i():r(new Error(`[BugCatch] upload failed (HTTP ${s.status}).`))},s.onerror=()=>r(new Error("[BugCatch] the browser blocked the upload to storage. If this is a new environment, the media bucket is probably missing its CORS policy.")),s.onabort=()=>r(new Error("[BugCatch] upload cancelled.")),Xn.call(s,e)})}function Me(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(0)} KB`:`${(t/1024/1024).toFixed(1)} MB`}function We(t){const e=Math.floor(t/60),n=t%60;return`${e}:${String(n).padStart(2,"0")}`}const ro=7*24*60*60*1e3;let Ye;function io(){return Ye||(Ye=new Promise((t,e)=>{const n=indexedDB.open("bugcatch-drafts",1);n.onupgradeneeded=()=>n.result.createObjectStore("drafts"),n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error),n.onblocked=()=>e(new Error("Draft storage is blocked."))}).catch(t=>{throw Ye=null,t})),Ye}function so(t,e){var n,o;return JSON.stringify([t.apiBase,t.projectId,e||((n=t.user)==null?void 0:n.email)||((o=t.user)==null?void 0:o.id)||"anonymous"])}async function Xe(t,e){const n=await io();return new Promise((o,i)=>{const r=n.transaction("drafts",e===void 0?"readonly":"readwrite"),s=r.objectStore("drafts"),l=e===void 0?s.get(t):e===null?s.delete(t):s.put({...e,savedAt:Date.now()},t);r.oncomplete=()=>o(l.result),r.onerror=()=>i(r.error),r.onabort=()=>i(r.error||new Error("Draft was not saved."))})}async function co(t){const e=await Xe(t);return e&&Date.now()-e.savedAt>ro?(await Xe(t,null),null):e||null}const lo="bugcatch.session.",pt=t=>`${lo}${t}`,ht=new Map;function he(t){var e;if(!t)return null;try{const n=(e=window.localStorage)==null?void 0:e.getItem(pt(t));if(n){const o=JSON.parse(n);if(o!=null&&o.token)return o}}catch{}return ht.get(t)||null}function uo(t,e){var o;if(!t||!(e!=null&&e.token))return;const n={token:e.token,email:e.email||null,name:e.name||null};ht.set(t,n);try{(o=window.localStorage)==null||o.setItem(pt(t),JSON.stringify(n))}catch{}}function ft(t){var e;if(t){ht.delete(t);try{(e=window.localStorage)==null||e.removeItem(pt(t))}catch{}}}function Ze({apiKey:t,token:e}){return{"Content-Type":"application/json","X-BugCatch-Key":t,...e?{"X-BugCatch-Session":e}:{}}}async function Dt(t){try{const e=await t.json(),n=Array.isArray(e.message)?e.message.join(", "):e.message;if(n)return n}catch{}return`Request failed (HTTP ${t.status})`}async function po({apiBase:t,apiKey:e,projectId:n,token:o}){const i={mode:"off",signedIn:null,signedOutReason:null};try{const r=await fetch(`${t}/ingest/login?projectId=${encodeURIComponent(n)}`,{headers:Ze({apiKey:e,token:o})});if(!r.ok)return i;const s=await r.json();return{mode:s.mode==="optional"||s.mode==="required"?s.mode:"off",signedIn:s.signedIn||null,signedOutReason:s.signedOutReason||null}}catch{return i}}async function ho({apiBase:t,apiKey:e,projectId:n,email:o,name:i}){const r=await fetch(`${t}/ingest/login/start`,{method:"POST",headers:Ze({apiKey:e}),body:JSON.stringify({projectId:n,email:o,...i?{name:i}:{}})});if(!r.ok)throw new Error(await Dt(r));return r.json()}async function fo({apiBase:t,apiKey:e,projectId:n,email:o,code:i}){const r=await fetch(`${t}/ingest/login`,{method:"POST",headers:Ze({apiKey:e}),body:JSON.stringify({projectId:n,email:o,code:i})});if(!r.ok)throw new Error(await Dt(r));const s=await r.json(),l={token:s.sessionToken,email:s.email,name:s.name};return uo(n,l),l}async function go({apiBase:t,apiKey:e,projectId:n,token:o}){if(ft(n),!o)return{signedOut:!0};try{await fetch(`${t}/ingest/logout`,{method:"POST",headers:Ze({apiKey:e,token:o}),body:JSON.stringify({projectId:n})})}catch{}return{signedOut:!0}}const gt="bugcatch.watch",Nt=[2e3,5e3,15e3,3e4,6e4],mo=5e3;function re(){var t;try{return((t=window.localStorage)==null?void 0:t.getItem(gt))||null}catch{return null}}function mt(t){var e;if(t)try{(e=window.localStorage)==null||e.setItem(gt,t)}catch{}}function ve(){var t;try{(t=window.localStorage)==null||t.removeItem(gt)}catch{}Ut()}const Je="bugcatch.unread";function bo(t){return[(t==null?void 0:t.bugId)||"report",(t==null?void 0:t.kind)||"status",(t==null?void 0:t.at)||""].join("|")}function qe(){var t;try{const e=(t=window.localStorage)==null?void 0:t.getItem(Je),n=e?JSON.parse(e):[];return Array.isArray(n)?n.filter(o=>o&&typeof o.id=="string"):[]}catch{return[]}}function Ge(t){var e,n;try{t.length?(e=window.localStorage)==null||e.setItem(Je,JSON.stringify(t)):(n=window.localStorage)==null||n.removeItem(Je)}catch{}}function yo(t){const e={...t,id:bo(t)},n=qe().filter(o=>o.id!==e.id);return n.push(e),Ge(n.slice(-20)),e}function wo(t){const e=qe().filter(n=>n.id!==t);return Ge(e),e}function vo(t){const e=qe().filter(n=>n.bugId!==t);return Ge(e),e}function Ut(){return Ge([]),[]}function xo(t,e){let n=t,o=n.indexOf(`
|
|
1
|
+
(function(q,te){typeof exports=="object"&&typeof module<"u"?module.exports=te():typeof define=="function"&&define.amd?define(te):(q=typeof globalThis<"u"?globalThis:q||self,q.BugCatch=te())})(this,function(){"use strict";var An=q=>{throw TypeError(q)};var Ea=(q,te,we)=>te.has(q)||An("Cannot "+we);var Rn=(q,te,we)=>te.has(q)?An("Cannot add the same private member more than once"):te instanceof WeakSet?te.add(q):te.set(q,we);var K=(q,te,we)=>(Ea(q,te,"access private method"),we);var B,ye,ct,Qn,jn,zn,lt,On;const q="[REDACTED]",te=new Set(["auth","bearer","session","sid","phpsessid","otp","pass","passwd","pwd","sig","codeverifier"]),we=["token","secret","password","passwd","apikey","signature","credential","sessionid","privatekey","accesskey","authorization"],Hn=new Set(["key","code","state","nonce","salt","hash"]),At=[/eyJ[\w-]{8,}\.[\w-]{8,}\.[\w-]+/g,/(?:AKIA|ASIA|AROA|AIDA|AGPA|ANPA|ANVA|APKA)[0-9A-Z]{16}/g,/AIza[\w-]{35}/g,/gh[pousr]_[A-Za-z0-9]{36,}/g,/github_pat_\w{22,}/g,/[sprk]k_(?:live|test)_[0-9A-Za-z]{10,}/g,/xox[abposr]-[A-Za-z0-9-]{10,}/g,/sk-ant-[\w-]{20,}/g,/sk-[\w-]{20,}/g,/glpat-[\w-]{20,}/g,/shp(?:at|ss|ca|pa)_[A-Za-z0-9]{32}/g],qn=/\bBearer\s+[\w.~+/=-]{8,}/gi,Dn=/^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#@]+)@/;function Rt(t){try{return decodeURIComponent(t.replace(/\+/g," "))}catch{return t}}function Nn(t){return Rt(t).toLowerCase().replace(/[^a-z0-9]/g,"")}function Un(t){return t.length>=20?!0:At.some(e=>(e.lastIndex=0,e.test(t)))}function Vn(t,e){const n=Nn(t);if(!n)return!1;if(te.has(n))return!0;for(const o of we)if(n.includes(o))return!0;return Hn.has(n)?Un(Rt(e)):!1}function dt(t){return t.split("&").map(e=>{const n=e.indexOf("=");if(n===-1)return e;const o=e.slice(0,n),i=e.slice(n+1);return i&&Vn(o,i)?`${o}=${q}`:e}).join("&")}function Qt(t){let e=t;for(const n of At)n.lastIndex=0,e=e.replace(n,q);return e}function jt(t){if(t==null)return t;let e=String(t);if(!e)return e;e=e.replace(Dn,`$1${q}@`);const n=e.indexOf("#");let o=n===-1?e:e.slice(0,n),i=n===-1?"":e.slice(n);const r=o.indexOf("?");if(r!==-1&&(o=o.slice(0,r+1)+dt(o.slice(r+1))),i.length>1){const s=i.slice(1),l=s.indexOf("?");l!==-1?i=`#${s.slice(0,l+1)}${dt(s.slice(l+1))}`:s.includes("=")&&(i=`#${dt(s)}`)}return Qt(o+i)}function Kn(t){if(t==null)return t;let e=String(t);return e&&(e=e.replace(/[A-Za-z][A-Za-z0-9+.-]{0,30}:\/\/[^\s"'<>)\]]+/g,n=>jt(n)),e=e.replace(qn,`Bearer ${q}`),Qt(e))}function Pe(t){const e=[];return{push(n){e.push(n),e.length>t&&e.splice(0,e.length-t)},all:()=>e.slice(),clear:()=>{e.length=0},get size(){return e.length}}}const zt=["log","info","warn","error","debug"];function Pn(t,{levels:e=["warn","error","log","info"]}={}){const n={};for(const o of zt)n[o]=console[o],e.includes(o)&&(console[o]=(...i)=>{try{t.push({level:o,text:i.map(qt).join(" ").slice(0,2e3),at:new Date().toISOString()})}catch{}n[o].apply(console,i)});return()=>{for(const o of zt)console[o]=n[o]}}function _n(t,{slowMs:e=2e3}={}){const n=window.fetch,o=XMLHttpRequest.prototype.open,i=XMLHttpRequest.prototype.send;return n&&(window.fetch=async function(...s){var y,p,b;const l=performance.now(),u=typeof s[0]=="string"?s[0]:(y=s[0])==null?void 0:y.url,h=((p=s[1])==null?void 0:p.method)||(typeof s[0]=="object"?(b=s[0])==null?void 0:b.method:"GET")||"GET";try{const f=await n.apply(this,s);return ut(t,{url:u,method:h,status:f.status,ms:Math.round(performance.now()-l),slowMs:e}),f}catch(f){throw ut(t,{url:u,method:h,status:0,error:String((f==null?void 0:f.message)||f),ms:Math.round(performance.now()-l),slowMs:e}),f}}),XMLHttpRequest.prototype.open=function(s,l,...u){return this.__bc={method:s,url:l,started:0},o.call(this,s,l,...u)},XMLHttpRequest.prototype.send=function(...s){return this.__bc&&(this.__bc.started=performance.now(),this.addEventListener("loadend",()=>{ut(t,{url:this.__bc.url,method:this.__bc.method,status:this.status,ms:Math.round(performance.now()-this.__bc.started),slowMs:e})})),i.apply(this,s)},()=>{n&&(window.fetch=n),XMLHttpRequest.prototype.open=o,XMLHttpRequest.prototype.send=i}}function ut(t,{url:e,method:n,status:o,ms:i,error:r,slowMs:s}){try{t.push({url:jt(String(e)).slice(0,500),method:n,status:o,ms:i,error:r===void 0?void 0:Kn(r),failed:o===0||o>=400,slow:i>=s,at:new Date().toISOString()})}catch{}}function Fn(t){const e=o=>{const i=String(o.message||"Error"),r=o.filename?` (${o.filename}:${o.lineno}:${o.colno})`:"";t.push({level:"error",text:(/^uncaught/i.test(i)?i:`Uncaught ${i}`)+r,at:new Date().toISOString()})},n=o=>{t.push({level:"error",text:`Unhandled rejection: ${qt(o.reason)}`,at:new Date().toISOString()})};return window.addEventListener("error",e),window.addEventListener("unhandledrejection",n),()=>{window.removeEventListener("error",e),window.removeEventListener("unhandledrejection",n)}}async function Ot(){const t=Ht();try{if(navigator.getBattery){const e=await navigator.getBattery();t.battery=Math.round(e.level*100),t.charging=e.charging}}catch{}return t}function Ht(){var e,n,o,i,r,s,l,u,h;const t=window.navigator||{};return{userAgent:t.userAgent,platform:t.platform,language:t.language,languages:t.languages?[...t.languages]:null,online:t.onLine,cookieEnabled:t.cookieEnabled,maxTouchPoints:t.maxTouchPoints??null,viewport:{width:window.innerWidth,height:window.innerHeight},screen:{width:(e=window.screen)==null?void 0:e.width,height:(n=window.screen)==null?void 0:n.height,availWidth:(o=window.screen)==null?void 0:o.availWidth,availHeight:(i=window.screen)==null?void 0:i.availHeight,colorDepth:(r=window.screen)==null?void 0:r.colorDepth,orientation:((l=(s=window.screen)==null?void 0:s.orientation)==null?void 0:l.type)||null},devicePixelRatio:window.devicePixelRatio,referrer:document.referrer||null,title:document.title,capturedAt:new Date().toISOString(),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,timezoneOffsetMinutes:new Date().getTimezoneOffset(),browserMode:t.webdriver?"Automated":"Normal",doNotTrack:t.doNotTrack||null,hardwareConcurrency:t.hardwareConcurrency??null,deviceMemory:t.deviceMemory??null,connection:t.connection?{effectiveType:t.connection.effectiveType,downlink:t.connection.downlink,rtt:t.connection.rtt,saveData:t.connection.saveData}:null,prefersColorScheme:(u=window.matchMedia)!=null&&u.call(window,"(prefers-color-scheme: dark)").matches?"dark":"light",prefersReducedMotion:((h=window.matchMedia)==null?void 0:h.call(window,"(prefers-reduced-motion: reduce)").matches)||!1}}function qt(t){if(typeof t=="string")return t;if(t instanceof Error)return`${t.name}: ${t.message}`;try{return JSON.stringify(t)}catch{return String(t)}}const Wn=typeof window<"u"&&window.fetch?window.fetch.bind(window):null,Yn=typeof XMLHttpRequest<"u"?XMLHttpRequest.prototype.open:null,Xn=typeof XMLHttpRequest<"u"?XMLHttpRequest.prototype.send:null,Dt=["image/png","image/jpeg","image/webp","image/gif","video/webm","video/mp4","audio/webm","audio/ogg","audio/mpeg","audio/mp4","audio/wav","application/pdf","text/plain","text/csv","application/json","application/zip","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],_e=["image/png","image/jpeg","image/webp","video/webm","video/mp4"],Zn=()=>{var t;return!!((t=navigator==null?void 0:navigator.mediaDevices)!=null&&t.getUserMedia&&typeof MediaRecorder<"u")},Jn=()=>{var t;return!!((t=navigator==null?void 0:navigator.mediaDevices)!=null&&t.getDisplayMedia&&typeof MediaRecorder<"u")},Gn=()=>{var t;return!!((t=navigator==null?void 0:navigator.mediaDevices)!=null&&t.getDisplayMedia)};function Fe(t,e=Dt){const n=String(t||"").split(";")[0].trim().toLowerCase();return e.includes(n)?n:null}async function eo(){const t=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:1},audio:!1});try{const e=t.getVideoTracks()[0],n=document.createElement("video");n.srcObject=t,n.muted=!0,n.playsInline=!0,await n.play(),await new Promise(l=>requestAnimationFrame(()=>requestAnimationFrame(l)));const{width:o,height:i}=e.getSettings(),r=document.createElement("canvas");r.width=o||n.videoWidth,r.height=i||n.videoHeight,r.getContext("2d").drawImage(n,0,0,r.width,r.height);const s=await new Promise(l=>r.toBlob(l,"image/png"));if(!s)throw new Error("The browser returned an empty screenshot.");return{blob:s,mime:"image/png",kind:"SCREENSHOT"}}finally{t.getTracks().forEach(e=>e.stop())}}async function to({maxMs:t=12e4,onTick:e,onAutoStop:n}={}){const o=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:15},audio:!1}),i=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm"].find(f=>MediaRecorder.isTypeSupported(f))||"video/webm",r=new MediaRecorder(o,{mimeType:i,videoBitsPerSecond:25e5}),s=[];r.ondataavailable=f=>{f.data.size&&s.push(f.data)},r.start(1e3);const l=Date.now(),u=setInterval(()=>e==null?void 0:e(Math.floor((Date.now()-l)/1e3)),500),h=()=>{clearInterval(u),clearTimeout(b),o.getTracks().forEach(f=>f.stop())},y=new Promise(f=>{r.onstop=()=>{h(),f(new Blob(s,{type:i}))}}),p=()=>{r.state!=="inactive"&&r.stop(),n==null||n()};o.getVideoTracks()[0].addEventListener("ended",p);const b=setTimeout(p,t);return{mime:i,maxMs:t,async stop(){return clearTimeout(b),r.state!=="inactive"&&r.stop(),{blob:await y,mime:i,kind:"VIDEO"}},cancel(){h(),r.state!=="inactive"&&r.stop()}}}async function no({maxMs:t=12e4,onTick:e,onAutoStop:n}={}){const o=await navigator.mediaDevices.getUserMedia({audio:!0}),i=["audio/webm;codecs=opus","audio/webm","audio/mp4","audio/ogg"].find(f=>MediaRecorder.isTypeSupported(f))||"",r=new MediaRecorder(o,i?{mimeType:i}:void 0),s=[];r.ondataavailable=f=>{f.data.size&&s.push(f.data)},r.start(1e3);const l=Date.now(),u=setInterval(()=>e==null?void 0:e(Math.floor((Date.now()-l)/1e3)),500),h=()=>{clearInterval(u),clearTimeout(b),o.getTracks().forEach(f=>f.stop())},y=new Promise(f=>{r.onstop=()=>{h(),f(new Blob(s,{type:r.mimeType||i}))}}),b=setTimeout(()=>{r.state!=="inactive"&&r.stop(),n==null||n()},t);return{mime:r.mimeType||i,maxMs:t,async stop(){clearTimeout(b),r.state!=="inactive"&&r.stop();const f=await y;return{blob:f,mime:f.type||r.mimeType||i,kind:"AUDIO"}},cancel(){h(),r.state!=="inactive"&&r.stop()}}}async function oo({apiBase:t,apiKey:e,blob:n,mime:o,onProgress:i}){const r=Fe(o||n.type);if(!r)throw new Error(`[BugCatch] ${o||n.type||"that file"} can't be attached.`);const s=await Wn(`${t}/ingest/presign`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":e},body:JSON.stringify({mime:r})});if(!s.ok)throw new Error(`[BugCatch] could not start the upload (HTTP ${s.status}).`);const{key:l,uploadUrl:u}=await s.json();return await ao(u,n,r,i),{storageKey:l,mime:r}}function ao(t,e,n,o){return new Promise((i,r)=>{const s=new XMLHttpRequest;Yn.call(s,"PUT",t,!0),s.setRequestHeader("Content-Type",n),s.upload.onprogress=l=>{l.lengthComputable&&(o==null||o(l.loaded/l.total))},s.onload=()=>{s.status>=200&&s.status<300?i():r(new Error(`[BugCatch] upload failed (HTTP ${s.status}).`))},s.onerror=()=>r(new Error("[BugCatch] the browser blocked the upload to storage. If this is a new environment, the media bucket is probably missing its CORS policy.")),s.onabort=()=>r(new Error("[BugCatch] upload cancelled.")),Xn.call(s,e)})}function Me(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(0)} KB`:`${(t/1024/1024).toFixed(1)} MB`}function We(t){const e=Math.floor(t/60),n=t%60;return`${e}:${String(n).padStart(2,"0")}`}const ro=7*24*60*60*1e3;let Ye;function io(){return Ye||(Ye=new Promise((t,e)=>{const n=indexedDB.open("bugcatch-drafts",1);n.onupgradeneeded=()=>n.result.createObjectStore("drafts"),n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error),n.onblocked=()=>e(new Error("Draft storage is blocked."))}).catch(t=>{throw Ye=null,t})),Ye}function so(t,e){var n,o;return JSON.stringify([t.apiBase,t.projectId,e||((n=t.user)==null?void 0:n.email)||((o=t.user)==null?void 0:o.id)||"anonymous"])}async function Xe(t,e){const n=await io();return new Promise((o,i)=>{const r=n.transaction("drafts",e===void 0?"readonly":"readwrite"),s=r.objectStore("drafts"),l=e===void 0?s.get(t):e===null?s.delete(t):s.put({...e,savedAt:Date.now()},t);r.oncomplete=()=>o(l.result),r.onerror=()=>i(r.error),r.onabort=()=>i(r.error||new Error("Draft was not saved."))})}async function co(t){const e=await Xe(t);return e&&Date.now()-e.savedAt>ro?(await Xe(t,null),null):e||null}const lo="bugcatch.session.",pt=t=>`${lo}${t}`,ht=new Map;function fe(t){var e;if(!t)return null;try{const n=(e=window.localStorage)==null?void 0:e.getItem(pt(t));if(n){const o=JSON.parse(n);if(o!=null&&o.token)return o}}catch{}return ht.get(t)||null}function uo(t,e){var o;if(!t||!(e!=null&&e.token))return;const n={token:e.token,email:e.email||null,name:e.name||null};ht.set(t,n);try{(o=window.localStorage)==null||o.setItem(pt(t),JSON.stringify(n))}catch{}}function ft(t){var e;if(t){ht.delete(t);try{(e=window.localStorage)==null||e.removeItem(pt(t))}catch{}}}function Ze({apiKey:t,token:e}){return{"Content-Type":"application/json","X-BugCatch-Key":t,...e?{"X-BugCatch-Session":e}:{}}}async function Nt(t){try{const e=await t.json(),n=Array.isArray(e.message)?e.message.join(", "):e.message;if(n)return n}catch{}return`Request failed (HTTP ${t.status})`}async function po({apiBase:t,apiKey:e,projectId:n,token:o}){const i={mode:"off",signedIn:null,signedOutReason:null};try{const r=await fetch(`${t}/ingest/login?projectId=${encodeURIComponent(n)}`,{headers:Ze({apiKey:e,token:o})});if(!r.ok)return i;const s=await r.json();return{mode:s.mode==="optional"||s.mode==="required"?s.mode:"off",signedIn:s.signedIn||null,signedOutReason:s.signedOutReason||null}}catch{return i}}async function ho({apiBase:t,apiKey:e,projectId:n,email:o,name:i}){const r=await fetch(`${t}/ingest/login/start`,{method:"POST",headers:Ze({apiKey:e}),body:JSON.stringify({projectId:n,email:o,...i?{name:i}:{}})});if(!r.ok)throw new Error(await Nt(r));return r.json()}async function fo({apiBase:t,apiKey:e,projectId:n,email:o,code:i}){const r=await fetch(`${t}/ingest/login`,{method:"POST",headers:Ze({apiKey:e}),body:JSON.stringify({projectId:n,email:o,code:i})});if(!r.ok)throw new Error(await Nt(r));const s=await r.json(),l={token:s.sessionToken,email:s.email,name:s.name};return uo(n,l),l}async function go({apiBase:t,apiKey:e,projectId:n,token:o}){if(ft(n),!o)return{signedOut:!0};try{await fetch(`${t}/ingest/logout`,{method:"POST",headers:Ze({apiKey:e,token:o}),body:JSON.stringify({projectId:n})})}catch{}return{signedOut:!0}}const gt="bugcatch.watch",Ut=[2e3,5e3,15e3,3e4,6e4],mo=5e3;function re(){var t;try{return((t=window.localStorage)==null?void 0:t.getItem(gt))||null}catch{return null}}function mt(t){var e;if(t)try{(e=window.localStorage)==null||e.setItem(gt,t)}catch{}}function ve(){var t;try{(t=window.localStorage)==null||t.removeItem(gt)}catch{}Vt()}const Je="bugcatch.unread";function bo(t){return[(t==null?void 0:t.bugId)||"report",(t==null?void 0:t.kind)||"status",(t==null?void 0:t.at)||""].join("|")}function qe(){var t;try{const e=(t=window.localStorage)==null?void 0:t.getItem(Je),n=e?JSON.parse(e):[];return Array.isArray(n)?n.filter(o=>o&&typeof o.id=="string"):[]}catch{return[]}}function Ge(t){var e,n;try{t.length?(e=window.localStorage)==null||e.setItem(Je,JSON.stringify(t)):(n=window.localStorage)==null||n.removeItem(Je)}catch{}}function yo(t){const e={...t,id:bo(t)},n=qe().filter(o=>o.id!==e.id);return n.push(e),Ge(n.slice(-20)),e}function wo(t){const e=qe().filter(n=>n.id!==t);return Ge(e),e}function vo(t){const e=qe().filter(n=>n.bugId!==t);return Ge(e),e}function Vt(){return Ge([]),[]}function xo(t,e){let n=t,o=n.indexOf(`
|
|
2
2
|
|
|
3
3
|
`);for(;o!==-1;){const i=n.slice(0,o);n=n.slice(o+2);const r=i.split(`
|
|
4
4
|
`).filter(s=>s.startsWith("data:")).map(s=>s.slice(5).trim()).join(`
|
|
5
5
|
`);if(r)try{e(JSON.parse(r))}catch{}o=n.indexOf(`
|
|
6
6
|
|
|
7
|
-
`)}return n}async function ko({apiBase:t}){const e=re();if(!e)return{reporter:null,reports:[]};const n=await fetch(`${t}/ingest/watch/reports`,{headers:{Authorization:`Bearer ${e}`}});if(n.status===401)return ve(),{reporter:null,reports:[]};if(!n.ok)throw new Error(`[BugCatch] could not load your reports (HTTP ${n.status})`);return n.json()}async function So({apiBase:t,bugId:e}){const n=re();if(!n)return null;const o=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}`,{headers:{Authorization:`Bearer ${n}`}});if(o.status===401)return ve(),null;if(o.status===404)return null;if(!o.ok)throw new Error(`[BugCatch] could not load that report (HTTP ${o.status})`);return o.json()}async function Vt({apiBase:t,bugId:e,body:n,attachments:o}){const i=re();if(!i)throw new Error("[BugCatch] nothing filed from this browser yet.");const r=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/messages`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({...n?{body:n}:{},...o!=null&&o.length?{attachments:o}:{}})});if(r.status===401)throw ve(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(!r.ok){let s="";try{const l=await r.json();s=Array.isArray(l.message)?l.message.join(", "):l.message||""}catch{}throw new Error(s||`[BugCatch] could not send that (HTTP ${r.status}).`)}return r.json()}async function Co({apiBase:t,apiKey:e,projectId:n}){const o={agent:!1,live:!1};try{const i=await fetch(`${t}/ingest/calls?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":e}});if(!i.ok)return o;const r=await i.json();return r!=null&&r.available?r.kinds&&typeof r.kinds=="object"?{agent:!1,live:!!r.kinds.live}:{agent:!1,live:r.kind==="live"}:o}catch{return o}}async function Eo({apiBase:t,apiKey:e,token:n,payload:o}){const i=await fetch(`${t}/ingest/calls`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":e,...n?{"X-BugCatch-Session":n}:{}},body:JSON.stringify(o)});if(!i.ok){let r="";try{const l=await i.json();r=Array.isArray(l.message)?l.message.join(", "):l.message||""}catch{}const s=new Error(r||`[BugCatch] the call could not be started (HTTP ${i.status}).`);throw s.status=i.status,s}return i.json()}async function Kt({apiBase:t,bugId:e}){const n=re();if(!n)return!1;try{const o=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,{headers:{Authorization:`Bearer ${n}`}});if(!o.ok)return!1;const i=await o.json();return!!(i!=null&&i.offered)}catch{return!1}}async function $o({apiBase:t,bugId:e}){const n=re();if(!n)throw new Error("[BugCatch] nothing filed from this browser yet.");const o=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,{method:"POST",headers:{Authorization:`Bearer ${n}`}});if(o.status===401)throw ve(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(!o.ok){let i="";try{const r=await o.json();i=Array.isArray(r.message)?r.message.join(", "):r.message||""}catch{}throw new Error(i||`[BugCatch] the call could not be started (HTTP ${o.status}).`)}return o.json()}async function To({apiBase:t,bugId:e,callId:n}){const o=re();if(o)try{await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/give-up`,{method:"POST",headers:{Authorization:`Bearer ${o}`}})}catch{}}async function Io({apiBase:t,bugId:e,callId:n}){const o=re();if(!o)throw new Error("[BugCatch] nothing filed from this browser yet.");const i=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/answer`,{method:"POST",headers:{Authorization:`Bearer ${o}`}});if(i.status===401)throw ve(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(i.status===409)throw new Error("[BugCatch] that call is no longer ringing.");if(!i.ok){let r="";try{const s=await i.json();r=Array.isArray(s.message)?s.message.join(", "):s.message||""}catch{}throw new Error(r||`[BugCatch] the call could not be answered (HTTP ${i.status}).`)}return i.json()}async function Pt({apiBase:t,bugId:e,callId:n}){const o=re();if(o)try{await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/decline`,{method:"POST",headers:{Authorization:`Bearer ${o}`}})}catch{}}function Mo({apiBase:t,onUpdate:e}){let n=!0,o=0,i=null;async function r(){const s=re();if(!s)throw new Error("nothing filed from this browser yet");i=new AbortController;const l=await fetch(`${t}/ingest/watch/stream`,{headers:{Authorization:`Bearer ${s}`,Accept:"text/event-stream"},signal:i.signal});if(l.status===401)throw n=!1,ve(),new Error("subscription no longer valid");if(!l.ok||!l.body)throw new Error(`stream failed (${l.status})`);const u=Date.now(),g=l.body.getReader(),y=new TextDecoder;let p="";try{for(;;){const{value:b,done:h}=await g.read();if(h)break;p+=y.decode(b,{stream:!0}),p=xo(p,k=>{if(k.type!=="ping")try{e(k)}catch{}})}}finally{Date.now()-u>=mo&&(o=0)}}return(async()=>{for(;n;){try{await r()}catch(l){if((l==null?void 0:l.name)==="AbortError")return}if(!n)return;const s=Nt[Math.min(o,Nt.length-1)];o+=1,await new Promise(l=>setTimeout(l,s))}})(),()=>{n=!1,i==null||i.abort(),i=null}}const Lo={OPEN:"is open",IN_PROGRESS:"is being worked on",RESOLVED:"has been fixed",CLOSED:"has been closed"},Bo={status:null,severity:"#e8912a",assignment:"#4da3ff",reply:"#35b87f"};function _t(t){return t!=null&&t.summary?t.summary:`Your report ${Lo[t==null?void 0:t.status]||"was updated"}`}function Ao(t){var e;return(t==null?void 0:t.kind)==="reply"&&((e=t.reply)!=null&&e.body)?`${t.reply.author?`${t.reply.author}: `:""}${t.reply.body}`:(t==null?void 0:t.title)||""}function Ro(t){const e=Date.parse(t||"");if(!Number.isFinite(e))return"";const n=Math.round((Date.now()-e)/6e4);if(n<1)return"just now";if(n<60)return`${n}m ago`;const o=Math.round(n/60);if(o<24)return`${o}h ago`;const i=Math.round(o/24);return i===1?"yesterday":`${i}d ago`}function Qo(){var t;try{const e=document.querySelector('[data-bugcatch="widget"]'),n=(t=e==null?void 0:e.shadowRoot)==null?void 0:t.querySelector(".dock"),o=(n==null?void 0:n.getBoundingClientRect().height)||0;return o?Math.round(o)+12:0}catch{return 0}}function jo({accent:t="#4F46E5",position:e="bottom-right",onRead:n=null,onReadAll:o=null,onCall:i=null}={}){const[r,s]=String(e).split("-"),l=r==="top",u=s==="left",g=new Map;let y=null,p=null;function b(){return y!=null&&y.isConnected||(y=document.createElement("div"),y.setAttribute("data-bugcatch","updates"),y.style.cssText=["position:fixed",`${l?"top":"bottom"}:${20+Qo()}px`,`${u?"left":"right"}:20px`,"z-index:2147482998","display:flex","flex-direction:column","gap:10px",`align-items:${u?"flex-start":"flex-end"}`,"width:min(320px,calc(100vw - 40px))","pointer-events:none"].join(";"),document.body.appendChild(y)),y}function h(S){if(!S._bcShown){S.remove();return}S.style.opacity="0",S.style.transform=`translateY(${l?-8:8}px)`,setTimeout(()=>S.remove(),250)}function k(S,E){const T=document.createElement("button");return T.type="button",T.textContent=S,T.style.cssText=["padding:5px 11px",`border:${E?"0":"1px solid rgba(236,238,242,.24)"}`,"border-radius:6px",`background:${E?t:"transparent"}`,`color:${E?"#fff":"#eceef2"}`,"font:600 12px/1.4 inherit","cursor:pointer","white-space:nowrap"].join(";"),T}function A(S){var D;const E=document.createElement("div");E.setAttribute("role","status"),E.style.cssText=["box-sizing:border-box","width:100%","padding:12px 14px","border-radius:10px","background:#1b1e26","color:#eceef2",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 12px 30px rgba(0,0,0,0.45)",`border-left:3px solid ${Bo[S==null?void 0:S.kind]||t}`,"opacity:0",`transform:translateY(${l?-8:8}px)`,"transition:opacity .2s ease,transform .2s ease","pointer-events:auto"].join(";");const T=document.createElement("div");T.style.cssText="font-weight:600;margin-bottom:2px",T.textContent=_t(S);const L=document.createElement("div");L.style.cssText=(S==null?void 0:S.kind)==="reply"?"color:#a4abba;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden":"color:#a4abba",L.textContent=Ao(S);const X=document.createElement("div");X.style.cssText="display:flex;align-items:center;gap:8px;margin-top:10px;flex-wrap:wrap";const q=document.createElement("span");q.style.cssText="color:#7b8394;font-size:11px;margin-right:auto",q.textContent=Ro(S==null?void 0:S.at);const Q=k("Mark as read",!1);if(Q.setAttribute("aria-label",`Mark as read: ${_t(S)}`),Q.addEventListener("click",()=>n==null?void 0:n(S.id)),X.append(q,Q),(D=S==null?void 0:S.call)!=null&&D.offered&&typeof i=="function"){const $=k("Talk it through",!0);$.addEventListener("click",()=>i(S)),X.insertBefore($,Q)}return E.append(T,L,X),E}function ie(S){const E=document.createElement("div");E.style.cssText=["box-sizing:border-box","width:100%","display:flex","align-items:center","gap:8px","padding:8px 12px","border-radius:10px","background:#1b1e26","color:#a4abba",'font:12px/1.4 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 12px 30px rgba(0,0,0,0.45)","pointer-events:auto"].join(";");const T=document.createElement("span");T.style.cssText="margin-right:auto",T.textContent=`${S} more update${S===1?"":"s"}`;const L=k("Mark all as read",!1);return L.style.cssText+=";padding:4px 9px",L.addEventListener("click",()=>o==null?void 0:o()),E.append(T,L),E}return{render(S){const E=Array.isArray(S)?S:[];if(!E.length){for(const $ of g.values())h($);g.clear(),p==null||p.remove(),p=null,y==null||y.remove(),y=null;return}const T=E.slice(-3),L=new Set(T.map($=>$.id)),X=b();for(const[$,se]of g)L.has($)||(h(se),g.delete($));const q=[];for(const $ of T){if(g.has($.id))continue;const se=A($);g.set($.id,se),q.push(se)}const Q=l?[...T].reverse():T;for(const $ of Q)X.appendChild(g.get($.id));const D=E.length-T.length;D>0?(p==null||p.remove(),p=ie(D),l?X.appendChild(p):X.insertBefore(p,X.firstChild)):(p==null||p.remove(),p=null),requestAnimationFrame(()=>{for(const $ of q)$.isConnected&&($._bcShown=!0,$.style.opacity="1",$.style.transform="translateY(0)")})},destroy(){g.clear(),p=null,y==null||y.remove(),y=null}}}async function zo({apiBase:t,apiKey:e,projectId:n,sessionToken:o}){try{const i=await fetch(`${t}/ingest/known-issues?projectId=${encodeURIComponent(n)}`,{headers:bt(e,o)});if(!i.ok)return[];const r=await i.json();return Array.isArray(r==null?void 0:r.issues)?r.issues:[]}catch{return[]}}async function Oo({apiBase:t,apiKey:e,projectId:n,q:o,sessionToken:i,signal:r}){try{const s=`${t}/ingest/known-issues/match?projectId=${encodeURIComponent(n)}&q=${encodeURIComponent(o)}`,l=await fetch(s,{headers:bt(e,i),signal:r});if(!l.ok)return[];const u=await l.json();return Array.isArray(u==null?void 0:u.issues)?u.issues:[]}catch{return[]}}async function Ho({apiBase:t,apiKey:e,projectId:n,bugId:o,reporterEmail:i,reporterName:r,metadata:s,logs:l,sessionToken:u}){const g=await fetch(`${t}/ingest/known-issues/${encodeURIComponent(o)}/join`,{method:"POST",headers:bt(e,u),body:JSON.stringify({projectId:n,reporterEmail:i,reporterName:r,metadata:s,logs:l})});if(!g.ok)throw new Error(await qo(g));const y=await g.json();return y!=null&&y.watchToken&&mt(y.watchToken),y}function bt(t,e){return{"Content-Type":"application/json","X-BugCatch-Key":t,...e?{"X-BugCatch-Session":e}:{}}}async function qo(t){try{const e=await t.json(),n=Array.isArray(e.message)?e.message.join(", "):e.message;if(n)return n}catch{}return`Could not add you to this issue (HTTP ${t.status})`}async function Do({apiBase:t,bugId:e,...n}){const o=re();if(!o)throw new Error("This browser cannot access that report.");const i=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/verification`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok)throw new Error(r.message||"Could not record feedback. Please refresh and try again.");return r}const No=2e4,Ft=120,Wt=200;function Yt(t){if(typeof t!="string"||!t.trim()||t.length>400)return null;try{return new RegExp(t.trim(),"gi")}catch{return null}}const Uo=t=>String(t).replace(/\s+/g," ").trim().slice(0,Ft);function Xt(t){const e=t.length>1&&t[1]!==void 0?t[1]:t[0];return typeof e!="string"||!e.trim()?null:{value:Uo(e),start:t.index,end:t.index+t[0].length}}function Vo(t,e){const n=[],o=new Set;for(const i of e||[]){const r=typeof i=="string"?i.slice(0,No):"";if(!r)continue;const s=[],l=(u,g)=>s.some(([y,p])=>u<p&&g>y);for(const u of t||[]){if(!u||u.scan===!1)continue;const g=Yt(u.pattern);if(!g)continue;let y,p=0;for(g.lastIndex=0;(y=g.exec(r))!==null&&!(++p>Wt);){if(y[0]===""){g.lastIndex+=1;continue}const b=Xt(y);if(b&&!l(b.start,b.end)){s.push([b.start,b.end]);const h=`${u.key}:${b.value.toLowerCase()}`;o.has(h)||(o.add(h),n.push({key:u.key,label:u.label,value:b.value}))}}}}return n}function Ko(t,e){const n=typeof e=="string"?e.trim():"";if(!n||n.length>Ft)return null;const o=Yt(t&&(t.valuePattern||t.pattern));if(!o)return null;let i,r=0;for(o.lastIndex=0;(i=o.exec(n))!==null&&!(++r>Wt);){if(i[0]===""){o.lastIndex+=1;continue}const s=i.index+i[0].length===n.length,l=i.index===0||i.index===1;if(s&&l){const u=Xt(i);if(u)return u.value}}return null}async function Po({apiBase:t,apiKey:e,projectId:n}){const o={policy:"off",fields:[]};try{const i=await fetch(`${t}/ingest/reference-fields?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":e}});if(!i.ok)return o;const r=await i.json(),s=r.policy==="optional"||r.policy==="required"?r.policy:"off",l=Array.isArray(r.fields)?r.fields:[];return l.length?{policy:s,fields:l}:o}catch{return o}}const Zt={"bottom-right":"bottom:20px;right:20px;","bottom-left":"bottom:20px;left:20px;","top-right":"top:20px;right:20px;","top-left":"top:20px;left:20px;"},Jt=[{value:"LOW",label:"Low"},{value:"MEDIUM",label:"Medium"},{value:"HIGH",label:"High"},{value:"CRITICAL",label:"Critical"}],R={camera:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8.5A1.5 1.5 0 0 1 4.5 7h2.2a1 1 0 0 0 .83-.45l.94-1.4A1 1 0 0 1 9.3 4.7h5.4a1 1 0 0 1 .83.45l.94 1.4a1 1 0 0 0 .83.45h2.2A1.5 1.5 0 0 1 21 8.5v9A1.5 1.5 0 0 1 19.5 19h-15A1.5 1.5 0 0 1 3 17.5z"/><circle cx="12" cy="13" r="3.4"/></svg>',video:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="6" width="12.5" height="12" rx="2.2"/><path d="M15.5 10.8l4.2-2.6a.6.6 0 0 1 .92.5v6.6a.6.6 0 0 1-.92.5l-4.2-2.6z"/></svg>',paperclip:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 11.5l-7.6 7.6a4.6 4.6 0 0 1-6.5-6.5l8-8a3.2 3.2 0 0 1 4.5 4.5l-8 8a1.8 1.8 0 0 1-2.5-2.5l7.1-7.1"/></svg>',close:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>',mic:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="2.5" width="6" height="11" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21M9 21h6"/></svg>',send:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l16-8-6 16-2.6-6.2L4 12Z"/></svg>',stopSquare:'<svg viewBox="0 0 24 24" fill="currentColor"><rect x="7" y="7" width="10" height="10" rx="2"/></svg>',back:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 5.5L8 12l6.5 6.5"/></svg>',phone:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.2 3.5h3l1.5 3.7-2 1.4a11.5 11.5 0 0 0 5.7 5.7l1.4-2 3.7 1.5v3a1.8 1.8 0 0 1-2 1.8A15.6 15.6 0 0 1 4.4 5.5a1.8 1.8 0 0 1 1.8-2z"/></svg>',phoneOff:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.2 3.5h3l1.5 3.7-2 1.4a11.5 11.5 0 0 0 5.7 5.7l1.4-2 3.7 1.5v3a1.8 1.8 0 0 1-2 1.8A15.6 15.6 0 0 1 4.4 5.5a1.8 1.8 0 0 1 1.8-2z"/><path d="M3 21L21 3"/></svg>',bug:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 6a4 4 0 0 1 8 0"/><rect x="7" y="7.5" width="10" height="12" rx="5"/><path d="M7 11H3.5M7 15.5H4M17 11h3.5M17 15.5h3M12 8v11.5"/></svg>',check:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.8l4.6 4.4L19 7"/></svg>',retry:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 12a8 8 0 1 1-2.6-5.9M20 4v4.5h-4.5"/></svg>',sun:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4.2"/><path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.4 5.4l1.6 1.6M17 17l1.6 1.6M18.6 5.4L17 7M7 17l-1.6 1.6"/></svg>',moon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13.4A8.2 8.2 0 1 1 10.6 4a6.6 6.6 0 0 0 9.4 9.4z"/></svg>',auto:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="2.8" y="4.4" width="18.4" height="12.6" rx="2.2"/><path d="M8.6 20.2h6.8"/><path d="M12 4.4v12.6"/><path d="M12 7.2a3.6 3.6 0 0 1 0 7.2z" fill="currentColor" stroke="none"/></svg>'},_o='<svg class="bc-brand" viewBox="0 0 254 60" fill="none" role="img" aria-label="sphoro BugCatch"><g fill="currentColor"><path transform="translate(0.00 40.00) scale(0.04000 -0.04000)" d="M276.00 -14.00Q179.00 -14.00 117.00 28.00Q55.00 70.00 42.00 148.00L158.00 178.00Q165.00 143.00 181.50 123.00Q198.00 103.00 222.50 94.50Q247.00 86.00 276.00 86.00Q320.00 86.00 341.00 101.50Q362.00 117.00 362.00 140.00Q362.00 163.00 342.00 175.50Q322.00 188.00 278.00 196.00L250.00 201.00Q198.00 211.00 155.00 228.50Q112.00 246.00 86.00 277.00Q60.00 308.00 60.00 357.00Q60.00 431.00 114.00 470.50Q168.00 510.00 256.00 510.00Q339.00 510.00 394.00 473.00Q449.00 436.00 466.00 376.00L349.00 340.00Q341.00 378.00 316.50 394.00Q292.00 410.00 256.00 410.00Q220.00 410.00 201.00 397.50Q182.00 385.00 182.00 363.00Q182.00 339.00 202.00 327.50Q222.00 316.00 256.00 310.00L284.00 305.00Q340.00 295.00 385.50 278.50Q431.00 262.00 457.50 231.50Q484.00 201.00 484.00 149.00Q484.00 71.00 427.50 28.50Q371.00 -14.00 276.00 -14.00Z"/><path transform="translate(19.56 40.00) scale(0.04000 -0.04000)" d="M70.00 -200.00V496.00H194.00V436.00H212.00Q229.00 465.00 265.00 487.50Q301.00 510.00 368.00 510.00Q428.00 510.00 479.00 480.50Q530.00 451.00 561.00 394.00Q592.00 337.00 592.00 256.00V240.00Q592.00 159.00 561.00 102.00Q530.00 45.00 479.00 15.50Q428.00 -14.00 368.00 -14.00Q323.00 -14.00 292.50 -3.50Q262.00 7.00 243.50 23.50Q225.00 40.00 214.00 57.00H196.00V-200.00ZM330.00 96.00Q389.00 96.00 427.50 133.50Q466.00 171.00 466.00 243.00V253.00Q466.00 325.00 427.00 362.50Q388.00 400.00 330.00 400.00Q272.00 400.00 233.00 362.50Q194.00 325.00 194.00 253.00V243.00Q194.00 171.00 233.00 133.50Q272.00 96.00 330.00 96.00Z"/><path transform="translate(43.68 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V700.00H196.00V435.00H214.00Q222.00 451.00 239.00 467.00Q256.00 483.00 284.50 493.50Q313.00 504.00 357.00 504.00Q415.00 504.00 458.50 477.50Q502.00 451.00 526.00 404.50Q550.00 358.00 550.00 296.00V0.00H424.00V286.00Q424.00 342.00 396.50 370.00Q369.00 398.00 318.00 398.00Q260.00 398.00 228.00 359.50Q196.00 321.00 196.00 252.00V0.00Z"/><path transform="translate(66.92 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/><path transform="translate(90.00 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V496.00H194.00V440.00H212.00Q223.00 470.00 248.50 484.00Q274.00 498.00 308.00 498.00H368.00V386.00H306.00Q258.00 386.00 227.00 360.50Q196.00 335.00 196.00 282.00V0.00Z"/><path transform="translate(104.44 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/></g><rect x="139.52" y="16" width="1.6" height="26" rx="0.8" fill="var(--bc-brand-mark, #5647ee)" opacity="0.4"/><g fill="var(--bc-brand-mark, #5647ee)"><path transform="translate(154.52 35.00) scale(0.01400 -0.01400)" d="M46.35 0.00V105.85H139.75V594.15H46.35V700.00H404.08Q467.38 700.00 514.79 678.41Q562.20 656.83 588.70 617.33Q615.20 577.83 615.20 523.35V513.70Q615.20 465.52 597.03 434.76Q578.85 404.00 553.91 387.24Q528.98 370.48 506.28 363.30V346.35Q528.98 340.35 555.24 323.50Q581.50 306.65 600.00 275.48Q618.50 244.30 618.50 194.48V184.48Q618.50 126.65 591.41 85.24Q564.33 43.83 516.83 21.91Q469.33 0.00 406.85 0.00ZM259.85 109.15H392.60Q441.20 109.15 469.80 132.60Q498.40 156.05 498.40 198.55V208.20Q498.40 250.70 470.21 274.15Q442.02 297.60 392.60 297.60H259.85ZM259.85 406.75H391.65Q437.55 406.75 466.32 430.11Q495.10 453.48 495.10 493.80V503.80Q495.10 544.95 466.74 567.90Q438.37 590.85 391.65 590.85H259.85Z"/><path transform="translate(167.00 35.00) scale(0.01400 -0.01400)" d="M335.30 -14.00Q251.22 -14.00 190.60 16.63Q129.97 47.25 97.56 104.96Q65.15 162.68 65.15 243.03V700.00H185.25V239.73Q185.25 170.48 224.03 131.99Q262.80 93.50 335.30 93.50Q407.80 93.50 446.57 131.99Q485.35 170.48 485.35 239.73V700.00H605.45V243.03Q605.45 162.68 573.13 104.96Q540.80 47.25 480.09 16.63Q419.38 -14.00 335.30 -14.00Z"/><path transform="translate(179.60 35.00) scale(0.01400 -0.01400)" d="M311.85 -14.00Q238.45 -14.00 179.69 18.50Q120.92 51.00 86.69 113.67Q52.45 176.35 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.23 645.59Q598.33 577.17 598.33 460.87V456.70H479.87V464.52Q479.87 504.67 463.76 536.86Q447.65 569.05 414.99 587.77Q382.32 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 138.89Q257.63 91.85 334.00 91.85Q410.02 91.85 445.12 132.83Q480.22 173.80 480.22 237.92V249.67H302.85V351.88H598.33V0.00H487.52V69.10H470.57Q462.70 50.87 446.06 31.44Q429.42 12.00 397.64 -1.00Q365.85 -14.00 311.85 -14.00Z"/><path transform="translate(192.05 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(204.25 35.00) scale(0.01400 -0.01400)" d="M19.75 0.00 211.62 700.00H421.33L613.20 0.00H489.27L447.42 159.60H185.53L143.68 0.00ZM214.25 270.40H418.70L324.95 624.87H308.00Z"/><path transform="translate(216.31 35.00) scale(0.01400 -0.01400)" d="M233.95 0.00V590.85H24.70V700.00H563.30V590.85H354.05V0.00Z"/><path transform="translate(227.75 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(239.95 35.00) scale(0.01400 -0.01400)" d="M69.50 0.00V700.00H189.60V405.58H466.40V700.00H586.50V0.00H466.40V296.42H189.60V0.00Z"/></g></svg>',Gt=[{value:"light",label:"Light",icon:R.sun},{value:"dark",label:"Dark",icon:R.moon},{value:"auto",label:"System default",icon:R.auto}],en="bugcatch:theme";function Fo(){try{const t=localStorage.getItem(en);return Gt.some(e=>e.value===t)?t:null}catch{return null}}function Wo(t){try{localStorage.setItem(en,t)}catch{}}const Yo=t=>`
|
|
7
|
+
`)}return n}async function ko({apiBase:t}){const e=re();if(!e)return{reporter:null,reports:[]};const n=await fetch(`${t}/ingest/watch/reports`,{headers:{Authorization:`Bearer ${e}`}});if(n.status===401)return ve(),{reporter:null,reports:[]};if(!n.ok)throw new Error(`[BugCatch] could not load your reports (HTTP ${n.status})`);return n.json()}async function So({apiBase:t,bugId:e}){const n=re();if(!n)return null;const o=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}`,{headers:{Authorization:`Bearer ${n}`}});if(o.status===401)return ve(),null;if(o.status===404)return null;if(!o.ok)throw new Error(`[BugCatch] could not load that report (HTTP ${o.status})`);return o.json()}async function Kt({apiBase:t,bugId:e,body:n,attachments:o}){const i=re();if(!i)throw new Error("[BugCatch] nothing filed from this browser yet.");const r=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/messages`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify({...n?{body:n}:{},...o!=null&&o.length?{attachments:o}:{}})});if(r.status===401)throw ve(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(!r.ok){let s="";try{const l=await r.json();s=Array.isArray(l.message)?l.message.join(", "):l.message||""}catch{}throw new Error(s||`[BugCatch] could not send that (HTTP ${r.status}).`)}return r.json()}async function Co({apiBase:t,apiKey:e,projectId:n}){const o={agent:!1,live:!1};try{const i=await fetch(`${t}/ingest/calls?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":e}});if(!i.ok)return o;const r=await i.json();return r!=null&&r.available?r.kinds&&typeof r.kinds=="object"?{agent:!1,live:!!r.kinds.live}:{agent:!1,live:r.kind==="live"}:o}catch{return o}}async function Eo({apiBase:t,apiKey:e,token:n,payload:o}){const i=await fetch(`${t}/ingest/calls`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":e,...n?{"X-BugCatch-Session":n}:{}},body:JSON.stringify(o)});if(!i.ok){let r="";try{const l=await i.json();r=Array.isArray(l.message)?l.message.join(", "):l.message||""}catch{}const s=new Error(r||`[BugCatch] the call could not be started (HTTP ${i.status}).`);throw s.status=i.status,s}return i.json()}async function Pt({apiBase:t,bugId:e}){const n=re();if(!n)return!1;try{const o=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,{headers:{Authorization:`Bearer ${n}`}});if(!o.ok)return!1;const i=await o.json();return!!(i!=null&&i.offered)}catch{return!1}}async function $o({apiBase:t,bugId:e}){const n=re();if(!n)throw new Error("[BugCatch] nothing filed from this browser yet.");const o=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,{method:"POST",headers:{Authorization:`Bearer ${n}`}});if(o.status===401)throw ve(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(!o.ok){let i="";try{const r=await o.json();i=Array.isArray(r.message)?r.message.join(", "):r.message||""}catch{}throw new Error(i||`[BugCatch] the call could not be started (HTTP ${o.status}).`)}return o.json()}async function To({apiBase:t,bugId:e,callId:n}){const o=re();if(o)try{await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/give-up`,{method:"POST",headers:{Authorization:`Bearer ${o}`}})}catch{}}async function Io({apiBase:t,bugId:e,callId:n}){const o=re();if(!o)throw new Error("[BugCatch] nothing filed from this browser yet.");const i=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/answer`,{method:"POST",headers:{Authorization:`Bearer ${o}`}});if(i.status===401)throw ve(),new Error("[BugCatch] this browser can no longer prove it filed that report.");if(i.status===409)throw new Error("[BugCatch] that call is no longer ringing.");if(!i.ok){let r="";try{const s=await i.json();r=Array.isArray(s.message)?s.message.join(", "):s.message||""}catch{}throw new Error(r||`[BugCatch] the call could not be answered (HTTP ${i.status}).`)}return i.json()}async function _t({apiBase:t,bugId:e,callId:n}){const o=re();if(o)try{await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/decline`,{method:"POST",headers:{Authorization:`Bearer ${o}`}})}catch{}}function Mo({apiBase:t,onUpdate:e}){let n=!0,o=0,i=null;async function r(){const s=re();if(!s)throw new Error("nothing filed from this browser yet");i=new AbortController;const l=await fetch(`${t}/ingest/watch/stream`,{headers:{Authorization:`Bearer ${s}`,Accept:"text/event-stream"},signal:i.signal});if(l.status===401)throw n=!1,ve(),new Error("subscription no longer valid");if(!l.ok||!l.body)throw new Error(`stream failed (${l.status})`);const u=Date.now(),h=l.body.getReader(),y=new TextDecoder;let p="";try{for(;;){const{value:b,done:f}=await h.read();if(f)break;p+=y.decode(b,{stream:!0}),p=xo(p,k=>{if(k.type!=="ping")try{e(k)}catch{}})}}finally{Date.now()-u>=mo&&(o=0)}}return(async()=>{for(;n;){try{await r()}catch(l){if((l==null?void 0:l.name)==="AbortError")return}if(!n)return;const s=Ut[Math.min(o,Ut.length-1)];o+=1,await new Promise(l=>setTimeout(l,s))}})(),()=>{n=!1,i==null||i.abort(),i=null}}const Lo={OPEN:"is open",IN_PROGRESS:"is being worked on",RESOLVED:"has been fixed",CLOSED:"has been closed"},Bo={status:null,severity:"#e8912a",assignment:"#4da3ff",reply:"#35b87f"};function Ft(t){return t!=null&&t.summary?t.summary:`Your report ${Lo[t==null?void 0:t.status]||"was updated"}`}function Ao(t){var e;return(t==null?void 0:t.kind)==="reply"&&((e=t.reply)!=null&&e.body)?`${t.reply.author?`${t.reply.author}: `:""}${t.reply.body}`:(t==null?void 0:t.title)||""}function Ro(t){const e=Date.parse(t||"");if(!Number.isFinite(e))return"";const n=Math.round((Date.now()-e)/6e4);if(n<1)return"just now";if(n<60)return`${n}m ago`;const o=Math.round(n/60);if(o<24)return`${o}h ago`;const i=Math.round(o/24);return i===1?"yesterday":`${i}d ago`}function Qo(){var t;try{const e=document.querySelector('[data-bugcatch="widget"]'),n=(t=e==null?void 0:e.shadowRoot)==null?void 0:t.querySelector(".dock"),o=(n==null?void 0:n.getBoundingClientRect().height)||0;return o?Math.round(o)+12:0}catch{return 0}}function jo({accent:t="#4F46E5",position:e="bottom-right",onRead:n=null,onReadAll:o=null,onCall:i=null}={}){const[r,s]=String(e).split("-"),l=r==="top",u=s==="left",h=new Map;let y=null,p=null;function b(){return y!=null&&y.isConnected||(y=document.createElement("div"),y.setAttribute("data-bugcatch","updates"),y.style.cssText=["position:fixed",`${l?"top":"bottom"}:${20+Qo()}px`,`${u?"left":"right"}:20px`,"z-index:2147482998","display:flex","flex-direction:column","gap:10px",`align-items:${u?"flex-start":"flex-end"}`,"width:min(320px,calc(100vw - 40px))","pointer-events:none"].join(";"),document.body.appendChild(y)),y}function f(S){if(!S._bcShown){S.remove();return}S.style.opacity="0",S.style.transform=`translateY(${l?-8:8}px)`,setTimeout(()=>S.remove(),250)}function k(S,E){const T=document.createElement("button");return T.type="button",T.textContent=S,T.style.cssText=["padding:5px 11px",`border:${E?"0":"1px solid rgba(236,238,242,.24)"}`,"border-radius:6px",`background:${E?t:"transparent"}`,`color:${E?"#fff":"#eceef2"}`,"font:600 12px/1.4 inherit","cursor:pointer","white-space:nowrap"].join(";"),T}function A(S){var N;const E=document.createElement("div");E.setAttribute("role","status"),E.style.cssText=["box-sizing:border-box","width:100%","padding:12px 14px","border-radius:10px","background:#1b1e26","color:#eceef2",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 12px 30px rgba(0,0,0,0.45)",`border-left:3px solid ${Bo[S==null?void 0:S.kind]||t}`,"opacity:0",`transform:translateY(${l?-8:8}px)`,"transition:opacity .2s ease,transform .2s ease","pointer-events:auto"].join(";");const T=document.createElement("div");T.style.cssText="font-weight:600;margin-bottom:2px",T.textContent=Ft(S);const L=document.createElement("div");L.style.cssText=(S==null?void 0:S.kind)==="reply"?"color:#a4abba;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden":"color:#a4abba",L.textContent=Ao(S);const X=document.createElement("div");X.style.cssText="display:flex;align-items:center;gap:8px;margin-top:10px;flex-wrap:wrap";const D=document.createElement("span");D.style.cssText="color:#7b8394;font-size:11px;margin-right:auto",D.textContent=Ro(S==null?void 0:S.at);const j=k("Mark as read",!1);if(j.setAttribute("aria-label",`Mark as read: ${Ft(S)}`),j.addEventListener("click",()=>n==null?void 0:n(S.id)),X.append(D,j),(N=S==null?void 0:S.call)!=null&&N.offered&&typeof i=="function"){const $=k("Talk it through",!0);$.addEventListener("click",()=>i(S)),X.insertBefore($,j)}return E.append(T,L,X),E}function ie(S){const E=document.createElement("div");E.style.cssText=["box-sizing:border-box","width:100%","display:flex","align-items:center","gap:8px","padding:8px 12px","border-radius:10px","background:#1b1e26","color:#a4abba",'font:12px/1.4 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 12px 30px rgba(0,0,0,0.45)","pointer-events:auto"].join(";");const T=document.createElement("span");T.style.cssText="margin-right:auto",T.textContent=`${S} more update${S===1?"":"s"}`;const L=k("Mark all as read",!1);return L.style.cssText+=";padding:4px 9px",L.addEventListener("click",()=>o==null?void 0:o()),E.append(T,L),E}return{render(S){const E=Array.isArray(S)?S:[];if(!E.length){for(const $ of h.values())f($);h.clear(),p==null||p.remove(),p=null,y==null||y.remove(),y=null;return}const T=E.slice(-3),L=new Set(T.map($=>$.id)),X=b();for(const[$,se]of h)L.has($)||(f(se),h.delete($));const D=[];for(const $ of T){if(h.has($.id))continue;const se=A($);h.set($.id,se),D.push(se)}const j=l?[...T].reverse():T;for(const $ of j)X.appendChild(h.get($.id));const N=E.length-T.length;N>0?(p==null||p.remove(),p=ie(N),l?X.appendChild(p):X.insertBefore(p,X.firstChild)):(p==null||p.remove(),p=null),requestAnimationFrame(()=>{for(const $ of D)$.isConnected&&($._bcShown=!0,$.style.opacity="1",$.style.transform="translateY(0)")})},destroy(){h.clear(),p=null,y==null||y.remove(),y=null}}}async function zo({apiBase:t,apiKey:e,projectId:n,sessionToken:o}){try{const i=await fetch(`${t}/ingest/known-issues?projectId=${encodeURIComponent(n)}`,{headers:bt(e,o)});if(!i.ok)return[];const r=await i.json();return Array.isArray(r==null?void 0:r.issues)?r.issues:[]}catch{return[]}}async function Oo({apiBase:t,apiKey:e,projectId:n,q:o,sessionToken:i,signal:r}){try{const s=`${t}/ingest/known-issues/match?projectId=${encodeURIComponent(n)}&q=${encodeURIComponent(o)}`,l=await fetch(s,{headers:bt(e,i),signal:r});if(!l.ok)return[];const u=await l.json();return Array.isArray(u==null?void 0:u.issues)?u.issues:[]}catch{return[]}}async function Ho({apiBase:t,apiKey:e,projectId:n,bugId:o,reporterEmail:i,reporterName:r,metadata:s,logs:l,sessionToken:u}){const h=await fetch(`${t}/ingest/known-issues/${encodeURIComponent(o)}/join`,{method:"POST",headers:bt(e,u),body:JSON.stringify({projectId:n,reporterEmail:i,reporterName:r,metadata:s,logs:l})});if(!h.ok)throw new Error(await qo(h));const y=await h.json();return y!=null&&y.watchToken&&mt(y.watchToken),y}function bt(t,e){return{"Content-Type":"application/json","X-BugCatch-Key":t,...e?{"X-BugCatch-Session":e}:{}}}async function qo(t){try{const e=await t.json(),n=Array.isArray(e.message)?e.message.join(", "):e.message;if(n)return n}catch{}return`Could not add you to this issue (HTTP ${t.status})`}async function Do({apiBase:t,bugId:e,...n}){const o=re();if(!o)throw new Error("This browser cannot access that report.");const i=await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/verification`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify(n)}),r=await i.json().catch(()=>({}));if(!i.ok)throw new Error(r.message||"Could not record feedback. Please refresh and try again.");return r}const No=2e4,Wt=120,Yt=200;function Xt(t){if(typeof t!="string"||!t.trim()||t.length>400)return null;try{return new RegExp(t.trim(),"gi")}catch{return null}}const Uo=t=>String(t).replace(/\s+/g," ").trim().slice(0,Wt);function Zt(t){const e=t.length>1&&t[1]!==void 0?t[1]:t[0];return typeof e!="string"||!e.trim()?null:{value:Uo(e),start:t.index,end:t.index+t[0].length}}function Vo(t,e){const n=[],o=new Set;for(const i of e||[]){const r=typeof i=="string"?i.slice(0,No):"";if(!r)continue;const s=[],l=(u,h)=>s.some(([y,p])=>u<p&&h>y);for(const u of t||[]){if(!u||u.scan===!1)continue;const h=Xt(u.pattern);if(!h)continue;let y,p=0;for(h.lastIndex=0;(y=h.exec(r))!==null&&!(++p>Yt);){if(y[0]===""){h.lastIndex+=1;continue}const b=Zt(y);if(b&&!l(b.start,b.end)){s.push([b.start,b.end]);const f=`${u.key}:${b.value.toLowerCase()}`;o.has(f)||(o.add(f),n.push({key:u.key,label:u.label,value:b.value}))}}}}return n}function Ko(t,e){const n=typeof e=="string"?e.trim():"";if(!n||n.length>Wt)return null;const o=Xt(t&&(t.valuePattern||t.pattern));if(!o)return null;let i,r=0;for(o.lastIndex=0;(i=o.exec(n))!==null&&!(++r>Yt);){if(i[0]===""){o.lastIndex+=1;continue}const s=i.index+i[0].length===n.length,l=i.index===0||i.index===1;if(s&&l){const u=Zt(i);if(u)return u.value}}return null}async function Po({apiBase:t,apiKey:e,projectId:n}){const o={policy:"off",fields:[]};try{const i=await fetch(`${t}/ingest/reference-fields?projectId=${encodeURIComponent(n)}`,{headers:{"X-BugCatch-Key":e}});if(!i.ok)return o;const r=await i.json(),s=r.policy==="optional"||r.policy==="required"?r.policy:"off",l=Array.isArray(r.fields)?r.fields:[];return l.length?{policy:s,fields:l}:o}catch{return o}}const Jt={"bottom-right":"bottom:20px;right:20px;","bottom-left":"bottom:20px;left:20px;","top-right":"top:20px;right:20px;","top-left":"top:20px;left:20px;"},Gt=[{value:"LOW",label:"Low"},{value:"MEDIUM",label:"Medium"},{value:"HIGH",label:"High"},{value:"CRITICAL",label:"Critical"}],Q={camera:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8.5A1.5 1.5 0 0 1 4.5 7h2.2a1 1 0 0 0 .83-.45l.94-1.4A1 1 0 0 1 9.3 4.7h5.4a1 1 0 0 1 .83.45l.94 1.4a1 1 0 0 0 .83.45h2.2A1.5 1.5 0 0 1 21 8.5v9A1.5 1.5 0 0 1 19.5 19h-15A1.5 1.5 0 0 1 3 17.5z"/><circle cx="12" cy="13" r="3.4"/></svg>',video:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="6" width="12.5" height="12" rx="2.2"/><path d="M15.5 10.8l4.2-2.6a.6.6 0 0 1 .92.5v6.6a.6.6 0 0 1-.92.5l-4.2-2.6z"/></svg>',paperclip:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 11.5l-7.6 7.6a4.6 4.6 0 0 1-6.5-6.5l8-8a3.2 3.2 0 0 1 4.5 4.5l-8 8a1.8 1.8 0 0 1-2.5-2.5l7.1-7.1"/></svg>',close:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>',mic:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="2.5" width="6" height="11" rx="3"/><path d="M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21M9 21h6"/></svg>',send:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12l16-8-6 16-2.6-6.2L4 12Z"/></svg>',stopSquare:'<svg viewBox="0 0 24 24" fill="currentColor"><rect x="7" y="7" width="10" height="10" rx="2"/></svg>',back:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 5.5L8 12l6.5 6.5"/></svg>',phone:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.2 3.5h3l1.5 3.7-2 1.4a11.5 11.5 0 0 0 5.7 5.7l1.4-2 3.7 1.5v3a1.8 1.8 0 0 1-2 1.8A15.6 15.6 0 0 1 4.4 5.5a1.8 1.8 0 0 1 1.8-2z"/></svg>',phoneOff:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.2 3.5h3l1.5 3.7-2 1.4a11.5 11.5 0 0 0 5.7 5.7l1.4-2 3.7 1.5v3a1.8 1.8 0 0 1-2 1.8A15.6 15.6 0 0 1 4.4 5.5a1.8 1.8 0 0 1 1.8-2z"/><path d="M3 21L21 3"/></svg>',bug:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 6a4 4 0 0 1 8 0"/><rect x="7" y="7.5" width="10" height="12" rx="5"/><path d="M7 11H3.5M7 15.5H4M17 11h3.5M17 15.5h3M12 8v11.5"/></svg>',check:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.8l4.6 4.4L19 7"/></svg>',retry:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 12a8 8 0 1 1-2.6-5.9M20 4v4.5h-4.5"/></svg>',sun:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4.2"/><path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.4 5.4l1.6 1.6M17 17l1.6 1.6M18.6 5.4L17 7M7 17l-1.6 1.6"/></svg>',moon:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13.4A8.2 8.2 0 1 1 10.6 4a6.6 6.6 0 0 0 9.4 9.4z"/></svg>',auto:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="2.8" y="4.4" width="18.4" height="12.6" rx="2.2"/><path d="M8.6 20.2h6.8"/><path d="M12 4.4v12.6"/><path d="M12 7.2a3.6 3.6 0 0 1 0 7.2z" fill="currentColor" stroke="none"/></svg>'},_o='<svg class="bc-brand" viewBox="0 0 254 60" fill="none" role="img" aria-label="sphoro BugCatch"><g fill="currentColor"><path transform="translate(0.00 40.00) scale(0.04000 -0.04000)" d="M276.00 -14.00Q179.00 -14.00 117.00 28.00Q55.00 70.00 42.00 148.00L158.00 178.00Q165.00 143.00 181.50 123.00Q198.00 103.00 222.50 94.50Q247.00 86.00 276.00 86.00Q320.00 86.00 341.00 101.50Q362.00 117.00 362.00 140.00Q362.00 163.00 342.00 175.50Q322.00 188.00 278.00 196.00L250.00 201.00Q198.00 211.00 155.00 228.50Q112.00 246.00 86.00 277.00Q60.00 308.00 60.00 357.00Q60.00 431.00 114.00 470.50Q168.00 510.00 256.00 510.00Q339.00 510.00 394.00 473.00Q449.00 436.00 466.00 376.00L349.00 340.00Q341.00 378.00 316.50 394.00Q292.00 410.00 256.00 410.00Q220.00 410.00 201.00 397.50Q182.00 385.00 182.00 363.00Q182.00 339.00 202.00 327.50Q222.00 316.00 256.00 310.00L284.00 305.00Q340.00 295.00 385.50 278.50Q431.00 262.00 457.50 231.50Q484.00 201.00 484.00 149.00Q484.00 71.00 427.50 28.50Q371.00 -14.00 276.00 -14.00Z"/><path transform="translate(19.56 40.00) scale(0.04000 -0.04000)" d="M70.00 -200.00V496.00H194.00V436.00H212.00Q229.00 465.00 265.00 487.50Q301.00 510.00 368.00 510.00Q428.00 510.00 479.00 480.50Q530.00 451.00 561.00 394.00Q592.00 337.00 592.00 256.00V240.00Q592.00 159.00 561.00 102.00Q530.00 45.00 479.00 15.50Q428.00 -14.00 368.00 -14.00Q323.00 -14.00 292.50 -3.50Q262.00 7.00 243.50 23.50Q225.00 40.00 214.00 57.00H196.00V-200.00ZM330.00 96.00Q389.00 96.00 427.50 133.50Q466.00 171.00 466.00 243.00V253.00Q466.00 325.00 427.00 362.50Q388.00 400.00 330.00 400.00Q272.00 400.00 233.00 362.50Q194.00 325.00 194.00 253.00V243.00Q194.00 171.00 233.00 133.50Q272.00 96.00 330.00 96.00Z"/><path transform="translate(43.68 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V700.00H196.00V435.00H214.00Q222.00 451.00 239.00 467.00Q256.00 483.00 284.50 493.50Q313.00 504.00 357.00 504.00Q415.00 504.00 458.50 477.50Q502.00 451.00 526.00 404.50Q550.00 358.00 550.00 296.00V0.00H424.00V286.00Q424.00 342.00 396.50 370.00Q369.00 398.00 318.00 398.00Q260.00 398.00 228.00 359.50Q196.00 321.00 196.00 252.00V0.00Z"/><path transform="translate(66.92 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/><path transform="translate(90.00 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V496.00H194.00V440.00H212.00Q223.00 470.00 248.50 484.00Q274.00 498.00 308.00 498.00H368.00V386.00H306.00Q258.00 386.00 227.00 360.50Q196.00 335.00 196.00 282.00V0.00Z"/><path transform="translate(104.44 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/></g><rect x="139.52" y="16" width="1.6" height="26" rx="0.8" fill="var(--bc-brand-mark, #5647ee)" opacity="0.4"/><g fill="var(--bc-brand-mark, #5647ee)"><path transform="translate(154.52 35.00) scale(0.01400 -0.01400)" d="M46.35 0.00V105.85H139.75V594.15H46.35V700.00H404.08Q467.38 700.00 514.79 678.41Q562.20 656.83 588.70 617.33Q615.20 577.83 615.20 523.35V513.70Q615.20 465.52 597.03 434.76Q578.85 404.00 553.91 387.24Q528.98 370.48 506.28 363.30V346.35Q528.98 340.35 555.24 323.50Q581.50 306.65 600.00 275.48Q618.50 244.30 618.50 194.48V184.48Q618.50 126.65 591.41 85.24Q564.33 43.83 516.83 21.91Q469.33 0.00 406.85 0.00ZM259.85 109.15H392.60Q441.20 109.15 469.80 132.60Q498.40 156.05 498.40 198.55V208.20Q498.40 250.70 470.21 274.15Q442.02 297.60 392.60 297.60H259.85ZM259.85 406.75H391.65Q437.55 406.75 466.32 430.11Q495.10 453.48 495.10 493.80V503.80Q495.10 544.95 466.74 567.90Q438.37 590.85 391.65 590.85H259.85Z"/><path transform="translate(167.00 35.00) scale(0.01400 -0.01400)" d="M335.30 -14.00Q251.22 -14.00 190.60 16.63Q129.97 47.25 97.56 104.96Q65.15 162.68 65.15 243.03V700.00H185.25V239.73Q185.25 170.48 224.03 131.99Q262.80 93.50 335.30 93.50Q407.80 93.50 446.57 131.99Q485.35 170.48 485.35 239.73V700.00H605.45V243.03Q605.45 162.68 573.13 104.96Q540.80 47.25 480.09 16.63Q419.38 -14.00 335.30 -14.00Z"/><path transform="translate(179.60 35.00) scale(0.01400 -0.01400)" d="M311.85 -14.00Q238.45 -14.00 179.69 18.50Q120.92 51.00 86.69 113.67Q52.45 176.35 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.23 645.59Q598.33 577.17 598.33 460.87V456.70H479.87V464.52Q479.87 504.67 463.76 536.86Q447.65 569.05 414.99 587.77Q382.32 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 138.89Q257.63 91.85 334.00 91.85Q410.02 91.85 445.12 132.83Q480.22 173.80 480.22 237.92V249.67H302.85V351.88H598.33V0.00H487.52V69.10H470.57Q462.70 50.87 446.06 31.44Q429.42 12.00 397.64 -1.00Q365.85 -14.00 311.85 -14.00Z"/><path transform="translate(192.05 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(204.25 35.00) scale(0.01400 -0.01400)" d="M19.75 0.00 211.62 700.00H421.33L613.20 0.00H489.27L447.42 159.60H185.53L143.68 0.00ZM214.25 270.40H418.70L324.95 624.87H308.00Z"/><path transform="translate(216.31 35.00) scale(0.01400 -0.01400)" d="M233.95 0.00V590.85H24.70V700.00H563.30V590.85H354.05V0.00Z"/><path transform="translate(227.75 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(239.95 35.00) scale(0.01400 -0.01400)" d="M69.50 0.00V700.00H189.60V405.58H466.40V700.00H586.50V0.00H466.40V296.42H189.60V0.00Z"/></g></svg>',en=[{value:"light",label:"Light",icon:Q.sun},{value:"dark",label:"Dark",icon:Q.moon},{value:"auto",label:"System default",icon:Q.auto}],tn="bugcatch:theme";function Fo(){try{const t=localStorage.getItem(tn);return en.some(e=>e.value===t)?t:null}catch{return null}}function Wo(t){try{localStorage.setItem(tn,t)}catch{}}const Yo=t=>`
|
|
8
8
|
:host { all: initial; }
|
|
9
9
|
:host {
|
|
10
10
|
--bc-accent: ${t};
|
|
@@ -538,6 +538,15 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
538
538
|
.att .file .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
539
539
|
.att .file .sz { flex: none; color: var(--bc-faint); font-size: 11px; }
|
|
540
540
|
|
|
541
|
+
/* Quick answers under the confirm question — only on the latest message. */
|
|
542
|
+
.msg-row .quick { display: none; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
|
|
543
|
+
.msg-row:last-child .quick { display: flex; }
|
|
544
|
+
.quick button {
|
|
545
|
+
font: inherit; font-size: 13px; padding: 6px 12px; border-radius: 999px; cursor: pointer;
|
|
546
|
+
border: 1px solid var(--bc-accent); background: transparent; color: var(--bc-accent);
|
|
547
|
+
}
|
|
548
|
+
.quick button:hover { background: color-mix(in srgb, var(--bc-accent) 12%, transparent); }
|
|
549
|
+
|
|
541
550
|
/* ---------- the composer ---------- */
|
|
542
551
|
.composer {
|
|
543
552
|
position: sticky; bottom: 0; margin-top: auto;
|
|
@@ -773,15 +782,15 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
773
782
|
.launcher:hover { transform: none; filter: none; box-shadow: 0 6px 18px rgba(10,12,16,.22), 0 1px 3px rgba(10,12,16,.16); }
|
|
774
783
|
.tool:hover, .themer button:hover { border-color: var(--bc-border); }
|
|
775
784
|
}
|
|
776
|
-
`;function Xo(t){const e=document.createElement("div");e.setAttribute("data-bugcatch","widget");let n=Fo()||Zo(t.config.theme);e.className=
|
|
785
|
+
`;function Xo(t){const e=document.createElement("div");e.setAttribute("data-bugcatch","widget");let n=Fo()||Zo(t.config.theme);e.className=nn(n);const o=e.attachShadow({mode:"open"}),i=document.createElement("style");i.textContent=Yo(t.config.accent||"#4F46E5"),o.appendChild(i);const r=Jt[t.config.widgetPosition]?t.config.widgetPosition:"bottom-right",s=document.createElement("div");s.className=`dock ${r.includes("right")?"at-right":"at-left"}`+(r.startsWith("top")?" at-top":""),s.style.cssText=Jt[r];const l=document.createElement("div");l.className="themer",l.setAttribute("role","group"),l.setAttribute("aria-label","Report widget theme"),l.innerHTML=en.map(y=>`<button type="button" data-theme="${y.value}" title="${y.label}" aria-label="${y.label}" aria-pressed="${y.value===n}">${y.icon}</button>`).join(""),l.addEventListener("click",y=>{const p=y.target.closest("button[data-theme]");!p||p.dataset.theme===n||(n=p.dataset.theme,e.className=nn(n),Wo(n),l.querySelectorAll("button").forEach(b=>{b.setAttribute("aria-pressed",String(b.dataset.theme===n))}))});const u=document.createElement("button");u.className="launcher",u.type="button",u.innerHTML=`${Q.bug}<span>Report a bug</span>`,u.setAttribute("aria-haspopup","dialog"),u.setAttribute("aria-expanded","false");let h=null;return u.addEventListener("click",()=>{if(h){h.close();return}s.classList.add("over"),u.setAttribute("aria-expanded","true"),h=Jo({root:o,host:e,dock:s,client:t,onClose:()=>{h=null,s.classList.remove("over"),u.setAttribute("aria-expanded","false")}})}),s.append(l,u),o.appendChild(s),document.body.appendChild(e),()=>{h==null||h.destroy(),e.remove()}}function Zo(t){return t==="dark"||t==="light"?t:"auto"}function nn(t){return t==="dark"?"bc-dark":t==="light"?"bc-light":"bc-auto"}function Jo({root:t,host:e,dock:n,client:o,onClose:i}){var En,$n,Tn,In,Mn,Ln;const r=o.config,s=r.attachments!==!1,l=s&&Gn(),u=s&&Jn(),h=[];let y="MEDIUM",p=null,b=!1;const f=document.createElement("div");f.className=`scrim ${n.classList.contains("at-left")?"at-left":"at-right"} ${n.classList.contains("at-top")?"at-top":"at-bottom"}`,f.style.setProperty("--bc-dock-h",`${Math.round(n.getBoundingClientRect().height)}px`),f.innerHTML=`
|
|
777
786
|
<div class="panel" role="dialog" aria-modal="true" aria-labelledby="bc-h">
|
|
778
787
|
<div class="head">
|
|
779
|
-
<div class="mark">${
|
|
788
|
+
<div class="mark">${Q.bug}</div>
|
|
780
789
|
<div class="titles">
|
|
781
790
|
<h2 id="bc-h">Report a bug</h2>
|
|
782
791
|
<p>We'll attach what the page was doing, so you don't have to explain it.</p>
|
|
783
792
|
</div>
|
|
784
|
-
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${
|
|
793
|
+
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${Q.close}</button>
|
|
785
794
|
</div>
|
|
786
795
|
<div class="body">
|
|
787
796
|
<div class="slot"></div>
|
|
@@ -804,7 +813,7 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
804
813
|
<div class="field">
|
|
805
814
|
<label id="bc-prio-l">Severity</label>
|
|
806
815
|
<div class="seg" role="group" aria-labelledby="bc-prio-l">
|
|
807
|
-
${
|
|
816
|
+
${Gt.map(a=>`
|
|
808
817
|
<button type="button" data-prio="${a.value}" aria-pressed="${a.value===y}">${a.label}</button>
|
|
809
818
|
`).join("")}
|
|
810
819
|
</div>
|
|
@@ -813,9 +822,9 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
813
822
|
<div class="field">
|
|
814
823
|
<label>Attach <span style="font-weight:450;color:var(--bc-faint)">(optional)</span></label>
|
|
815
824
|
<div class="tools">
|
|
816
|
-
${l?`<button class="tool" type="button" data-act="shot">${
|
|
817
|
-
${u?`<button class="tool" type="button" data-act="rec">${
|
|
818
|
-
<button class="tool" type="button" data-act="file">${
|
|
825
|
+
${l?`<button class="tool" type="button" data-act="shot">${Q.camera}Screenshot</button>`:""}
|
|
826
|
+
${u?`<button class="tool" type="button" data-act="rec">${Q.video}Record</button>`:""}
|
|
827
|
+
<button class="tool" type="button" data-act="file">${Q.paperclip}File</button>
|
|
819
828
|
</div>
|
|
820
829
|
<div class="thumbs"></div>
|
|
821
830
|
<input type="file" accept="${_e.join(",")}" multiple hidden />
|
|
@@ -835,16 +844,16 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
835
844
|
<button class="ghost" type="button" data-act="call" hidden>Talk to the team</button>
|
|
836
845
|
<button class="primary" type="button" data-act="send">Send report</button>
|
|
837
846
|
</div>
|
|
838
|
-
</div>`;const k=a=>
|
|
839
|
-
${
|
|
847
|
+
</div>`;const k=a=>f.querySelector(a),A=k("#bc-title"),ie=k(".slot"),S=k(".thumbs"),E=f.querySelector("input[type=file]"),T=k('[data-act="send"]'),L=k('[data-act="call"]'),X=k(".note"),D=k(".compose"),j=k(".whoami"),N=k(".refs"),$=k(".known"),se=k('[data-act="history"]'),ne=document.createElement("div");ne.setAttribute("role","status"),ne.className="note",D.prepend(ne);const De=so(r,(En=fe(r.projectId))==null?void 0:En.email);let xe=r.drafts===!1,ot=!1,ke=Promise.resolve(),U;function oe(){if(clearTimeout(U),!xe||ot||r.drafts===!1)return ke;const a=A.value||k("#bc-desc").value||h.length?{title:A.value,description:k("#bc-desc").value,priority:y,items:h.map(({blob:c,mime:d,kind:g})=>({blob:c,mime:d,kind:g}))}:null;return ke=ke.catch(()=>{}).then(()=>Xe(De,a)).then(()=>{ne.textContent=a?"Draft saved on this device":""}).catch(()=>{ne.textContent="Draft could not be saved. Keep this tab open."}),ke}function Le(){clearTimeout(U),U=setTimeout(oe,250)}D.addEventListener("input",Le),D.addEventListener("change",Le);const at=()=>{oe()};window.addEventListener("pagehide",at);function Ne(){h.filter(a=>a.status==="failed").forEach(Qe)}window.addEventListener("online",Ne),r.drafts!==!1&&(D.inert=!0,co(De).then(a=>{Ae||!a||(ne.innerHTML='Unfinished report on this device. <button type="button" data-resume>Resume report</button> <button type="button" data-discard>Discard</button>',ne.querySelector("[data-resume]").onclick=()=>{A.value=a.title||"",k("#bc-desc").value=a.description||"",y=Gt.some(c=>c.value===a.priority)?a.priority:"MEDIUM",f.querySelectorAll("[data-prio]").forEach(c=>c.setAttribute("aria-pressed",String(c.dataset.prio===y)));for(const c of(a.items||[]).slice(0,r.maxAttachments??5))Ce(c);xe=!0,oe()},ne.querySelector("[data-discard]").onclick=()=>{xe=!0,oe()})}).catch(()=>{ne.textContent="Draft storage is unavailable. Keep this tab open."}).finally(()=>{D.inert=!1,ne.querySelector("[data-resume]")||(xe=!0)}));const me=document.activeElement,Be=document.documentElement.style,kt=Be.overflow;Be.overflow="hidden";let Ae=!1,Se=null;function Ue(){var a;Ae||(oe(),Ae=!0,clearTimeout(U),window.removeEventListener("pagehide",at),window.removeEventListener("online",Ne),p==null||p.cancel(),Se==null||Se(),h.forEach(c=>c.previewUrl&&URL.revokeObjectURL(c.previewUrl)),Be.overflow=kt,document.removeEventListener("keydown",Re,!0),f.remove(),(a=t.querySelector(".recbar"))==null||a.remove(),n.hidden=!1,e.style.opacity="",i==null||i())}function ce(){var a;if(!Ae){f.classList.add("closing"),setTimeout(Ue,160);try{(a=me==null?void 0:me.focus)==null||a.call(me)}catch{}}}function Re(a){if(a.key==="Escape"){if(a.stopPropagation(),p){je({keep:!1});return}b||ce();return}if(a.key!=="Tab"||p)return;const c=[...f.querySelectorAll("button:not(:disabled), input:not([hidden]), textarea, select, [href]")].filter(v=>v.offsetParent!==null||v===document.activeElement);if(!c.length)return;const d=c[0],g=c[c.length-1],C=f.getRootNode().activeElement;a.shiftKey&&C===d?(a.preventDefault(),g.focus()):!a.shiftKey&&C===g&&(a.preventDefault(),d.focus())}document.addEventListener("keydown",Re,!0),f.addEventListener("click",a=>{a.target===f&&!b&&ce()}),k('[data-act="close"]').addEventListener("click",ce),k('[data-act="cancel"]').addEventListener("click",ce),f.querySelectorAll("[data-prio]").forEach(a=>{a.addEventListener("click",()=>{y=a.dataset.prio,Le(),f.querySelectorAll("[data-prio]").forEach(c=>{c.setAttribute("aria-pressed",String(c===a))})})});function z(a,c="err"){ie.innerHTML=a?`<div class="msg ${c}">${x(a)}</div>`:""}function de(){const a=h.some(c=>c.status==="uploading");T.disabled=b||a||h.some(c=>c.status==="failed"),X.textContent=a?"Waiting for the upload to finish…":h.some(c=>c.status==="failed")?"Retry or remove failed attachments before sending.":"",f.querySelectorAll(".tool").forEach(c=>{c.disabled=b||h.length>=(r.maxAttachments??5)})}function rt(a){var v;const c=a.el,d=a.kind==="VIDEO"?"Video":"Shot",g=a.kind==="VIDEO"?`<video src="${a.previewUrl}" muted playsinline preload="metadata"></video>`:`<img src="${a.previewUrl}" alt="" />`;let C="";a.status==="uploading"?C=`<div class="veil"><div class="spinner"></div><div class="bar"><i style="width:${Math.round(a.progress*100)}%"></i></div></div>`:a.status==="failed"&&(C=`<div class="veil err"><button type="button" data-act="retry" aria-label="Retry upload">${Q.retry}</button>Failed</div>`),c.innerHTML=`
|
|
848
|
+
${g}
|
|
840
849
|
<span class="kind">${d} · ${Me(a.size)}</span>
|
|
841
|
-
<button class="drop" type="button" data-act="drop" aria-label="Remove ${d.toLowerCase()}">${
|
|
842
|
-
${C}`,c.querySelector('[data-act="drop"]').addEventListener("click",()=>St(a)),(v=c.querySelector('[data-act="retry"]'))==null||v.addEventListener("click",()=>Qe(a))}function St(a){const c=
|
|
850
|
+
<button class="drop" type="button" data-act="drop" aria-label="Remove ${d.toLowerCase()}">${Q.close}</button>
|
|
851
|
+
${C}`,c.querySelector('[data-act="drop"]').addEventListener("click",()=>St(a)),(v=c.querySelector('[data-act="retry"]'))==null||v.addEventListener("click",()=>Qe(a))}function St(a){const c=h.indexOf(a);c>=0&&h.splice(c,1),a.previewUrl&&URL.revokeObjectURL(a.previewUrl),a.el.remove(),oe(),de()}async function Qe(a){a.status="uploading",a.progress=0,rt(a),de();try{const{storageKey:c,mime:d}=await o.uploadAttachment(a.blob,a.mime,g=>{a.progress=g;const C=a.el.querySelector(".bar i");C&&(C.style.width=`${Math.round(g*100)}%`)});a.storageKey=c,a.mime=d,a.status="ready"}catch(c){a.status="failed",z(c.message.replace("[BugCatch] ",""))}rt(a),de()}function Ce({blob:a,mime:c,kind:d}){const g=r.maxAttachmentBytes??26214400;if(a.size>g){z(`That file is ${Me(a.size)} — the limit is ${Me(g)}.`);return}const C=Fe(c||a.type,_e);if(!C){z("Only PNG, JPEG, WebP, WebM and MP4 files can be attached to a report.");return}const v={blob:a,kind:d,mime:C,size:a.size,previewUrl:URL.createObjectURL(a),status:"uploading",progress:0,storageKey:null,el:document.createElement("div")};v.el.className="thumb",h.push(v),S.appendChild(v.el),z(""),oe(),Qe(v)}async function Ct(a){e.style.opacity="0",e.style.pointerEvents="none",await new Promise(c=>requestAnimationFrame(()=>requestAnimationFrame(c)));try{return await a()}finally{e.style.opacity="",e.style.pointerEvents=""}}($n=f.querySelector('[data-act="shot"]'))==null||$n.addEventListener("click",async()=>{try{const a=await Ct(eo);Ce(a)}catch(a){(a==null?void 0:a.name)!=="NotAllowedError"&&z(`Screenshot failed: ${a.message}`)}}),(Tn=f.querySelector('[data-act="file"]'))==null||Tn.addEventListener("click",()=>E.click()),E==null||E.addEventListener("change",()=>{const a=(r.maxAttachments??5)-h.length;[...E.files].slice(0,Math.max(a,0)).forEach(c=>{Ce({blob:c,mime:c.type,kind:c.type.startsWith("video/")?"VIDEO":"SCREENSHOT"})}),E.value=""}),(In=f.querySelector('[data-act="rec"]'))==null||In.addEventListener("click",async()=>{const a=r.maxRecordingMs??12e4;let c;try{p=await to({maxMs:a,onTick:d=>{c&&(c.querySelector(".time").textContent=We(d))},onAutoStop:()=>{p&&je({keep:!0})}})}catch(d){(d==null?void 0:d.name)!=="NotAllowedError"&&z(`Recording failed: ${d.message}`);return}f.style.display="none",n.hidden=!0,c=document.createElement("div"),c.className="recbar",c.innerHTML=`
|
|
843
852
|
<span class="dot"></span>
|
|
844
853
|
<span class="time">0:00</span>
|
|
845
854
|
<span class="hint">Recording — up to ${We(Math.round(a/1e3))}</span>
|
|
846
855
|
<button class="stop" type="button">Stop</button>
|
|
847
|
-
<button class="ghost" type="button">Discard</button>`,c.querySelector(".stop").addEventListener("click",()=>je({keep:!0})),c.querySelector(".ghost").addEventListener("click",()=>je({keep:!1})),t.appendChild(c),c.querySelector(".stop").focus()});async function je({keep:a}){var d;const c=p;if(c){if(p=null,(d=t.querySelector(".recbar"))==null||d.remove(),
|
|
856
|
+
<button class="ghost" type="button">Discard</button>`,c.querySelector(".stop").addEventListener("click",()=>je({keep:!0})),c.querySelector(".ghost").addEventListener("click",()=>je({keep:!1})),t.appendChild(c),c.querySelector(".stop").focus()});async function je({keep:a}){var d;const c=p;if(c){if(p=null,(d=t.querySelector(".recbar"))==null||d.remove(),f.style.display="",n.hidden=!1,!a){c.cancel(),A.focus();return}try{const g=await c.stop();g.blob.size?Ce(g):z("That recording came back empty — nothing was captured.")}catch(g){z(`Recording failed: ${g.message}`)}A.focus()}}let m={policy:"off",fields:[]},w=null,I="",P="",_=!1,Ee=!1;o.referenceFields().then(a=>{m=a}).catch(()=>{});function it(){return m.policy==="off"||!m.fields.length?[]:Vo(m.fields,[A.value,k("#bc-desc").value])}function $e(){return!w||!I.trim()?[]:[{key:w,value:I.trim().slice(0,120)}]}function ge(){var g,C;if(!w){N.hidden=!0,N.innerHTML="";return}const a=m.fields.find(v=>v.key===w)||m.fields[0],c=m.policy!=="required";N.hidden=!1,N.innerHTML=`
|
|
848
857
|
<p class="why">${x(c?"One more thing, so we can find your record — this helps us answer faster.":"We need one of these to look this up.")}</p>
|
|
849
858
|
<div class="row">
|
|
850
859
|
${m.fields.length>1?`
|
|
@@ -860,8 +869,8 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
860
869
|
aria-label="${x(a.label)}" />
|
|
861
870
|
</div>
|
|
862
871
|
${a.hint?`<p class="hint">${x(a.hint)}</p>`:""}
|
|
863
|
-
${
|
|
864
|
-
${c?`<button type="button" class="link" data-act="ref-skip">I don't have this</button>`:""}`;const d=
|
|
872
|
+
${P?`<p class="after err">${x(P)}</p>`:""}
|
|
873
|
+
${c?`<button type="button" class="link" data-act="ref-skip">I don't have this</button>`:""}`;const d=N.querySelector(".ref-value");d.addEventListener("input",()=>{I=d.value,P="",Ee=!1}),d.addEventListener("keydown",v=>{v.key==="Enter"&&(v.preventDefault(),T.click())}),(g=N.querySelector(".ref-kind"))==null||g.addEventListener("change",v=>{var F;w=v.target.value,P="",ge(),(F=N.querySelector(".ref-value"))==null||F.focus()}),(C=N.querySelector('[data-act="ref-skip"]'))==null||C.addEventListener("click",()=>{_=!0,w=null,I="",P="",Ee=!1,ge(),z("")}),d.focus()}function ma(){return m.policy==="off"||!m.fields.length||it().length||$e().length?!1:!_||m.policy==="required"}T.addEventListener("click",async()=>{const a=A.value;if(!a.trim()){z("Please describe what went wrong."),A.classList.add("invalid"),A.focus(),setTimeout(()=>A.classList.remove("invalid"),500);return}if(ma()){w=w||m.fields[0].key,ge(),z("");return}if(w&&I.trim()){const d=m.fields.find(g=>g.key===w);if(!Ee&&d&&!Ko(d,I)){P=`That does not look like a ${d.label.toLowerCase()}. Press Send again to use it anyway.`,Ee=!0,ge();return}}b=!0,z(""),de();const c=T.innerHTML;T.innerHTML='<span class="spinner"></span>Sending…';try{const d=await o.report({title:a,description:k("#bc-desc").value,priority:y,references:$e(),attachments:h.filter(g=>g.status==="ready").map(g=>({type:g.kind,storageKey:g.storageKey,mime:g.mime}))});if(d!=null&&d.cancelled){b=!1,T.innerHTML=c,de();return}ot=!0,clearTimeout(U),await ke,r.drafts!==!1&&await Xe(De,null).catch(()=>{}),xn(d)}catch(d){b=!1,T.innerHTML=c,z(d.message.replace("[BugCatch] ","")),de(),Z.mode!=="off"&&It().catch(()=>{})}}),(Mn=f.querySelector('[data-act="history"]'))==null||Mn.addEventListener("click",kn);let ze=[],st="",Et=null,Ve=null;function mn(){r.knownIssues!==!1&&o.knownIssues().then(a=>{ze=a,Ke()}).catch(()=>{})}let bn=null;function ba(a){if(r.knownIssues===!1)return;clearTimeout(bn),Ve==null||Ve.abort();const c=(a||"").trim();if(c.length<3){mn();return}bn=setTimeout(()=>{Ve=new AbortController,o.matchKnownIssues(c,{signal:Ve.signal}).then(d=>{d.length&&(ze=d,Ke())}).catch(()=>{})},250)}function Ke(){if(!ze.length){$.hidden=!0,$.innerHTML="";return}$.hidden=!1,$.innerHTML=`
|
|
865
874
|
<p class="known-h">Already reported</p>
|
|
866
875
|
${ze.map(a=>`
|
|
867
876
|
<div class="issue ${a.joined?"is-joined":""}">
|
|
@@ -879,7 +888,7 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
879
888
|
<button class="ghost" type="button" data-join-confirm="${x(a.id)}">Follow</button>
|
|
880
889
|
</div>`:""}
|
|
881
890
|
`).join("")}
|
|
882
|
-
${st?`<p class="err">${x(st)}</p>`:""}`}function ya(a){const c=a.status==="IN_PROGRESS"?"Being worked on now":"Not fixed yet",d=a.affectedCount===0?"":` · ${a.affectedCount} ${a.affectedCount===1?"person has":"people have"} said this is happening to them`;return`${c} · reported ${et(a.since)}${d}`}$.addEventListener("click",async a=>{var v,
|
|
891
|
+
${st?`<p class="err">${x(st)}</p>`:""}`}function ya(a){const c=a.status==="IN_PROGRESS"?"Being worked on now":"Not fixed yet",d=a.affectedCount===0?"":` · ${a.affectedCount} ${a.affectedCount===1?"person has":"people have"} said this is happening to them`;return`${c} · reported ${et(a.since)}${d}`}$.addEventListener("click",async a=>{var v,F,O,W,ee;const c=a.target.closest("[data-join]"),d=a.target.closest("[data-join-confirm]");if(!c&&!d)return;const g=(d||c).getAttribute(d?"data-join-confirm":"data-join");st="";const C=((F=(v=$.querySelector(".join-email"))==null?void 0:v.value)==null?void 0:F.trim())||((O=o.signedInAs())==null?void 0:O.email)||((W=o.config.user)==null?void 0:W.email);if(!C){Et=g,Ke(),(ee=$.querySelector(".join-email"))==null||ee.focus();return}try{const pe=await o.meToo(g,{email:C});Et=null,ze=ze.map(V=>V.id===g?{...V,joined:!0,affectedCount:pe.affectedCount??V.affectedCount}:V),Ke()}catch(pe){st=pe.message.replace("[BugCatch] ",""),Ke()}}),mn(),A.addEventListener("input",()=>ba(A.value));let yn=!1;function wn(){o.callKind().then(a=>{a&&(yn=!0,L.hidden=$t())}).catch(()=>{})}wn();let Z={mode:o.lastLoginMode||"off",signedIn:null},J="idle",Oe=((Ln=o.config.user)==null?void 0:Ln.email)||"",He="",G=!1,ue="";const $t=()=>Z.mode==="required"&&!Z.signedIn;function wa(){const a=$t();D.hidden=a,T.hidden=a,se&&(se.hidden=a),a?L.hidden=!0:yn&&(L.hidden=!1)}function va(){var c;if(Z.mode==="off"){j.hidden=!0,j.innerHTML="";return}j.hidden=!1,j.classList.toggle("asking",J!=="idle");const a=ue?`<div class="after err">${x(ue)}</div>`:"";if(J==="idle"){if(Z.signedIn){j.innerHTML=`<span class="who">Signed in as <strong>${x(Z.signedIn.email)}</strong></span><button type="button" class="link" data-act="signout">Sign out</button>`;return}const d=(c=o.config.user)==null?void 0:c.email;j.innerHTML=`<span class="who">${Z.mode==="required"?"Sign in to report a bug here.":d?`Reporting as <strong>${x(d)}</strong>.`:"Reporting anonymously — sign in and we can tell you what happens next."}</span><button type="button" class="link" data-act="signin">Sign in</button>`;return}if(J==="email"){j.innerHTML=`
|
|
883
892
|
<p class="why">Sign in with any email address — we'll send you a code.
|
|
884
893
|
It's how you hear back about this report${Z.mode==="required"?", and this project asks for it":""}.</p>
|
|
885
894
|
<div class="row">
|
|
@@ -891,7 +900,7 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
891
900
|
</button>
|
|
892
901
|
</div>
|
|
893
902
|
${a}
|
|
894
|
-
${Z.mode==="optional"?'<div class="after"><button type="button" class="link" data-act="skip">Not now</button></div>':""}`;return}
|
|
903
|
+
${Z.mode==="optional"?'<div class="after"><button type="button" class="link" data-act="skip">Not now</button></div>':""}`;return}j.innerHTML=`
|
|
895
904
|
<p class="why">We sent a code to <strong>${x(Oe)}</strong>. It expires in ten minutes.</p>
|
|
896
905
|
<div class="row">
|
|
897
906
|
<input type="text" class="code" data-fld="code" value="${x(He)}"
|
|
@@ -905,7 +914,7 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
905
914
|
<div class="after">
|
|
906
915
|
<button type="button" class="link" data-act="resend" ${G?"disabled":""}>Send it again</button>
|
|
907
916
|
<button type="button" class="link" data-act="signin-back" ${G?"disabled":""}>Use another address</button>
|
|
908
|
-
</div>`}function le({focus:a=!1}={}){var d;if(va(),wa(),!a||G)return;const c=
|
|
917
|
+
</div>`}function le({focus:a=!1}={}){var d;if(va(),wa(),!a||G)return;const c=j.querySelector("[data-fld]");c&&(c.focus(),(d=c.setSelectionRange)==null||d.call(c,c.value.length,c.value.length))}j.addEventListener("input",a=>{const c=a.target.closest("[data-fld]");c&&(c.dataset.fld==="email"?Oe=c.value:He=c.value)}),j.addEventListener("keydown",a=>{a.key!=="Enter"||!a.target.closest("[data-fld]")||(a.preventDefault(),J==="email"?Tt():vn())});async function Tt({resent:a=!1}={}){const c=Oe.trim();if(!c){ue="Enter the address to send the code to.",le({focus:!0});return}G=!0,ue="",le();try{await o.signIn(c),Oe=c,a||(He=""),J="code"}catch(d){ue=d.message}finally{G=!1,le({focus:!0})}}async function vn(){const a=He.trim();if(!a){ue="Enter the code we emailed you.",le({focus:!0});return}G=!0,ue="",le();try{const c=await o.confirmSignIn(Oe.trim(),a);Z.signedIn=c,J="idle",He="",z(""),wn()}catch(c){ue=c.message}finally{G=!1,le({focus:J!=="idle"})}}j.addEventListener("click",async a=>{const c=a.target.closest("button[data-act]");if(!c)return;const d=c.dataset.act;if(d==="signin"){J="email",ue="",le({focus:!0});return}if(d==="skip"){J="idle",ue="",le();return}if(d==="signin-back"){J="email",ue="",He="",le({focus:!0});return}if(d==="code"){Tt();return}if(d==="resend"){Tt({resent:!0});return}if(d==="confirm"){vn();return}if(d==="signout"){G=!0,le();try{await o.signOut()}finally{Z.signedIn=null,G=!1,J=Z.mode==="required"?"email":"idle",le({focus:J!=="idle"})}}});async function It({announce:a=!1}={}){const c=await o.loginState();Z={mode:c.mode,signedIn:c.signedIn},o.lastLoginMode=c.mode,$t()&&J==="idle"&&(J="email"),Z.signedIn&&(J="idle"),a&&c.signedOutReason&&z(c.signedOutReason,"info"),le()}It({announce:!0}).catch(()=>{}),L.addEventListener("click",async()=>{b=!0,z(""),de(),L.disabled=!0,L.innerHTML='<span class="spinner"></span>Ringing…';try{const a=await o.startCall();xa(a)}catch(a){b=!1,L.disabled=!1,L.textContent="Talk to the team",de(),a.filed?xn(a.filed,{callFailed:a.reason||"The call could not be started."}):(z(a.message.replace("[BugCatch] ","")),Z.mode!=="off"&&It().catch(()=>{}))}});function xa(a){const c=f.querySelector(".panel"),d=a!=null&&a.bugId?String(a.bugId).slice(0,8):null;c.innerHTML=`
|
|
909
918
|
<div class="call">
|
|
910
919
|
<div class="call-head">
|
|
911
920
|
<span class="call-dot" aria-hidden="true"></span>
|
|
@@ -918,79 +927,83 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
918
927
|
<span class="spacer"></span>
|
|
919
928
|
<button class="primary" type="button" data-act="hangup">Cancel</button>
|
|
920
929
|
</div>
|
|
921
|
-
</div>`;const
|
|
930
|
+
</div>`;const g=c.querySelector(".call-state"),C=c.querySelector(".call-dot"),v={ringing:"Ringing the team…",connecting:"Someone answered — connecting…",connected:"Connected",missed:"Nobody was free",ended:"Call ended",failed:"The call dropped"},F=["ended","failed","missed"],O=o.on("call",({state:W})=>{if(g.textContent=v[W]||W,C.classList.toggle("off",F.includes(W)),F.includes(W)&&(c.querySelector('[data-act="hangup"]').textContent="Close",W==="missed")){const ee=c.querySelector(".call-note");ee&&(ee.textContent="Nobody was free to pick up just now. Your report is filed and the team will reply in the chat.")}});c.querySelector('[data-act="hangup"]').addEventListener("click",()=>{O(),o.endCall(),ce()})}function xn(a,{callFailed:c=null}={}){var v;const d=a!=null&&a.id?String(a.id).slice(0,8):null,g=(v=a==null?void 0:a.estimate)!=null&&v.label?String(a.estimate.label):null,C=c?`<p class="eta">${x(c)} Your report is filed, and the team will reply in the chat.</p>`:"";f.querySelector(".panel").innerHTML=`
|
|
922
931
|
<div class="done">
|
|
923
|
-
<div class="tick">${
|
|
932
|
+
<div class="tick">${Q.check}</div>
|
|
924
933
|
<h3>Thanks — that's on its way.</h3>
|
|
925
934
|
<p>${d?`Filed as <code>${x(d)}</code>.`:"The team has what they need to reproduce it."}</p>
|
|
926
935
|
${C}
|
|
927
|
-
${
|
|
928
|
-
</div>`,setTimeout(ce,C?6e3:
|
|
936
|
+
${g?`<p class="eta">Reports like this usually take <strong>${x(g)}</strong>. We'll let you know when it moves.</p>`:""}
|
|
937
|
+
</div>`,setTimeout(ce,C?6e3:g?4e3:2e3)}async function kn(){const a=f.querySelector(".panel");a.innerHTML=`
|
|
929
938
|
<div class="head">
|
|
930
|
-
<div class="mark">${
|
|
939
|
+
<div class="mark">${Q.bug}</div>
|
|
931
940
|
<div class="titles">
|
|
932
941
|
<h2>Your reports</h2>
|
|
933
942
|
<p>Everything you've reported, and where each one got to.</p>
|
|
934
943
|
</div>
|
|
935
|
-
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${
|
|
944
|
+
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${Q.close}</button>
|
|
936
945
|
</div>
|
|
937
|
-
<div class="history"><div class="empty">Loading…</div></div>`,a.querySelector('[data-act="close"]').addEventListener("click",ce);let c=[];try{({reports:c}=await o.myReports())}catch{a.querySelector(".history").innerHTML=`<div class="empty">Couldn't load your reports just now.</div>`;return}const d=a.querySelector(".history");if(d){d.innerHTML=c.length?c.map(
|
|
938
|
-
<button class="row" type="button" data-report="${x(
|
|
946
|
+
<div class="history"><div class="empty">Loading…</div></div>`,a.querySelector('[data-act="close"]').addEventListener("click",ce);let c=[];try{({reports:c}=await o.myReports())}catch{a.querySelector(".history").innerHTML=`<div class="empty">Couldn't load your reports just now.</div>`;return}const d=a.querySelector(".history");if(d){d.innerHTML=c.length?c.map(g=>`
|
|
947
|
+
<button class="row" type="button" data-report="${x(g.id)}">
|
|
939
948
|
<span class="who">
|
|
940
|
-
<span class="ttl">${x(
|
|
941
|
-
<span class="sub">${x(
|
|
949
|
+
<span class="ttl">${x(g.title)}</span>
|
|
950
|
+
<span class="sub">${x(g.reference)} · ${x(et(g.createdAt))}</span>
|
|
942
951
|
</span>
|
|
943
|
-
<span class="pill ${x(String(
|
|
944
|
-
</button>`).join(""):`<div class="empty">You haven't reported anything yet.</div>`;for(const
|
|
952
|
+
<span class="pill ${x(String(g.status).toLowerCase())}">${x(wt(g.status))}</span>
|
|
953
|
+
</button>`).join(""):`<div class="empty">You haven't reported anything yet.</div>`;for(const g of d.querySelectorAll("[data-report]"))g.addEventListener("click",()=>Sn(g.dataset.report))}}async function Sn(a){var v;const c=f.querySelector(".panel");c.innerHTML=`
|
|
945
954
|
<div class="head">
|
|
946
|
-
<button class="icon-btn back" type="button" data-act="back" aria-label="Back to your reports">${
|
|
955
|
+
<button class="icon-btn back" type="button" data-act="back" aria-label="Back to your reports">${Q.back}</button>
|
|
947
956
|
<div class="titles">
|
|
948
957
|
<h2>Your report</h2>
|
|
949
958
|
<p>Everything that has happened, and a way to answer.</p>
|
|
950
959
|
</div>
|
|
951
|
-
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${
|
|
960
|
+
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${Q.close}</button>
|
|
952
961
|
</div>
|
|
953
|
-
<div class="history"><div class="empty">Loading…</div></div>`,c.querySelector('[data-act="close"]').addEventListener("click",ce),c.querySelector('[data-act="back"]').addEventListener("click",
|
|
962
|
+
<div class="history"><div class="empty">Loading…</div></div>`,c.querySelector('[data-act="close"]').addEventListener("click",ce),c.querySelector('[data-act="back"]').addEventListener("click",kn);let d=null;try{d=await o.myReport(a)}catch{d=null}const g=c.querySelector(".history");if(!g||!c.querySelector('[data-act="back"]'))return;if(!d){g.innerHTML=`<div class="empty">Couldn't load that report just now.</div>`;return}be=a,o.markReportRead(a),g.classList.add("chatting"),g.innerHTML=`
|
|
954
963
|
<div class="report-head">
|
|
955
964
|
<span class="ttl">${x(d.title)}</span>
|
|
956
965
|
<span class="sub">${x(d.reference)} · ${x(d.project||"")}</span>
|
|
957
966
|
<span class="pill ${x(String(d.status).toLowerCase())}">${x(wt(d.status))}</span>
|
|
958
967
|
${(v=d.estimate)!=null&&v.label?`<span class="eta-line">Usually takes ${x(String(d.estimate.label))}</span>`:""}
|
|
959
968
|
</div>
|
|
960
|
-
<div class="thread">${
|
|
969
|
+
<div class="thread">${on(d.timeline)}</div>`;const C=g.querySelector(".thread");yt(C),Cn(g,d),d.canReply&&ka(g,C,a)}function Cn(a,c){var g,C;if((g=a.querySelector(".fix-verification"))==null||g.remove(),!c.resolvedAt||!["RESOLVED","CLOSED"].includes(c.status))return;const d=document.createElement("div");d.className="fix-verification",c.verification?d.textContent=c.verification==="CONFIRMED"?"You confirmed that this fix works.":"Your feedback was recorded.":(d.innerHTML='<p>Does the fix work for you?</p><textarea maxlength="4000" aria-label="Fix feedback" placeholder="What happens when you try again? (optional)"></textarea><button type="button" data-result="CONFIRMED">It works now</button> <button type="button" data-result="STILL_HAPPENING">Still happening</button><p class="feedback-status" role="status"></p>',d.querySelectorAll("[data-result]").forEach(v=>{v.onclick=async()=>{d.querySelectorAll("button").forEach(F=>{F.disabled=!0});try{await o.verifyFix(c.id,{result:v.dataset.result,resolvedAt:c.resolvedAt,note:d.querySelector("textarea").value}),await Sn(c.id)}catch(F){d.querySelector(".feedback-status").textContent=F.message,d.querySelectorAll("button").forEach(O=>{O.disabled=!1})}}})),(C=a.querySelector(".report-head"))==null||C.after(d)}async function Mt(a){const c=f.querySelector(".history.chatting"),d=c==null?void 0:c.querySelector(".thread");if(!d||be!==a)return;let g=null;try{g=await o.myReport(a)}catch{}if(!g||be!==a)return;Cn(c,g);const C=ta(d);d.innerHTML=on(g.timeline),C&&yt(d);const v=c.querySelector(".report-head .pill");v&&(v.className=`pill ${String(g.status).toLowerCase()}`,v.textContent=wt(g.status))}function ka(a,c,d){const g=document.createElement("div");g.className="composer",g.innerHTML=`
|
|
961
970
|
<div class="staged" hidden></div>
|
|
962
971
|
<div class="row">
|
|
963
972
|
<div class="tools">
|
|
964
|
-
<button class="tool" type="button" data-act="attach" title="Attach a file" aria-label="Attach a file">${
|
|
965
|
-
<button class="tool" type="button" data-act="voice" title="Record a voice note" aria-label="Record a voice note">${
|
|
966
|
-
<button class="tool" type="button" data-act="livecall" title="Call the team" aria-label="Call the team" hidden>${
|
|
973
|
+
<button class="tool" type="button" data-act="attach" title="Attach a file" aria-label="Attach a file">${Q.paperclip}</button>
|
|
974
|
+
<button class="tool" type="button" data-act="voice" title="Record a voice note" aria-label="Record a voice note">${Q.mic}</button>
|
|
975
|
+
<button class="tool" type="button" data-act="livecall" title="Call the team" aria-label="Call the team" hidden>${Q.phone}</button>
|
|
967
976
|
</div>
|
|
968
977
|
<textarea rows="1" placeholder="Write a reply…" aria-label="Write a reply"></textarea>
|
|
969
|
-
<button class="send" type="button" data-act="send" title="Send" aria-label="Send" disabled>${
|
|
978
|
+
<button class="send" type="button" data-act="send" title="Send" aria-label="Send" disabled>${Q.send}</button>
|
|
970
979
|
</div>
|
|
971
980
|
<div class="note" hidden></div>
|
|
972
|
-
<input type="file" hidden multiple accept="${
|
|
973
|
-
<span class="chip ${
|
|
974
|
-
<span class="nm">${x(
|
|
975
|
-
<span class="sz">${
|
|
976
|
-
<button type="button" data-drop="${
|
|
977
|
-
</span>`).join("");for(const
|
|
981
|
+
<input type="file" hidden multiple accept="${Dt.join(",")}">`,a.appendChild(g);const C=g.querySelector(".staged"),v=g.querySelector("textarea"),F=g.querySelector('[data-act="send"]'),O=g.querySelector('[data-act="voice"]'),W=g.querySelector('[data-act="livecall"]'),ee=g.querySelector("input[type=file]"),pe=g.querySelector(".note"),V=[];let Te=null,Y=!1;function ae(M,R=""){pe.hidden=!M,pe.className=`note ${R}`,pe.textContent=M||""}function Ie(){const M=V.filter(R=>R.storageKey);F.disabled=Y||!v.value.trim()&&!M.length,C.hidden=!V.length,C.innerHTML=V.map((R,he)=>`
|
|
982
|
+
<span class="chip ${R.storageKey?"":"uploading"}">
|
|
983
|
+
<span class="nm">${x(R.name)}</span>
|
|
984
|
+
<span class="sz">${R.storageKey?Me(R.size):"sending…"}</span>
|
|
985
|
+
<button type="button" data-drop="${he}" aria-label="Remove ${x(R.name)}">${Q.close}</button>
|
|
986
|
+
</span>`).join("");for(const R of C.querySelectorAll("[data-drop]"))R.addEventListener("click",()=>{V.splice(Number(R.dataset.drop),1),Ie()})}async function Bn(M,R,he){const H={name:he,size:M.size,storageKey:null};V.push(H),Ie();try{const{storageKey:Bt,mime:Ca}=await o.uploadAttachment(M,R);H.storageKey=Bt,H.mime=Ca}catch(Bt){V.splice(V.indexOf(H),1),ae(Bt.message||"That file could not be sent.","err")}Ie()}v.addEventListener("input",()=>{v.style.height="auto",v.style.height=`${Math.min(v.scrollHeight,120)}px`,Ie()}),v.addEventListener("keydown",M=>{M.key==="Enter"&&!M.shiftKey&&!M.isComposing&&(M.preventDefault(),Lt())}),g.querySelector('[data-act="attach"]').addEventListener("click",()=>ee.click()),ee.addEventListener("change",()=>{ae("");for(const M of ee.files){if(M.size>o.config.maxAttachmentBytes){ae(`${M.name} is larger than ${Me(o.config.maxAttachmentBytes)}.`,"err");continue}Bn(M,M.type,M.name)}ee.value=""}),Zn()||(O.disabled=!0,O.title="This browser cannot record audio"),O.addEventListener("click",async()=>{if(Te){const M=Te;Te=null,O.classList.remove("recording"),O.innerHTML=Q.mic,ae("");const{blob:R,mime:he}=await M.stop();R.size&&Bn(R,he,"Voice note");return}try{ae(""),Te=await no({maxMs:o.config.maxRecordingMs,onTick:M=>ae(`Recording — ${We(M)}. Tap the mic to stop.`),onAutoStop:()=>O.click()}),O.classList.add("recording"),O.innerHTML=Q.stopSquare}catch{Te=null,ae("The microphone is not available — check the browser permission.","err")}}),o.canCallTeam(d).then(M=>{M&&(W.hidden=!1)}).catch(()=>{}),W.addEventListener("click",async()=>{W.disabled=!0,ae("");try{const M=await o.startLiveCall(d);Sa(a,c,M)}catch(M){ae(M.message.replace("[BugCatch] ",""),"err")}finally{W.disabled=!1}}),F.addEventListener("click",Lt),c.addEventListener("click",M=>{var he,H;const R=(H=(he=M.target).closest)==null?void 0:H.call(he,"[data-quick]");!R||Y||(v.value=R.dataset.quick,Lt())});async function Lt(){var he;const M=v.value.trim(),R=V.filter(H=>H.storageKey);if(!(Y||!M&&!R.length)){Y=!0,Ie(),ae(""),c.insertAdjacentHTML("beforeend",an({from:"reporter",body:M,at:new Date().toISOString(),attachments:R.map(H=>({type:"FILE",name:H.name,size:H.size}))},"pending")),yt(c);try{await Kt({apiBase:o.config.apiBase,bugId:d,body:M,attachments:R.map(H=>({storageKey:H.storageKey,mime:H.mime,name:H.name,size:H.size}))}),v.value="",v.style.height="auto",V.length=0,await Mt(d)}catch(H){(he=c.querySelector(".msg-row.pending"))==null||he.classList.replace("pending","failed"),ae(H.message||"That could not be sent — try again.","err")}finally{Y=!1,Ie()}}}Ie()}function Sa(a,c,d){const g=document.createElement("div");g.className="livecall",g.innerHTML=`
|
|
978
987
|
<span class="call-dot" aria-hidden="true"></span>
|
|
979
988
|
<span class="who" role="status" aria-live="polite">Calling the team…</span>
|
|
980
989
|
<span class="secs" hidden></span>
|
|
981
990
|
<button class="act" type="button" data-act="mute" hidden>Mute</button>
|
|
982
|
-
<button class="act danger" type="button" data-act="hangup">Cancel</button>`,a.insertBefore(
|
|
991
|
+
<button class="act danger" type="button" data-act="hangup">Cancel</button>`,a.insertBefore(g,c);const C=g.querySelector(".who"),v=g.querySelector(".secs"),F=g.querySelector(".call-dot"),O=g.querySelector('[data-act="mute"]'),W=g.querySelector('[data-act="hangup"]');let ee=null;const pe=()=>{ee&&(clearInterval(ee),ee=null)},V=Y=>{pe(),F.classList.add("off"),g.classList.add("over"),C.textContent=Y,v.hidden=!0,O.hidden=!0,W.textContent="Dismiss",W.classList.remove("danger")},Te=o.on("call",({state:Y})=>{if(Y==="ringing"&&(C.textContent="Calling the team…"),Y==="connecting"&&(C.textContent="Someone answered — connecting…"),Y==="connected"){C.textContent="You're on a call with the team",O.hidden=!1,v.hidden=!1;const ae=Date.now();pe(),ee=setInterval(()=>{v.textContent=We(Math.floor((Date.now()-ae)/1e3))},1e3),v.textContent="0s"}Y==="missed"&&V("Nobody was free. Send a message instead and the team will pick it up."),Y==="ended"&&V("Call ended."),Y==="failed"&&V("The call dropped.")});O.addEventListener("click",()=>{const Y=d.setMuted(!d.isMuted());O.textContent=Y?"Unmute":"Mute",C.textContent=Y?"You're muted":"You're on a call with the team"}),W.addEventListener("click",()=>{Te(),pe(),o.endCall(),g.remove(),Mt(be)})}let be=null;return Se=o.on("update",a=>{!be||(a==null?void 0:a.bugId)!==be||(o.markReportRead(be),Mt(be))}),t.appendChild(f),de(),A.focus(),{destroy:Ue,close:ce}}function on(t){const e=t||[];return e.length?e.map(n=>{var o,i,r,s;return n.from?an({from:n.from,author:(o=n.reply)==null?void 0:o.author,automated:(i=n.reply)==null?void 0:i.automated,body:(r=n.reply)==null?void 0:r.body,at:n.at,attachments:(s=n.reply)==null?void 0:s.attachments}):Go(n)}).join(""):""}function Go(t){return`
|
|
983
992
|
<div class="sys k-${x(t.kind)}">
|
|
984
993
|
<span class="dot" aria-hidden="true"></span>${x(t.summary||"")}
|
|
985
994
|
· ${x(et(t.at))}
|
|
986
|
-
</div>`}function
|
|
995
|
+
</div>`}function an(t,e=""){const n=t.from==="reporter",o=t.body||"",i=t.attachments||[],r=!n&&!!t.automated,s=o?`<span class="msg-text">${x(o)}</span>`:"",l=i.length?`<div class="att">${i.map(ea).join("")}</div>`:"";let u="";r?u='<span class="msg-who auto">Automatic reply</span>':!n&&t.author&&(u=`<span class="msg-who">${x(t.author)}</span>`);const h=r&&/reply "yes" or "no"/i.test(o)?`<div class="quick" role="group" aria-label="Answer">
|
|
996
|
+
<button type="button" data-quick="Yes, this is the problem">Yes, that's it</button>
|
|
997
|
+
<button type="button" data-quick="No, that is not the problem">No, it's something else</button>
|
|
998
|
+
</div>`:"";return`
|
|
987
999
|
<div class="msg-row ${n?"mine":"theirs"} ${r?"auto":""} ${e}">
|
|
988
1000
|
${u}
|
|
989
1001
|
<div class="bubble ${o?"":"silent"}">${s}${l}</div>
|
|
1002
|
+
${h}
|
|
990
1003
|
<span class="msg-when">${x(et(t.at))}</span>
|
|
991
1004
|
</div>`}function ea(t){const e=x(t.name||"attachment");if(!t.url)return`<span class="file"><span class="nm">${e}</span></span>`;const n=x(t.url);return t.type==="SCREENSHOT"?`<a href="${n}" target="_blank" rel="noopener noreferrer"><img src="${n}" alt="${e}" loading="lazy"></a>`:t.type==="AUDIO"?`<audio controls preload="metadata" src="${n}"></audio>`:t.type==="VIDEO"?`<video controls preload="metadata" src="${n}"></video>`:`
|
|
992
1005
|
<a class="file" href="${n}" target="_blank" rel="noopener noreferrer" download>
|
|
993
1006
|
<span class="nm">${e}</span>
|
|
994
1007
|
${t.size?`<span class="sz">${x(Me(t.size))}</span>`:""}
|
|
995
|
-
</a>`}function ta(t){return t.scrollHeight-t.scrollTop-t.clientHeight<40}function yt(t){t.scrollTop=t.scrollHeight}function wt(t){return{OPEN:"Open",IN_PROGRESS:"In progress",RESOLVED:"Fixed",CLOSED:"Closed"}[t]||String(t||"").toLowerCase()}function et(t){const e=new Date(t).getTime();if(!Number.isFinite(e))return"";const n=Math.floor((Date.now()-e)/864e5);if(n<=0)return"today";if(n===1)return"yesterday";if(n<30)return`${n} days ago`;const o=Math.floor(n/30);return o===1?"a month ago":`${o} months ago`}function x(t){return String(t).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}const an=8e3;function na(t=an){const e=window.AudioContext||window.webkitAudioContext;try{return new e({sampleRate:t})}catch{return new e}}async function oa(t){if(t.state==="suspended")try{await t.resume()}catch{}}function aa(t,e,n){const o=e/n,i=new Float32Array(Math.floor(t.length/o));for(let r=0;r<i.length;r++){const s=Math.floor(r*o),l=Math.min(Math.floor((r+1)*o),t.length);let u=0;for(let g=s;g<l;g++)u+=t[g];i[r]=l>s?u/(l-s):0}return i}const ra=132,rn=32635;function ia(t){const e=new Uint8Array(t.length);for(let n=0;n<t.length;n++){const o=Math.max(-1,Math.min(1,t[n]));let i=Math.round(o*32767);const r=i<0?128:0;r&&(i=-i),i>rn&&(i=rn),i+=ra;let s=7;for(let u=16384;!(i&u)&&s>0;s--,u>>=1);const l=i>>s+3&15;e[n]=~(r|s<<4|l)&255}return e}const sa=512;function ca(t,e,n,o=an){const i=t.createMediaStreamSource(e),r=t.createScriptProcessor(sa,1,1);r.onaudioprocess=l=>{const u=l.inputBuffer.getChannelData(0),g=t.sampleRate===o?u:aa(u,t.sampleRate,o);n(ia(g))},i.connect(r);const s=t.createGain();return s.gain.value=0,r.connect(s),s.connect(t.destination),{stop(){r.onaudioprocess=null;try{i.disconnect()}catch{}try{r.disconnect()}catch{}try{s.disconnect()}catch{}}}}const la="voiceai.realtime.v1",da=[{urls:"stun:stun.l.google.com:19302"}];function vt(){return navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:1}})}function xt(){var t;return typeof window<"u"&&typeof window.RTCPeerConnection=="function"&&!!((t=navigator.mediaDevices)!=null&&t.getUserMedia)}async function sn({realtimeUrl:t,stream:e,ringsUntil:n,onState:o,onAudioBlocked:i,onMicrophone:r}){const s=(m,w)=>{try{o==null||o(m,w)}catch{}},l=m=>{try{i==null||i(m)}catch{}},u=m=>{try{r==null||r(m)}catch{}};if(!xt()){const m=new Error("[BugCatch] this browser cannot make live calls.");throw s("failed",{reason:"unsupported"}),m}let g=e;if(!g)try{g=await vt()}catch(m){throw s("failed",{reason:"microphone",error:String((m==null?void 0:m.name)||m)}),m}let y;try{y=await ua(t)}catch(m){throw ln(g),s("failed",{reason:"connect"}),m}let p=null,b=null,h=!1,k=null,A=null,ie=null,S=!1,E=null,T=null,L=!1;const X=[];let q=!1,Q=!1,D=!1,$=null,se=null,ne=0;const De=2e3,xe=5e3,ot=3e4,ke=4,N=(m,w)=>{if(!h){h=!0,k&&(clearTimeout(k),k=null),ce(),T==null||T(),T=null,at(),E==null||E(),E=null;try{p==null||p.close()}catch{}ln(g),b&&(b.srcObject=null,b.remove(),b=null);try{y.readyState===WebSocket.OPEN&&y.close(1e3,"call over")}catch{}s(m,w)}},oe=m=>{y.readyState===WebSocket.OPEN&&y.send(JSON.stringify(m))},Le=async()=>{if(L||ie||h||!A||!A.audio&&!A.transcript)return;L=!0;const m=A.encoding||"mulaw";if(m!=="mulaw"){cn(`this call is kept as ${m}, which this SDK cannot produce.`);return}const w=Number(A.sample_rate)||8e3;try{const I=na(w);if(await oa(I),h){try{I.close()}catch{}return}const K=ca(I,g,P=>{y.readyState===WebSocket.OPEN&&y.send(P)},w);ie={context:I,tap:K}}catch(I){cn(`could not send the copy this call is keeping: ${String((I==null?void 0:I.message)||I)}`)}};function at(){if(L=!1,!ie)return;const{context:m,tap:w}=ie;ie=null;try{w.stop()}catch{}try{m.close()}catch{}}function Ne(){var w;if(!b||h)return;let m;try{m=(w=b.play)==null?void 0:w.call(b)}catch{Be();return}if(!m||typeof m.then!="function"){ge();return}m.then(ge,Be)}function ge(){E==null||E(),E=null,S&&(S=!1,l(!1))}function Be(){h||(S||(S=!0,l(!0)),kt())}function kt(){if(E||typeof window>"u"||typeof window.addEventListener!="function")return;const m=()=>Ne(),w=["pointerdown","keydown","touchstart"];for(const I of w)window.addEventListener(I,m,{capture:!0,passive:!0});E=()=>{for(const I of w)try{window.removeEventListener(I,m,{capture:!0})}catch{}}}const Ae=m=>{p=new RTCPeerConnection({iceServers:m!=null&&m.length?m:da});for(const w of g.getAudioTracks())p.addTrack(w,g);T=de(),p.onicecandidate=w=>{w.candidate&&oe({type:"signal",signal:{kind:"candidate",payload:w.candidate.toJSON()}})},p.ontrack=w=>{var K;const[I]=w.streams;I&&(b||(b=document.createElement("audio"),b.autoplay=!0,b.playsInline=!0,(K=b.setAttribute)==null||K.call(b,"playsinline",""),b.style.cssText="position:fixed;width:0;height:0;opacity:0;pointer-events:none",document.body.appendChild(b)),b.srcObject=I,Ne())},p.onconnectionstatechange=Se,p.oniceconnectionstatechange=Se};function Se(){if(!p||h)return;const m=p.connectionState||p.iceConnectionState;if(m==="connected"||m==="completed"){Q=!0,ne=0,ce(),D=!1,s("connected");return}if(m==="disconnected"){if(!Q)return;Ue(De);return}if(m==="failed"){if(!Q){N("failed",{reason:"ice"});return}Ue(0)}}function Ue(m){h||(D||(D=!0,s("reconnecting"),se=setTimeout(()=>N("failed",{reason:"network"}),ot)),!$&&($=setTimeout(Re,m)))}function ce(){$&&(clearTimeout($),$=null),se&&(clearTimeout(se),se=null)}async function Re(){if($=null,h||!p)return;const m=p.connectionState||p.iceConnectionState;if(!(m==="connected"||m==="completed")){if(!q){oe({type:"signal",signal:{kind:"restart",payload:{}}}),$=setTimeout(Re,xe);return}ne>=ke||(ne+=1,await z(),$=setTimeout(Re,xe))}}async function z(){if(!(h||!p))try{const m=await p.createOffer({iceRestart:!0});await p.setLocalDescription(m),oe({type:"signal",signal:{kind:"offer",payload:p.localDescription.toJSON()}})}catch{}}function de(){let w=null,I=!1;const K=P=>{if(w&&(clearTimeout(w),w=null),P){if(!I)return;I=!1,u(!0);return}I||(w=setTimeout(()=>{w=null,!h&&(I=!0,u(!1))},600))};for(const P of g.getAudioTracks())P.onmute=()=>K(!1),P.onunmute=()=>K(!0),P.onended=()=>{w&&(clearTimeout(w),w=null),!I&&(I=!0,u(!1))};return()=>{w&&(clearTimeout(w),w=null);for(const P of g.getAudioTracks())P.onmute=null,P.onunmute=null,P.onended=null}}const rt=async()=>{try{const m=await p.createOffer();await p.setLocalDescription(m),oe({type:"signal",signal:{kind:"offer",payload:p.localDescription.toJSON()}})}catch{N("failed",{reason:"negotiation"})}},St=async m=>{try{await p.setRemoteDescription(new RTCSessionDescription(m));const w=await p.createAnswer();await p.setLocalDescription(w),oe({type:"signal",signal:{kind:"answer",payload:p.localDescription.toJSON()}}),await Qe()}catch{N("failed",{reason:"negotiation"})}},Qe=async()=>{for(;X.length;){const m=X.shift();try{await p.addIceCandidate(new RTCIceCandidate(m))}catch{}}};let Ce=Promise.resolve();y.onmessage=m=>{Ce=Ce.then(()=>Ct(m)).catch(()=>{})};const Ct=async m=>{var I,K,P,Ee,it;if(typeof m.data!="string")return;let w;try{w=JSON.parse(m.data)}catch{return}switch(w.type){case"session.created":{if(Ae((I=w.data)==null?void 0:I.ice_servers),A=((K=w.data)==null?void 0:K.capture)||null,(P=w.data)!=null&&P.peer_present){s("connecting"),Le();break}s("ringing"),je();break}case"peer.joined":{k&&(clearTimeout(k),k=null),s("connecting"),q=!!((Ee=w.data)!=null&&Ee.should_offer),q&&await rt(),Le();break}case"signal":{if(!p)break;const{kind:$e,payload:fe}=w.data||{};if($e==="offer")await St(fe);else if($e==="answer")try{await p.setRemoteDescription(new RTCSessionDescription(fe)),await Qe()}catch{N("failed",{reason:"negotiation"})}else if($e==="candidate")if(p.remoteDescription)try{await p.addIceCandidate(new RTCIceCandidate(fe))}catch{}else X.push(fe);else $e==="restart"&&q&&await z();break}case"peer.left":N("ended",{reason:"peer_left"});break;case"error":N("failed",{reason:"server",detail:(it=w.error)==null?void 0:it.detail});break;case"session.ended":N("ended",{reason:"server"});break}};y.onclose=()=>N("ended",{reason:"disconnected"}),y.onerror=()=>N("failed",{reason:"socket"});function je(){if(!n)return;const m=new Date(n).getTime()-Date.now();Number.isFinite(m)&&(k=setTimeout(()=>N("missed"),Math.max(0,m)))}return{hangUp(){oe({type:"session.end"}),N("ended",{reason:"hung_up"})},setMuted(m){for(const w of g.getAudioTracks())w.enabled=!m;return m},isMuted(){return g.getAudioTracks().every(m=>!m.enabled)}}}function ua(t){return new Promise((e,n)=>{let o;try{o=new WebSocket(t,la)}catch(i){n(i);return}o.onopen=()=>{o.onopen=null,o.onerror=null,e(o)},o.onerror=()=>{o.onopen=null,o.onerror=null,n(new Error("[BugCatch] could not connect the call."))}})}function cn(t){try{console.warn(`[BugCatch] ${t}`)}catch{}}function ln(t){var e;for(const n of((e=t==null?void 0:t.getTracks)==null?void 0:e.call(t))??[])try{n.stop()}catch{}}const tt={cycleMs:3e3,peak:.045,bursts:[{at:0,seconds:.4,hz:[440,660]},{at:.55,seconds:.4,hz:[440,660]}]};let dn=!1;if(typeof window<"u"&&window.addEventListener)for(const t of["pointerdown","keydown","touchstart"])window.addEventListener(t,()=>{dn=!0},{once:!0,capture:!0,passive:!0});function pa(){var t;try{return!!((t=navigator.userActivation)!=null&&t.hasBeenActive)}catch{return!1}}function ha(){if(!dn&&!pa())return()=>{};const t=typeof window<"u"&&(window.AudioContext||window.webkitAudioContext);if(!t)return()=>{};let e;try{e=new t}catch{return()=>{}}let n=!1,o=null;const i=[],r=({at:u,seconds:g,hz:y})=>{const p=e.currentTime+u,b=e.createGain();b.connect(e.destination),b.gain.setValueAtTime(0,p),b.gain.linearRampToValueAtTime(tt.peak,p+.02),b.gain.setValueAtTime(tt.peak,p+g-.06),b.gain.linearRampToValueAtTime(0,p+g);for(const h of y){const k=e.createOscillator();k.type="sine",k.frequency.value=h,k.connect(b),k.start(p),k.stop(p+g+.02),i.push(k)}},s=()=>{if(!n)try{tt.bursts.forEach(r)}catch{}},l=()=>{n||(s(),o=setInterval(s,tt.cycleMs))};return e.state==="running"?l():e.resume().then(l).catch(()=>{}),()=>{n=!0,o&&clearInterval(o);for(const u of i)try{u.stop()}catch{}try{e.close()}catch{}}}function fa(t){const e=Date.parse(t||"");return Number.isNaN(e)?0:Math.max(0,Math.round((e-Date.now())/1e3))}const un=["flex:1","padding:9px 12px","border:0","border-radius:8px","font:600 13px/1.4 inherit","cursor:pointer"].join(";");function ga({call:t,accent:e="#5b6ef5",position:n="bottom-right",onAnswer:o,onDecline:i,onExpire:r}){if(typeof document>"u"||!document.body)return()=>{};const[s,l]=String(n).split("-"),u=document.createElement("div");u.setAttribute("role","alertdialog"),u.setAttribute("aria-live","assertive"),u.setAttribute("aria-label",`${t.from||"Support"} is calling about ${t.reference}`),u.style.cssText=["position:fixed",`${s==="top"?"top":"bottom"}:20px`,`${l==="left"?"left":"right"}:20px`,"z-index:2147483647","width:300px","max-width:calc(100vw - 40px)","padding:14px","border-radius:12px","background:#1b1e26","color:#eceef2",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 18px 44px rgba(0,0,0,0.5)",`border:1px solid ${e}`,"opacity:0","transform:translateY(8px)","transition:opacity .2s ease,transform .2s ease"].join(";");const g=document.createElement("div");g.style.cssText="font-weight:600;font-size:14px;margin-bottom:2px",g.textContent=`${t.from||"Support"} is calling`;const y=document.createElement("div");y.style.cssText="color:#a4abba;margin-bottom:10px",y.textContent=t.project?`About your report ${t.reference} · ${t.project}`:`About your report ${t.reference}`;const p=document.createElement("div");p.style.cssText="color:#7d8598;font-size:12px;margin-bottom:10px";const b=document.createElement("button");b.type="button",b.textContent="Answer",b.style.cssText=`${un};background:${e};color:#fff`;const h=document.createElement("button");h.type="button",h.textContent="Not now",h.style.cssText=`${un};background:#2b2f3a;color:#c8cedb`;const k=document.createElement("div");if(k.style.cssText="display:flex;gap:8px",k.append(b,h),u.append(g,y,p),t.recorded){const L=document.createElement("div");L.style.cssText="color:#7d8598;font-size:12px;margin-bottom:10px",L.textContent="This call will be recorded.",u.append(L)}u.append(k),document.body.appendChild(u);const A=ha();let ie=!1,S=null;const E=()=>{ie||(ie=!0,S&&clearInterval(S),A(),u.style.opacity="0",u.style.transform="translateY(8px)",setTimeout(()=>u.remove(),250))},T=()=>{const L=fa(t.ringsUntil);if(p.textContent=L?`Ringing — ${L}s`:"The call has stopped ringing.",!L){E();try{r==null||r()}catch{}}};return T(),S=setInterval(T,1e3),b.addEventListener("click",()=>{E();try{o==null||o()}catch{}}),h.addEventListener("click",()=>{E();try{i==null||i()}catch{}}),requestAnimationFrame(()=>{u.style.opacity="1",u.style.transform="translateY(0)"}),E}const pn={name:"@sphoro/bugcatch-web-sdk",version:"0.14.1"},nt={apiBase:"http://localhost:3000",apiKey:null,projectId:null,consoleLimit:100,networkLimit:50,captureConsole:!0,captureNetwork:!0,captureErrors:!0,widget:!0,widgetPosition:"bottom-right",theme:"auto",accent:"#4F46E5",attachments:!0,maxAttachments:5,maxAttachmentBytes:25*1024*1024,maxRecordingMs:12e4,beforeSend:null,user:null,updates:!0,updateToast:!0,onUpdate:null,voice:!0,onCallState:null,onIncomingCall:null};class hn{constructor(){Rn(this,B);this.config={...nt},this.started=!1,this.teardown=[],this.consoleBuffer=Pe(nt.consoleLimit),this.networkBuffer=Pe(nt.networkLimit),this.stopWatching=null,this.notifier=null,this.call=null,this.callStarting=!1,this.ringing=null,this.listeners=new Map}init(e={}){if(this.started)return console.warn("[BugCatch] init() called twice — ignoring the second call."),this;if(this.config={...nt,...e},!this.config.apiKey)throw new Error("[BugCatch] apiKey is required.");if(!this.config.projectId)throw new Error("[BugCatch] projectId is required.");return this.consoleBuffer=Pe(this.config.consoleLimit),this.networkBuffer=Pe(this.config.networkLimit),this.config.captureConsole&&this.teardown.push(Pn(this.consoleBuffer)),this.config.captureNetwork&&this.teardown.push(_n(this.networkBuffer)),this.config.captureErrors&&this.teardown.push(Fn(this.consoleBuffer)),this.config.widget&&this.teardown.push(Xo(this)),this.config.updates&&re()&&(this.startWatching(),queueMicrotask(()=>V(this,B,ye).call(this))),this.started=!0,this}startWatching(){if(this.stopWatching)return this;this.stopWatching=Mo({apiBase:this.config.apiBase,onUpdate:n=>{if(n!=null&&n.incomingCall){V(this,B,zn).call(this,n);return}if(n!=null&&n.callWithdrawn){V(this,B,lt).call(this,n.callWithdrawn.callId);return}const o=yo(n);typeof this.config.onUpdate=="function"&&this.config.onUpdate(o),this.emit("update",o),V(this,B,ye).call(this)}}),this.teardown.push(()=>{var n;return(n=this.stopWatching)==null?void 0:n.call(this)}),this.teardown.push(()=>V(this,B,lt).call(this));const e=n=>{(n.key===Je||n.key===null)&&V(this,B,ye).call(this)};return window.addEventListener("storage",e),this.teardown.push(()=>window.removeEventListener("storage",e)),this}on(e,n){if(typeof n!="function")return()=>{};const o=this.listeners.get(e)||new Set;return o.add(n),this.listeners.set(e,o),()=>this.off(e,n)}off(e,n){var o;return(o=this.listeners.get(e))==null||o.delete(n),this}emit(e,n){for(const o of this.listeners.get(e)||[])try{o(n)}catch(i){console.error("[BugCatch] an update listener threw:",i)}}unreadUpdates(){return qe()}markUpdateRead(e){return wo(e),V(this,B,ye).call(this),this}markReportRead(e){return vo(e),V(this,B,ye).call(this),this}markUpdatesRead(){return Ut(),V(this,B,ye).call(this),this}async verifyFix(e,{result:n,resolvedAt:o,note:i}){const r=n==="STILL_HAPPENING"?await V(this,B,ct).call(this,{}):{};return Do({apiBase:this.config.apiBase,bugId:e,result:n,resolvedAt:o,note:i,metadata:r.metadata,logs:r.logs})}myReport(e){return So({apiBase:this.config.apiBase,bugId:e})}replyToReport(e,{body:n,attachments:o}={}){return Vt({apiBase:this.config.apiBase,bugId:e,body:n,attachments:o})}async canCallNow(){return!!await this.callKind()}async callKind(){return(await this.callKinds()).live?"live":null}async callKinds(){var n;const e={agent:!1,live:!1};return!this.config.voice||!((n=this.config.user)!=null&&n.email)?e:this.kinds!==void 0?this.kinds:(this.kinds=await Co({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.kinds)}canCall(e){return this.config.voice?Kt({apiBase:this.config.apiBase,bugId:e}):Promise.resolve(!1)}async startCall(e){var n;if(!this.config.voice)throw new Error("[BugCatch] calling is switched off.");if(this.call||this.callStarting)throw new Error("[BugCatch] a call is already running.");this.callStarting=!0;try{if(!await this.callKind())throw new Error((n=this.config.user)!=null&&n.email?"[BugCatch] calling is not available on this project.":"[BugCatch] a call needs to know who is calling — call identify() with an email first.");return await V(this,B,jn).call(this,e)}finally{this.callStarting=!1}}startLiveCall(e){return this.startCall(e)}canCallTeam(e){return this.config.voice?Kt({apiBase:this.config.apiBase,bugId:e}):Promise.resolve(!1)}endCall(){var e;return(e=this.call)==null||e.hangUp(),this.call=null,this}myReports(){return ko({apiBase:this.config.apiBase})}hasReports(){return!!re()}forgetReports(){var e;return(e=this.stopWatching)==null||e.call(this),this.stopWatching=null,this.endCall(),ve(),V(this,B,ye).call(this),this}identify(e){return this.config.user=e,this}async uploadAttachment(e,n,o){if(!this.started)throw new Error("[BugCatch] call init() first.");return oo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,blob:e,mime:n||(e==null?void 0:e.type),onProgress:o})}async report({title:e,description:n="",priority:o="MEDIUM",metadata:i={},attachments:r=[],references:s=[]}={}){if(!this.started)throw new Error("[BugCatch] call init() first.");if(!e||!e.trim())throw new Error("[BugCatch] a title is required.");const l=(r||[]).filter(b=>(b==null?void 0:b.storageKey)&&Fe(b.mime,_e)).map(b=>({type:b.type==="VIDEO"?"VIDEO":"SCREENSHOT",storageKey:b.storageKey,mime:Fe(b.mime,_e)}));let u=await V(this,B,ct).call(this,{title:e.trim(),description:n,priority:o,metadata:i,media:l,references:s});if(typeof this.config.beforeSend=="function"){const b=this.config.beforeSend(u);if(b===!1)return{cancelled:!0};b&&typeof b=="object"&&(u=b)}const g=he(this.config.projectId),y=await fetch(`${this.config.apiBase}/ingest/bugs`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":this.config.apiKey,...g!=null&&g.token?{"X-BugCatch-Session":g.token}:{}},body:JSON.stringify(u)});if(y.status===401&&g&&ft(this.config.projectId),!y.ok){let b="";try{const h=await y.json();b=Array.isArray(h.message)?h.message.join(", "):h.message||""}catch{}throw new Error(`[BugCatch] report failed (HTTP ${y.status})${b?": "+b:""}`)}const p=await y.json();return p.watchToken&&(mt(p.watchToken),this.config.updates&&this.startWatching()),p}loginState(){var e;return po({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:(e=he(this.config.projectId))==null?void 0:e.token})}referenceFields(){return this.refFields?this.refFields:(this.refFields=Po({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.refFields)}signedInAs(){const e=he(this.config.projectId);return e?{email:e.email,name:e.name}:null}signIn(e,{name:n}={}){var o;return ho({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:e,name:n??((o=this.config.user)==null?void 0:o.name)??null})}async confirmSignIn(e,n){var i;const o=await fo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:e,code:n});return(i=this.config.user)!=null&&i.email||(this.config.user={email:o.email,name:o.name||void 0}),this.emit("signin",{email:o.email,name:o.name}),{email:o.email,name:o.name}}async signOut(){var o;const e=he(this.config.projectId),n=await go({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:e==null?void 0:e.token});return e!=null&&e.email&&((o=this.config.user)==null?void 0:o.email)===e.email&&(this.config.user=null),this.emit("signout",{email:(e==null?void 0:e.email)||null}),n}knownIssues(){var e;return zo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,sessionToken:(e=he(this.config.projectId))==null?void 0:e.token})}matchKnownIssues(e,{signal:n}={}){var o;return Oo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,q:e||"",sessionToken:(o=he(this.config.projectId))==null?void 0:o.token,signal:n})}async meToo(e,{email:n,name:o}={}){var s,l;const i=he(this.config.projectId),r=await zt();return Ho({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,bugId:e,reporterEmail:n||((s=this.config.user)==null?void 0:s.email),reporterName:o||((l=this.config.user)==null?void 0:l.name),metadata:{...r,user:this.config.user||void 0,sdk:pn},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},sessionToken:i==null?void 0:i.token})}snapshot(){return{console:this.consoleBuffer.all(),network:this.networkBuffer.all(),environment:Ot()}}clear(){this.consoleBuffer.clear(),this.networkBuffer.clear()}destroy(){this.endCall(),this.teardown.forEach(e=>{try{e()}catch{}}),this.teardown=[],this.notifier=null,this.started=!1}}B=new WeakSet,ye=function(){const e=qe();if(this.emit("unread",{count:e.length,updates:e}),!!this.config.updateToast){if(!this.notifier){if(!e.length)return;this.notifier=jo({accent:this.config.accent,position:this.config.widgetPosition,onRead:n=>this.markUpdateRead(n),onReadAll:()=>this.markUpdatesRead(),onCall:this.config.voice?n=>{this.markUpdateRead(n.id),this.startCall(n.bugId)}:null}),this.teardown.push(()=>{var n;return(n=this.notifier)==null?void 0:n.destroy()})}this.notifier.render(e)}},ct=async function({title:e,description:n="",priority:o="MEDIUM",metadata:i={},media:r=[],references:s=[]}){var l,u;return{projectId:this.config.projectId,...e?{title:e}:{},description:n,priority:o,url:window.location.href,reporterEmail:(l=this.config.user)==null?void 0:l.email,reporterName:(u=this.config.user)==null?void 0:u.name,metadata:{...await zt(),release:this.config.release,environment:this.config.environment,buildId:this.config.buildId,...i,user:this.config.user||void 0,sdk:pn},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},...r.length?{attachments:r}:{},...s.length?{references:s}:{}}},Qn=async function(){const e=he(this.config.projectId);let n;try{n=await Eo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,token:e==null?void 0:e.token,payload:await V(this,B,ct).call(this,{})})}catch(o){throw o.status===401&&e&&ft(this.config.projectId),o}return n.watchToken&&(mt(n.watchToken),this.config.updates&&this.startWatching()),n},jn=async function(e){if(!xt())throw new Error("[BugCatch] this browser cannot make live calls.");const n=await vt();let o,i=null;try{if(e)o=await $o({apiBase:this.config.apiBase,bugId:e});else if(i=await V(this,B,Qn).call(this),e=i.id,o=i.live_call,!(o!=null&&o.realtime_url)){const s=new Error(`[BugCatch] the report was filed, but the team could not be rung${i.call_error?`: ${i.call_error}`:"."}`);throw s.filed=i,s.reason=i.call_error||null,s}}catch(s){for(const l of n.getTracks())l.stop();throw s}const r=await sn({realtimeUrl:o.realtime_url,stream:n,ringsUntil:o.rings_until,onState:(s,l)=>{(s==="ended"||s==="failed"||s==="missed")&&(this.call=null),s==="missed"&&To({apiBase:this.config.apiBase,bugId:e,callId:o.call_id}),typeof this.config.onCallState=="function"&&this.config.onCallState(s,{bugId:e,live:!0,...l}),this.emit("call",{bugId:e,live:!0,state:s,...l})}});return this.call=r,Object.assign(r,{bugId:e,callId:o.call_id,live:!0,filed:i})},zn=function(e){var i;const n=e.incomingCall;if(!this.config.voice||!xt()||((i=this.ringing)==null?void 0:i.callId)===n.callId||this.call||this.callStarting)return;V(this,B,lt).call(this);const o=ga({call:n,accent:this.config.accent,position:this.config.widgetPosition,onAnswer:()=>{V(this,B,On).call(this,e.bugId,n)},onDecline:()=>{this.ringing=null,Pt({apiBase:this.config.apiBase,bugId:e.bugId,callId:n.callId}),this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"declined"})},onExpire:()=>{this.ringing=null,this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"missed"})}});if(this.ringing={callId:n.callId,dismiss:o},typeof this.config.onIncomingCall=="function")try{this.config.onIncomingCall({bugId:e.bugId,...n})}catch{}this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"ringing"})},lt=function(e){if(this.ringing&&!(e&&this.ringing.callId!==e)){try{this.ringing.dismiss()}catch{}this.ringing=null}},On=async function(e,n){if(this.ringing=null,this.call||this.callStarting)return;this.callStarting=!0;let o;try{o=await vt()}catch(r){this.callStarting=!1,Pt({apiBase:this.config.apiBase,bugId:e,callId:n.callId}),this.emit("incoming-call",{bugId:e,callId:n.callId,state:"failed",error:r});return}let i;try{i=await Io({apiBase:this.config.apiBase,bugId:e,callId:n.callId})}catch(r){for(const s of o.getTracks())s.stop();this.callStarting=!1,this.emit("incoming-call",{bugId:e,callId:n.callId,state:"missed",error:r});return}try{const r=await sn({realtimeUrl:i.realtime_url,stream:o,onState:(s,l)=>{(s==="ended"||s==="failed"||s==="missed")&&(this.call=null),typeof this.config.onCallState=="function"&&this.config.onCallState(s,{bugId:e,live:!0,incoming:!0,...l}),this.emit("call",{bugId:e,live:!0,incoming:!0,state:s,...l})}});this.call=r,this.emit("incoming-call",{bugId:e,callId:n.callId,state:"answered"})}catch(r){for(const s of o.getTracks())s.stop();this.emit("incoming-call",{bugId:e,callId:n.callId,state:"failed",error:r})}finally{this.callStarting=!1}};const fn=new hn;return fn.Client=hn,fn});
|
|
1008
|
+
</a>`}function ta(t){return t.scrollHeight-t.scrollTop-t.clientHeight<40}function yt(t){t.scrollTop=t.scrollHeight}function wt(t){return{OPEN:"Open",IN_PROGRESS:"In progress",RESOLVED:"Fixed",CLOSED:"Closed"}[t]||String(t||"").toLowerCase()}function et(t){const e=new Date(t).getTime();if(!Number.isFinite(e))return"";const n=Math.floor((Date.now()-e)/864e5);if(n<=0)return"today";if(n===1)return"yesterday";if(n<30)return`${n} days ago`;const o=Math.floor(n/30);return o===1?"a month ago":`${o} months ago`}function x(t){return String(t).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}const rn=8e3;function na(t=rn){const e=window.AudioContext||window.webkitAudioContext;try{return new e({sampleRate:t})}catch{return new e}}async function oa(t){if(t.state==="suspended")try{await t.resume()}catch{}}function aa(t,e,n){const o=e/n,i=new Float32Array(Math.floor(t.length/o));for(let r=0;r<i.length;r++){const s=Math.floor(r*o),l=Math.min(Math.floor((r+1)*o),t.length);let u=0;for(let h=s;h<l;h++)u+=t[h];i[r]=l>s?u/(l-s):0}return i}const ra=132,sn=32635;function ia(t){const e=new Uint8Array(t.length);for(let n=0;n<t.length;n++){const o=Math.max(-1,Math.min(1,t[n]));let i=Math.round(o*32767);const r=i<0?128:0;r&&(i=-i),i>sn&&(i=sn),i+=ra;let s=7;for(let u=16384;!(i&u)&&s>0;s--,u>>=1);const l=i>>s+3&15;e[n]=~(r|s<<4|l)&255}return e}const sa=512;function ca(t,e,n,o=rn){const i=t.createMediaStreamSource(e),r=t.createScriptProcessor(sa,1,1);r.onaudioprocess=l=>{const u=l.inputBuffer.getChannelData(0),h=t.sampleRate===o?u:aa(u,t.sampleRate,o);n(ia(h))},i.connect(r);const s=t.createGain();return s.gain.value=0,r.connect(s),s.connect(t.destination),{stop(){r.onaudioprocess=null;try{i.disconnect()}catch{}try{r.disconnect()}catch{}try{s.disconnect()}catch{}}}}const la="voiceai.realtime.v1",da=[{urls:"stun:stun.l.google.com:19302"}];function vt(){return navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:1}})}function xt(){var t;return typeof window<"u"&&typeof window.RTCPeerConnection=="function"&&!!((t=navigator.mediaDevices)!=null&&t.getUserMedia)}async function cn({realtimeUrl:t,stream:e,ringsUntil:n,onState:o,onAudioBlocked:i,onMicrophone:r}){const s=(m,w)=>{try{o==null||o(m,w)}catch{}},l=m=>{try{i==null||i(m)}catch{}},u=m=>{try{r==null||r(m)}catch{}};if(!xt()){const m=new Error("[BugCatch] this browser cannot make live calls.");throw s("failed",{reason:"unsupported"}),m}let h=e;if(!h)try{h=await vt()}catch(m){throw s("failed",{reason:"microphone",error:String((m==null?void 0:m.name)||m)}),m}let y;try{y=await ua(t)}catch(m){throw dn(h),s("failed",{reason:"connect"}),m}let p=null,b=null,f=!1,k=null,A=null,ie=null,S=!1,E=null,T=null,L=!1;const X=[];let D=!1,j=!1,N=!1,$=null,se=null,ne=0;const De=2e3,xe=5e3,ot=3e4,ke=4,U=(m,w)=>{if(!f){f=!0,k&&(clearTimeout(k),k=null),ce(),T==null||T(),T=null,at(),E==null||E(),E=null;try{p==null||p.close()}catch{}dn(h),b&&(b.srcObject=null,b.remove(),b=null);try{y.readyState===WebSocket.OPEN&&y.close(1e3,"call over")}catch{}s(m,w)}},oe=m=>{y.readyState===WebSocket.OPEN&&y.send(JSON.stringify(m))},Le=async()=>{if(L||ie||f||!A||!A.audio&&!A.transcript)return;L=!0;const m=A.encoding||"mulaw";if(m!=="mulaw"){ln(`this call is kept as ${m}, which this SDK cannot produce.`);return}const w=Number(A.sample_rate)||8e3;try{const I=na(w);if(await oa(I),f){try{I.close()}catch{}return}const P=ca(I,h,_=>{y.readyState===WebSocket.OPEN&&y.send(_)},w);ie={context:I,tap:P}}catch(I){ln(`could not send the copy this call is keeping: ${String((I==null?void 0:I.message)||I)}`)}};function at(){if(L=!1,!ie)return;const{context:m,tap:w}=ie;ie=null;try{w.stop()}catch{}try{m.close()}catch{}}function Ne(){var w;if(!b||f)return;let m;try{m=(w=b.play)==null?void 0:w.call(b)}catch{Be();return}if(!m||typeof m.then!="function"){me();return}m.then(me,Be)}function me(){E==null||E(),E=null,S&&(S=!1,l(!1))}function Be(){f||(S||(S=!0,l(!0)),kt())}function kt(){if(E||typeof window>"u"||typeof window.addEventListener!="function")return;const m=()=>Ne(),w=["pointerdown","keydown","touchstart"];for(const I of w)window.addEventListener(I,m,{capture:!0,passive:!0});E=()=>{for(const I of w)try{window.removeEventListener(I,m,{capture:!0})}catch{}}}const Ae=m=>{p=new RTCPeerConnection({iceServers:m!=null&&m.length?m:da});for(const w of h.getAudioTracks())p.addTrack(w,h);T=de(),p.onicecandidate=w=>{w.candidate&&oe({type:"signal",signal:{kind:"candidate",payload:w.candidate.toJSON()}})},p.ontrack=w=>{var P;const[I]=w.streams;I&&(b||(b=document.createElement("audio"),b.autoplay=!0,b.playsInline=!0,(P=b.setAttribute)==null||P.call(b,"playsinline",""),b.style.cssText="position:fixed;width:0;height:0;opacity:0;pointer-events:none",document.body.appendChild(b)),b.srcObject=I,Ne())},p.onconnectionstatechange=Se,p.oniceconnectionstatechange=Se};function Se(){if(!p||f)return;const m=p.connectionState||p.iceConnectionState;if(m==="connected"||m==="completed"){j=!0,ne=0,ce(),N=!1,s("connected");return}if(m==="disconnected"){if(!j)return;Ue(De);return}if(m==="failed"){if(!j){U("failed",{reason:"ice"});return}Ue(0)}}function Ue(m){f||(N||(N=!0,s("reconnecting"),se=setTimeout(()=>U("failed",{reason:"network"}),ot)),!$&&($=setTimeout(Re,m)))}function ce(){$&&(clearTimeout($),$=null),se&&(clearTimeout(se),se=null)}async function Re(){if($=null,f||!p)return;const m=p.connectionState||p.iceConnectionState;if(!(m==="connected"||m==="completed")){if(!D){oe({type:"signal",signal:{kind:"restart",payload:{}}}),$=setTimeout(Re,xe);return}ne>=ke||(ne+=1,await z(),$=setTimeout(Re,xe))}}async function z(){if(!(f||!p))try{const m=await p.createOffer({iceRestart:!0});await p.setLocalDescription(m),oe({type:"signal",signal:{kind:"offer",payload:p.localDescription.toJSON()}})}catch{}}function de(){let w=null,I=!1;const P=_=>{if(w&&(clearTimeout(w),w=null),_){if(!I)return;I=!1,u(!0);return}I||(w=setTimeout(()=>{w=null,!f&&(I=!0,u(!1))},600))};for(const _ of h.getAudioTracks())_.onmute=()=>P(!1),_.onunmute=()=>P(!0),_.onended=()=>{w&&(clearTimeout(w),w=null),!I&&(I=!0,u(!1))};return()=>{w&&(clearTimeout(w),w=null);for(const _ of h.getAudioTracks())_.onmute=null,_.onunmute=null,_.onended=null}}const rt=async()=>{try{const m=await p.createOffer();await p.setLocalDescription(m),oe({type:"signal",signal:{kind:"offer",payload:p.localDescription.toJSON()}})}catch{U("failed",{reason:"negotiation"})}},St=async m=>{try{await p.setRemoteDescription(new RTCSessionDescription(m));const w=await p.createAnswer();await p.setLocalDescription(w),oe({type:"signal",signal:{kind:"answer",payload:p.localDescription.toJSON()}}),await Qe()}catch{U("failed",{reason:"negotiation"})}},Qe=async()=>{for(;X.length;){const m=X.shift();try{await p.addIceCandidate(new RTCIceCandidate(m))}catch{}}};let Ce=Promise.resolve();y.onmessage=m=>{Ce=Ce.then(()=>Ct(m)).catch(()=>{})};const Ct=async m=>{var I,P,_,Ee,it;if(typeof m.data!="string")return;let w;try{w=JSON.parse(m.data)}catch{return}switch(w.type){case"session.created":{if(Ae((I=w.data)==null?void 0:I.ice_servers),A=((P=w.data)==null?void 0:P.capture)||null,(_=w.data)!=null&&_.peer_present){s("connecting"),Le();break}s("ringing"),je();break}case"peer.joined":{k&&(clearTimeout(k),k=null),s("connecting"),D=!!((Ee=w.data)!=null&&Ee.should_offer),D&&await rt(),Le();break}case"signal":{if(!p)break;const{kind:$e,payload:ge}=w.data||{};if($e==="offer")await St(ge);else if($e==="answer")try{await p.setRemoteDescription(new RTCSessionDescription(ge)),await Qe()}catch{U("failed",{reason:"negotiation"})}else if($e==="candidate")if(p.remoteDescription)try{await p.addIceCandidate(new RTCIceCandidate(ge))}catch{}else X.push(ge);else $e==="restart"&&D&&await z();break}case"peer.left":U("ended",{reason:"peer_left"});break;case"error":U("failed",{reason:"server",detail:(it=w.error)==null?void 0:it.detail});break;case"session.ended":U("ended",{reason:"server"});break}};y.onclose=()=>U("ended",{reason:"disconnected"}),y.onerror=()=>U("failed",{reason:"socket"});function je(){if(!n)return;const m=new Date(n).getTime()-Date.now();Number.isFinite(m)&&(k=setTimeout(()=>U("missed"),Math.max(0,m)))}return{hangUp(){oe({type:"session.end"}),U("ended",{reason:"hung_up"})},setMuted(m){for(const w of h.getAudioTracks())w.enabled=!m;return m},isMuted(){return h.getAudioTracks().every(m=>!m.enabled)}}}function ua(t){return new Promise((e,n)=>{let o;try{o=new WebSocket(t,la)}catch(i){n(i);return}o.onopen=()=>{o.onopen=null,o.onerror=null,e(o)},o.onerror=()=>{o.onopen=null,o.onerror=null,n(new Error("[BugCatch] could not connect the call."))}})}function ln(t){try{console.warn(`[BugCatch] ${t}`)}catch{}}function dn(t){var e;for(const n of((e=t==null?void 0:t.getTracks)==null?void 0:e.call(t))??[])try{n.stop()}catch{}}const tt={cycleMs:3e3,peak:.045,bursts:[{at:0,seconds:.4,hz:[440,660]},{at:.55,seconds:.4,hz:[440,660]}]};let un=!1;if(typeof window<"u"&&window.addEventListener)for(const t of["pointerdown","keydown","touchstart"])window.addEventListener(t,()=>{un=!0},{once:!0,capture:!0,passive:!0});function pa(){var t;try{return!!((t=navigator.userActivation)!=null&&t.hasBeenActive)}catch{return!1}}function ha(){if(!un&&!pa())return()=>{};const t=typeof window<"u"&&(window.AudioContext||window.webkitAudioContext);if(!t)return()=>{};let e;try{e=new t}catch{return()=>{}}let n=!1,o=null;const i=[],r=({at:u,seconds:h,hz:y})=>{const p=e.currentTime+u,b=e.createGain();b.connect(e.destination),b.gain.setValueAtTime(0,p),b.gain.linearRampToValueAtTime(tt.peak,p+.02),b.gain.setValueAtTime(tt.peak,p+h-.06),b.gain.linearRampToValueAtTime(0,p+h);for(const f of y){const k=e.createOscillator();k.type="sine",k.frequency.value=f,k.connect(b),k.start(p),k.stop(p+h+.02),i.push(k)}},s=()=>{if(!n)try{tt.bursts.forEach(r)}catch{}},l=()=>{n||(s(),o=setInterval(s,tt.cycleMs))};return e.state==="running"?l():e.resume().then(l).catch(()=>{}),()=>{n=!0,o&&clearInterval(o);for(const u of i)try{u.stop()}catch{}try{e.close()}catch{}}}function fa(t){const e=Date.parse(t||"");return Number.isNaN(e)?0:Math.max(0,Math.round((e-Date.now())/1e3))}const pn=["flex:1","padding:9px 12px","border:0","border-radius:8px","font:600 13px/1.4 inherit","cursor:pointer"].join(";");function ga({call:t,accent:e="#5b6ef5",position:n="bottom-right",onAnswer:o,onDecline:i,onExpire:r}){if(typeof document>"u"||!document.body)return()=>{};const[s,l]=String(n).split("-"),u=document.createElement("div");u.setAttribute("role","alertdialog"),u.setAttribute("aria-live","assertive"),u.setAttribute("aria-label",`${t.from||"Support"} is calling about ${t.reference}`),u.style.cssText=["position:fixed",`${s==="top"?"top":"bottom"}:20px`,`${l==="left"?"left":"right"}:20px`,"z-index:2147483647","width:300px","max-width:calc(100vw - 40px)","padding:14px","border-radius:12px","background:#1b1e26","color:#eceef2",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 18px 44px rgba(0,0,0,0.5)",`border:1px solid ${e}`,"opacity:0","transform:translateY(8px)","transition:opacity .2s ease,transform .2s ease"].join(";");const h=document.createElement("div");h.style.cssText="font-weight:600;font-size:14px;margin-bottom:2px",h.textContent=`${t.from||"Support"} is calling`;const y=document.createElement("div");y.style.cssText="color:#a4abba;margin-bottom:10px",y.textContent=t.project?`About your report ${t.reference} · ${t.project}`:`About your report ${t.reference}`;const p=document.createElement("div");p.style.cssText="color:#7d8598;font-size:12px;margin-bottom:10px";const b=document.createElement("button");b.type="button",b.textContent="Answer",b.style.cssText=`${pn};background:${e};color:#fff`;const f=document.createElement("button");f.type="button",f.textContent="Not now",f.style.cssText=`${pn};background:#2b2f3a;color:#c8cedb`;const k=document.createElement("div");if(k.style.cssText="display:flex;gap:8px",k.append(b,f),u.append(h,y,p),t.recorded){const L=document.createElement("div");L.style.cssText="color:#7d8598;font-size:12px;margin-bottom:10px",L.textContent="This call will be recorded.",u.append(L)}u.append(k),document.body.appendChild(u);const A=ha();let ie=!1,S=null;const E=()=>{ie||(ie=!0,S&&clearInterval(S),A(),u.style.opacity="0",u.style.transform="translateY(8px)",setTimeout(()=>u.remove(),250))},T=()=>{const L=fa(t.ringsUntil);if(p.textContent=L?`Ringing — ${L}s`:"The call has stopped ringing.",!L){E();try{r==null||r()}catch{}}};return T(),S=setInterval(T,1e3),b.addEventListener("click",()=>{E();try{o==null||o()}catch{}}),f.addEventListener("click",()=>{E();try{i==null||i()}catch{}}),requestAnimationFrame(()=>{u.style.opacity="1",u.style.transform="translateY(0)"}),E}const hn={name:"@sphoro/bugcatch-web-sdk",version:"0.14.3"},nt={apiBase:"http://localhost:3000",apiKey:null,projectId:null,consoleLimit:100,networkLimit:50,captureConsole:!0,captureNetwork:!0,captureErrors:!0,widget:!0,widgetPosition:"bottom-right",theme:"auto",accent:"#4F46E5",attachments:!0,maxAttachments:5,maxAttachmentBytes:25*1024*1024,maxRecordingMs:12e4,beforeSend:null,user:null,updates:!0,updateToast:!0,onUpdate:null,voice:!0,onCallState:null,onIncomingCall:null};class fn{constructor(){Rn(this,B);this.config={...nt},this.started=!1,this.teardown=[],this.consoleBuffer=Pe(nt.consoleLimit),this.networkBuffer=Pe(nt.networkLimit),this.stopWatching=null,this.notifier=null,this.call=null,this.callStarting=!1,this.ringing=null,this.listeners=new Map}init(e={}){if(this.started)return console.warn("[BugCatch] init() called twice — ignoring the second call."),this;if(this.config={...nt,...e},!this.config.apiKey)throw new Error("[BugCatch] apiKey is required.");if(!this.config.projectId)throw new Error("[BugCatch] projectId is required.");return this.consoleBuffer=Pe(this.config.consoleLimit),this.networkBuffer=Pe(this.config.networkLimit),this.config.captureConsole&&this.teardown.push(Pn(this.consoleBuffer)),this.config.captureNetwork&&this.teardown.push(_n(this.networkBuffer)),this.config.captureErrors&&this.teardown.push(Fn(this.consoleBuffer)),this.config.widget&&this.teardown.push(Xo(this)),this.config.updates&&re()&&(this.startWatching(),queueMicrotask(()=>K(this,B,ye).call(this))),this.started=!0,this}startWatching(){if(this.stopWatching)return this;this.stopWatching=Mo({apiBase:this.config.apiBase,onUpdate:n=>{if(n!=null&&n.incomingCall){K(this,B,zn).call(this,n);return}if(n!=null&&n.callWithdrawn){K(this,B,lt).call(this,n.callWithdrawn.callId);return}const o=yo(n);typeof this.config.onUpdate=="function"&&this.config.onUpdate(o),this.emit("update",o),K(this,B,ye).call(this)}}),this.teardown.push(()=>{var n;return(n=this.stopWatching)==null?void 0:n.call(this)}),this.teardown.push(()=>K(this,B,lt).call(this));const e=n=>{(n.key===Je||n.key===null)&&K(this,B,ye).call(this)};return window.addEventListener("storage",e),this.teardown.push(()=>window.removeEventListener("storage",e)),this}on(e,n){if(typeof n!="function")return()=>{};const o=this.listeners.get(e)||new Set;return o.add(n),this.listeners.set(e,o),()=>this.off(e,n)}off(e,n){var o;return(o=this.listeners.get(e))==null||o.delete(n),this}emit(e,n){for(const o of this.listeners.get(e)||[])try{o(n)}catch(i){console.error("[BugCatch] an update listener threw:",i)}}unreadUpdates(){return qe()}markUpdateRead(e){return wo(e),K(this,B,ye).call(this),this}markReportRead(e){return vo(e),K(this,B,ye).call(this),this}markUpdatesRead(){return Vt(),K(this,B,ye).call(this),this}async verifyFix(e,{result:n,resolvedAt:o,note:i}){const r=n==="STILL_HAPPENING"?await K(this,B,ct).call(this,{}):{};return Do({apiBase:this.config.apiBase,bugId:e,result:n,resolvedAt:o,note:i,metadata:r.metadata,logs:r.logs})}myReport(e){return So({apiBase:this.config.apiBase,bugId:e})}replyToReport(e,{body:n,attachments:o}={}){return Kt({apiBase:this.config.apiBase,bugId:e,body:n,attachments:o})}async canCallNow(){return!!await this.callKind()}async callKind(){return(await this.callKinds()).live?"live":null}async callKinds(){var n;const e={agent:!1,live:!1};return!this.config.voice||!((n=this.config.user)!=null&&n.email)?e:this.kinds!==void 0?this.kinds:(this.kinds=await Co({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.kinds)}canCall(e){return this.config.voice?Pt({apiBase:this.config.apiBase,bugId:e}):Promise.resolve(!1)}async startCall(e){var n;if(!this.config.voice)throw new Error("[BugCatch] calling is switched off.");if(this.call||this.callStarting)throw new Error("[BugCatch] a call is already running.");this.callStarting=!0;try{if(!await this.callKind())throw new Error((n=this.config.user)!=null&&n.email?"[BugCatch] calling is not available on this project.":"[BugCatch] a call needs to know who is calling — call identify() with an email first.");return await K(this,B,jn).call(this,e)}finally{this.callStarting=!1}}startLiveCall(e){return this.startCall(e)}canCallTeam(e){return this.config.voice?Pt({apiBase:this.config.apiBase,bugId:e}):Promise.resolve(!1)}endCall(){var e;return(e=this.call)==null||e.hangUp(),this.call=null,this}myReports(){return ko({apiBase:this.config.apiBase})}hasReports(){return!!re()}forgetReports(){var e;return(e=this.stopWatching)==null||e.call(this),this.stopWatching=null,this.endCall(),ve(),K(this,B,ye).call(this),this}identify(e){return this.config.user=e,this}async uploadAttachment(e,n,o){if(!this.started)throw new Error("[BugCatch] call init() first.");return oo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,blob:e,mime:n||(e==null?void 0:e.type),onProgress:o})}async report({title:e,description:n="",priority:o="MEDIUM",metadata:i={},attachments:r=[],references:s=[]}={}){if(!this.started)throw new Error("[BugCatch] call init() first.");if(!e||!e.trim())throw new Error("[BugCatch] a title is required.");const l=(r||[]).filter(b=>(b==null?void 0:b.storageKey)&&Fe(b.mime,_e)).map(b=>({type:b.type==="VIDEO"?"VIDEO":"SCREENSHOT",storageKey:b.storageKey,mime:Fe(b.mime,_e)}));let u=await K(this,B,ct).call(this,{title:e.trim(),description:n,priority:o,metadata:i,media:l,references:s});if(typeof this.config.beforeSend=="function"){const b=this.config.beforeSend(u);if(b===!1)return{cancelled:!0};b&&typeof b=="object"&&(u=b)}const h=fe(this.config.projectId),y=await fetch(`${this.config.apiBase}/ingest/bugs`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":this.config.apiKey,...h!=null&&h.token?{"X-BugCatch-Session":h.token}:{}},body:JSON.stringify(u)});if(y.status===401&&h&&ft(this.config.projectId),!y.ok){let b="";try{const f=await y.json();b=Array.isArray(f.message)?f.message.join(", "):f.message||""}catch{}throw new Error(`[BugCatch] report failed (HTTP ${y.status})${b?": "+b:""}`)}const p=await y.json();return p.watchToken&&(mt(p.watchToken),this.config.updates&&this.startWatching()),p}loginState(){var e;return po({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:(e=fe(this.config.projectId))==null?void 0:e.token})}referenceFields(){return this.refFields?this.refFields:(this.refFields=Po({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.refFields)}signedInAs(){const e=fe(this.config.projectId);return e?{email:e.email,name:e.name}:null}signIn(e,{name:n}={}){var o;return ho({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:e,name:n??((o=this.config.user)==null?void 0:o.name)??null})}async confirmSignIn(e,n){var i;const o=await fo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:e,code:n});return(i=this.config.user)!=null&&i.email||(this.config.user={email:o.email,name:o.name||void 0}),this.emit("signin",{email:o.email,name:o.name}),{email:o.email,name:o.name}}async signOut(){var o;const e=fe(this.config.projectId),n=await go({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:e==null?void 0:e.token});return e!=null&&e.email&&((o=this.config.user)==null?void 0:o.email)===e.email&&(this.config.user=null),this.emit("signout",{email:(e==null?void 0:e.email)||null}),n}knownIssues(){var e;return zo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,sessionToken:(e=fe(this.config.projectId))==null?void 0:e.token})}matchKnownIssues(e,{signal:n}={}){var o;return Oo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,q:e||"",sessionToken:(o=fe(this.config.projectId))==null?void 0:o.token,signal:n})}async meToo(e,{email:n,name:o}={}){var s,l;const i=fe(this.config.projectId),r=await Ot();return Ho({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,bugId:e,reporterEmail:n||((s=this.config.user)==null?void 0:s.email),reporterName:o||((l=this.config.user)==null?void 0:l.name),metadata:{...r,user:this.config.user||void 0,sdk:hn},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},sessionToken:i==null?void 0:i.token})}snapshot(){return{console:this.consoleBuffer.all(),network:this.networkBuffer.all(),environment:Ht()}}clear(){this.consoleBuffer.clear(),this.networkBuffer.clear()}destroy(){this.endCall(),this.teardown.forEach(e=>{try{e()}catch{}}),this.teardown=[],this.notifier=null,this.started=!1}}B=new WeakSet,ye=function(){const e=qe();if(this.emit("unread",{count:e.length,updates:e}),!!this.config.updateToast){if(!this.notifier){if(!e.length)return;this.notifier=jo({accent:this.config.accent,position:this.config.widgetPosition,onRead:n=>this.markUpdateRead(n),onReadAll:()=>this.markUpdatesRead(),onCall:this.config.voice?n=>{this.markUpdateRead(n.id),this.startCall(n.bugId)}:null}),this.teardown.push(()=>{var n;return(n=this.notifier)==null?void 0:n.destroy()})}this.notifier.render(e)}},ct=async function({title:e,description:n="",priority:o="MEDIUM",metadata:i={},media:r=[],references:s=[]}){var l,u;return{projectId:this.config.projectId,...e?{title:e}:{},description:n,priority:o,url:window.location.href,reporterEmail:(l=this.config.user)==null?void 0:l.email,reporterName:(u=this.config.user)==null?void 0:u.name,metadata:{...await Ot(),release:this.config.release,environment:this.config.environment,buildId:this.config.buildId,...i,user:this.config.user||void 0,sdk:hn},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},...r.length?{attachments:r}:{},...s.length?{references:s}:{}}},Qn=async function(){const e=fe(this.config.projectId);let n;try{n=await Eo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,token:e==null?void 0:e.token,payload:await K(this,B,ct).call(this,{})})}catch(o){throw o.status===401&&e&&ft(this.config.projectId),o}return n.watchToken&&(mt(n.watchToken),this.config.updates&&this.startWatching()),n},jn=async function(e){if(!xt())throw new Error("[BugCatch] this browser cannot make live calls.");const n=await vt();let o,i=null;try{if(e)o=await $o({apiBase:this.config.apiBase,bugId:e});else if(i=await K(this,B,Qn).call(this),e=i.id,o=i.live_call,!(o!=null&&o.realtime_url)){const s=new Error(`[BugCatch] the report was filed, but the team could not be rung${i.call_error?`: ${i.call_error}`:"."}`);throw s.filed=i,s.reason=i.call_error||null,s}}catch(s){for(const l of n.getTracks())l.stop();throw s}const r=await cn({realtimeUrl:o.realtime_url,stream:n,ringsUntil:o.rings_until,onState:(s,l)=>{(s==="ended"||s==="failed"||s==="missed")&&(this.call=null),s==="missed"&&To({apiBase:this.config.apiBase,bugId:e,callId:o.call_id}),typeof this.config.onCallState=="function"&&this.config.onCallState(s,{bugId:e,live:!0,...l}),this.emit("call",{bugId:e,live:!0,state:s,...l})}});return this.call=r,Object.assign(r,{bugId:e,callId:o.call_id,live:!0,filed:i})},zn=function(e){var i;const n=e.incomingCall;if(!this.config.voice||!xt()||((i=this.ringing)==null?void 0:i.callId)===n.callId||this.call||this.callStarting)return;K(this,B,lt).call(this);const o=ga({call:n,accent:this.config.accent,position:this.config.widgetPosition,onAnswer:()=>{K(this,B,On).call(this,e.bugId,n)},onDecline:()=>{this.ringing=null,_t({apiBase:this.config.apiBase,bugId:e.bugId,callId:n.callId}),this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"declined"})},onExpire:()=>{this.ringing=null,this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"missed"})}});if(this.ringing={callId:n.callId,dismiss:o},typeof this.config.onIncomingCall=="function")try{this.config.onIncomingCall({bugId:e.bugId,...n})}catch{}this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"ringing"})},lt=function(e){if(this.ringing&&!(e&&this.ringing.callId!==e)){try{this.ringing.dismiss()}catch{}this.ringing=null}},On=async function(e,n){if(this.ringing=null,this.call||this.callStarting)return;this.callStarting=!0;let o;try{o=await vt()}catch(r){this.callStarting=!1,_t({apiBase:this.config.apiBase,bugId:e,callId:n.callId}),this.emit("incoming-call",{bugId:e,callId:n.callId,state:"failed",error:r});return}let i;try{i=await Io({apiBase:this.config.apiBase,bugId:e,callId:n.callId})}catch(r){for(const s of o.getTracks())s.stop();this.callStarting=!1,this.emit("incoming-call",{bugId:e,callId:n.callId,state:"missed",error:r});return}try{const r=await cn({realtimeUrl:i.realtime_url,stream:o,onState:(s,l)=>{(s==="ended"||s==="failed"||s==="missed")&&(this.call=null),typeof this.config.onCallState=="function"&&this.config.onCallState(s,{bugId:e,live:!0,incoming:!0,...l}),this.emit("call",{bugId:e,live:!0,incoming:!0,state:s,...l})}});this.call=r,this.emit("incoming-call",{bugId:e,callId:n.callId,state:"answered"})}catch(r){for(const s of o.getTracks())s.stop();this.emit("incoming-call",{bugId:e,callId:n.callId,state:"failed",error:r})}finally{this.callStarting=!1}};const gn=new fn;return gn.Client=fn,gn});
|
|
996
1009
|
//# sourceMappingURL=bugcatch.umd.js.map
|