@tanay-wispr/webflow-package 6.1.1 → 6.1.2
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/web-demo/index.js +5 -5
- package/package.json +1 -1
package/dist/web-demo/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
"use strict";(()=>{var W=class{constructor(){this.mediaStream=null,this.mediaRecorder=null,this.audioChunks=[],this.audioContext=null,this.analyser=null,this.dataArray=null,this.mediaStreamSource=null,this.processor=null,this.intSamples=[],this.BUFFER_SIZE=1024,this.TARGET_SAMPLE_RATE=16e3}blobToBase64(o){return new Promise((i,n)=>{let r=new FileReader;r.onloadend=()=>{typeof r.result=="string"?i(r.result.split(",")[1]):n(new Error("Failed to convert blob to base64"))},r.onerror=n,r.readAsDataURL(o)})}async convertIntSamplesToWAV(){let i=this.intSamples.length*1*2+44,n=new ArrayBuffer(i),r=new DataView(n),t=0,l=(d,g,u)=>{for(let m=0;m<u.length;m++)d.setUint8(g+m,u.charCodeAt(m))};l(r,0,"RIFF"),t+=4,r.setUint32(t,36+this.intSamples.length*1*2,!0),t+=4,l(r,t,"WAVE"),t+=4,l(r,t,"fmt "),t+=4,r.setUint32(t,16,!0),t+=4,r.setUint16(t,1,!0),t+=2,r.setUint16(t,1,!0),t+=2,r.setUint32(t,this.TARGET_SAMPLE_RATE,!0),t+=4,r.setUint32(t,this.TARGET_SAMPLE_RATE*1*2,!0),t+=4,r.setUint16(t,1*2,!0),t+=2,r.setUint16(t,16,!0),t+=2,l(r,t,"data"),t+=4,r.setUint32(t,this.intSamples.length*1*2,!0),t+=4;for(let d=0;d<this.intSamples.length;d++)r.setInt16(t,this.intSamples[d],!0),t+=2;return new Blob([r],{type:"audio/wav"})}async requestMicrophonePermission(){try{return this.mediaStream=await navigator.mediaDevices.getUserMedia({audio:!0}),this.mediaStream.getAudioTracks().forEach(o=>{o.enabled=!1}),!0}catch(o){return console.error("Initial microphone permission denied:",o),!1}}async setupRecorder(){try{return this.mediaStream&&this.mediaStream.getAudioTracks().length>0?this.mediaStream.getAudioTracks().forEach(o=>{o.enabled=!0}):this.mediaStream=await navigator.mediaDevices.getUserMedia({audio:!0}),this.mediaRecorder=new MediaRecorder(this.mediaStream),this.mediaRecorder.ondataavailable=o=>{this.audioChunks.push(o.data)},this.mediaRecorder.onstop=async()=>{this.mediaStream.getTracks().forEach(o=>{o.enabled=!1}),this.mediaRecorder=null},!0}catch(o){return console.error("Microphone access error:",o),(o.name==="NotAllowedError"||o.name==="PermissionDeniedError")&&alert("Please enable microphone access in your browser settings to continue."),!1}}async startRecording(o){this.mediaRecorder.state==="inactive"&&(this.audioChunks=[],this.mediaRecorder.start(),this.intSamples=[],this.audioContext||(this.audioContext=new AudioContext),this.mediaStreamSource=this.audioContext.createMediaStreamSource(this.mediaStream),this.processor=this.audioContext.createScriptProcessor(this.BUFFER_SIZE,1,1),this.processor.onaudioprocess=async i=>{let n=i.inputBuffer.getChannelData(0),r=Math.ceil(this.BUFFER_SIZE*this.TARGET_SAMPLE_RATE/this.audioContext.sampleRate),t=new OfflineAudioContext(1,r,this.TARGET_SAMPLE_RATE),l=this.audioContext.createBuffer(1,n.length,this.audioContext.sampleRate);l.copyToChannel(n,0);let d=t.createBufferSource();d.buffer=l,d.connect(t.destination),d.start();let u=(await t.startRendering()).getChannelData(0),m=new Int16Array(u.length),w=0;for(let h=0;h<u.length;h++){let b=Math.max(-1,Math.min(1,u[h]));m[h]=b<0?b*32768:b*32767,this.intSamples.push(m[h]),w+=u[h]*u[h]}let E=Math.sqrt(w/u.length),L=new Uint8Array(m.buffer),C="";for(let h=0;h<L.length;h++)C+=String.fromCharCode(L[h]);let F=btoa(C);o&&o({audio:F,volume:E,packetDuration:this.BUFFER_SIZE/this.audioContext.sampleRate})},this.mediaStreamSource.connect(this.processor),this.processor.connect(this.audioContext.destination))}async stopRecording(){this.mediaRecorder&&this.mediaRecorder.state==="recording"&&this.mediaRecorder.stop(),this.processor&&(this.processor.disconnect(),this.processor=null),this.mediaStreamSource&&(this.mediaStreamSource.disconnect(),this.mediaStreamSource=null)}setupAudioAnalysis(){return this.audioContext||(this.audioContext=new AudioContext),this.analyser=this.audioContext.createAnalyser(),this.audioContext.createMediaStreamSource(this.mediaStream).connect(this.analyser),this.analyser.fftSize=32,this.dataArray=new Uint8Array(this.analyser.frequencyBinCount),{analyser:this.analyser,dataArray:this.dataArray}}getVolumeScale(){if(!this.analyser||!this.dataArray)return 0;this.analyser.getByteFrequencyData(this.dataArray);let o=this.dataArray.reduce((r,t)=>r+t,0)/this.dataArray.length,i=8,n=0;return o>i&&(n=Math.pow((o-i)/(255-i),1.5)),n}getIntSamples(){return this.intSamples}async closeAudioContext(){this.audioContext&&(await this.audioContext.close(),this.audioContext=null)}isRecording(){return this.mediaRecorder&&this.mediaRecorder.state==="recording"}};var M=class{constructor(){this.storageKeys={accessToken:"accessToken",tokenExpiration:"tokenExpiration"}}async generateAndStoreToken(){try{let o=await fetch("https://api.wisprflow.ai/api/v1/dash/webflow_demo/generate_token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_id:"webflow_demo"})});if(!o.ok)throw new Error(`Token generation failed with status: ${o.status}`);let i=await o.json();return localStorage.setItem(this.storageKeys.accessToken,i.access_token),localStorage.setItem(this.storageKeys.tokenExpiration,(Date.now()+i.expires_in*1e3).toString()),i.access_token}catch(o){throw console.error("Token generation failed:",o),o}}async getValidToken(){let o=localStorage.getItem(this.storageKeys.tokenExpiration);return!o||Date.now()>=parseInt(o)?await this.generateAndStoreToken():localStorage.getItem(this.storageKeys.accessToken)}};var _=class{constructor(o,i){this.tokenService=o,this.audioService=i,this.websocket=null,this.isWebSocketReady=!1,this.audioChunkBuffer=[],this.isBufferFlushNeeded=!1,this.bufferStartTime=null,this.packetPosition=0,this.transcriptionReceived=!1,this.commitTimeout=null,this.onTranscriptionReceived=null,this.onError=null}async setupWebSocket(){this.websocket&&this.websocket.readyState===WebSocket.CLOSED&&(this.websocket=null),this.websocket&&(this.websocket.readyState===WebSocket.OPEN||this.websocket.readyState===WebSocket.CONNECTING)&&(this.websocket.onclose=null,this.websocket.close(),this.websocket=null);let o=await this.tokenService.getValidToken(),i=`wss://api.wisprflow.ai/api/v1/dash/client_ws?client_key=Bearer ${o}`;console.log("Connecting to WebSocket"),this.websocket=new WebSocket(i),this.websocket.onopen=()=>{let r=new URLSearchParams(window.location.search).get("type")==="email"?"email":"other";this.websocket.send(JSON.stringify({type:"auth",access_token:`Bearer ${o}`,context:{app:{type:r}}}))},this.websocket.onmessage=n=>{try{let r=JSON.parse(n.data);if(r.status==="error"||r.status==="auth_error"){console.error("WebSocket error:",r),this.triggerFallback();return}if(r.status==="text"&&r.final)if(this.transcriptionReceived=!0,this.commitTimeout&&(clearTimeout(this.commitTimeout),this.commitTimeout=null),r.body&&r.body.text===null)console.log("Empty recording detected, skipping text display"),this.onTranscriptionReceived&&this.onTranscriptionReceived(null);else{let t="No speech detected.";r.body&&r.body.text?t=r.body.text:r.body.status==="formatted"?t=r.body.llm_text:r.body.status==="raw_transcript"&&(t=r.body.asr_text),this.onTranscriptionReceived&&this.onTranscriptionReceived(t)}}catch(r){console.error("WebSocket message parsing error:",r),this.triggerFallback()}},this.websocket.onclose=n=>{console.log("WebSocket closed:",n.code,n.reason),this.websocket=null,this.isWebSocketReady=!1},this.websocket.onerror=n=>{console.error("WebSocket error:",n)}}async connectWebSocketInBackground(){if(this.websocket&&this.websocket.readyState===WebSocket.CONNECTING){console.log("\u23F3 WebSocket already connecting, skipping duplicate call");return}try{this.isWebSocketReady=!1,await this.setupWebSocket();let o=0,i=50;for(;(!this.websocket||this.websocket.readyState!==WebSocket.OPEN)&&o<i;)await new Promise(n=>setTimeout(n,100)),o++;this.websocket&&this.websocket.readyState===WebSocket.OPEN?(this.isWebSocketReady=!0,console.log("\u2705 WebSocket marked as ready for streaming")):(console.log("WebSocket connection failed, will use fallback"),this.isWebSocketReady=!1)}catch(o){console.error("WebSocket background connection failed:",o),this.isWebSocketReady=!1}}flushAudioBuffer(){if(!this.isBufferFlushNeeded||this.audioChunkBuffer.length===0)return;console.log(`Flushing ${this.audioChunkBuffer.length} buffered audio chunks...`),this.audioChunkBuffer.forEach(i=>{try{this.websocket&&this.websocket.readyState===WebSocket.OPEN&&this.websocket.send(JSON.stringify(i))}catch(n){console.error(`Error sending buffered chunk ${i.position}:`,n)}});let o=this.bufferStartTime?Date.now()-this.bufferStartTime:0;console.log(`Buffer flushed! Buffering lasted ${o}ms`),this.audioChunkBuffer=[],this.isBufferFlushNeeded=!1,this.bufferStartTime=null}sendAudioChunk(o){let i={type:"append",position:this.packetPosition,final:!1,audio_packets:{packets:[o.audio],volumes:[o.volume],packet_duration:o.packetDuration,audio_encoding:"wav",byte_encoding:"base64"}};this.isWebSocketReady&&this.websocket&&this.websocket.readyState===WebSocket.OPEN?(this.isBufferFlushNeeded&&this.flushAudioBuffer(),this.websocket.send(JSON.stringify(i))):(this.audioChunkBuffer.push(i),this.isBufferFlushNeeded=!0,this.bufferStartTime||(this.bufferStartTime=Date.now()),this.packetPosition===0&&console.log("WebSocket not ready yet, buffering audio chunks")),this.packetPosition++}async commitRecording(){if(this.transcriptionReceived=!1,this.isWebSocketReady&&this.websocket&&this.websocket.readyState===WebSocket.OPEN)try{this.websocket.send(JSON.stringify({type:"commit",total_packets:this.packetPosition})),this.commitTimeout=setTimeout(()=>{this.transcriptionReceived||(console.log("WebSocket timeout, falling back to Fetch"),this.triggerFallback())},4e3)}catch(o){console.error("WebSocket commit failed:",o),this.triggerFallback()}else console.log("WebSocket not available, using Fetch fallback"),this.triggerFallback()}triggerFallback(){this.commitTimeout&&(clearTimeout(this.commitTimeout),this.commitTimeout=null),this.sendAudioToServerFallback()}async sendAudioToServerFallback(){try{console.log("Using Fetch API fallback with collected samples");let o=await this.audioService.convertIntSamplesToWAV(),i=await this.audioService.blobToBase64(o),n=await this.tokenService.getValidToken(),r=await fetch("https://api.wisprflow.ai/api/v1/dash/client_api",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({audio:i,properties:{language:""}})});if(!r.ok)throw new Error("Fallback server error");let t=await r.json();if(t.text===null){console.log("Empty fallback recording detected, skipping text display"),this.onTranscriptionReceived&&this.onTranscriptionReceived(null);return}this.onTranscriptionReceived&&this.onTranscriptionReceived(t.text)}catch(o){console.error("Fallback also failed:",o),this.onError&&this.onError(o)}}resetSession(){this.audioChunkBuffer=[],this.isBufferFlushNeeded=!1,this.bufferStartTime=null,this.packetPosition=0,this.transcriptionReceived=!1,this.commitTimeout&&(clearTimeout(this.commitTimeout),this.commitTimeout=null)}isReady(){return this.isWebSocketReady}};async function z(p="control"){let o=new M,i=new W,n=new _(o,i),r=()=>document.querySelector('.w--tab-active [demo-element="input"]'),t=r(),l=document.querySelector('[demo-element="gradient"]'),d=()=>document.querySelector(".wd_pill-wrap"),g=()=>document.querySelector(".wd_pill"),u=()=>g()?.querySelector(".wd_pill-lottie-wrap"),m=document.querySelectorAll('[demo-element="start-recording"]'),w=document.querySelectorAll('[demo-element="stop-recording"]'),E=new Audio("https://dl.dropbox.com/scl/fi/zv8278qh9ovwq0r89rch1/dictation-start.wav?rlkey=pk241hf4c8qv7780qsq2m4cgv&st=wgpy7vop&dl=0"),L=new Audio("https://dl.dropbox.com/scl/fi/4mkbgr7om46imcp0l86yd/dictation-stop.wav?rlkey=4t5uwvg9kufphlu58natjn43t&st=9or4oqr0&dl=0");function C(e){let s=document.getSelection();return s.rangeCount>0&&e.contains(s.focusNode)?s.getRangeAt(0):null}function F(e,s,a){a.deleteContents();let c=document.createElement("div");c.innerHTML=s;let y=document.createDocumentFragment();for(;c.firstChild;)y.appendChild(c.firstChild);a.insertNode(y),a.collapse(!1);let f=document.getSelection();f.removeAllRanges(),f.addRange(a)}function h(e){e.dataset.isPlaceholder==="true"?(e.classList.remove("cursor-after"),e.classList.add("cursor-before"),e.style.color="#1a1a1a80"):(e.classList.remove("cursor-before"),e.classList.add("cursor-after"),e.style.color="#1a1a1a")}let b=()=>{m.forEach(e=>{e&&(e.style.display="flex")}),document.querySelectorAll('[demo-element="start-recording-text"]').forEach(e=>{e&&(e.style.display="block")})},k=()=>{m.forEach(e=>{e&&(e.style.display="none")}),document.querySelectorAll('[demo-element="start-recording-text"]').forEach(e=>{e&&(e.style.display="none")})},Y=()=>{w.forEach(e=>{e&&(e.style.display="flex")}),document.querySelectorAll('[demo-element="stop-recording-text"]').forEach(e=>{e&&(e.style.display="block")})},D=()=>{w.forEach(e=>{e&&(e.style.display="none")}),document.querySelectorAll('[demo-element="stop-recording-text"]').forEach(e=>{e&&(e.style.display="none")})},x=window.matchMedia("(min-width: 992px)").matches,v=!1,T=!1,S=!0,P=!0,B=null,G=!1;i.requestMicrophonePermission().then(e=>{if(P=!1,!e){if(alert("Please enable microphone access in your browser settings to continue."),t||(t=r()),!t)return;document.querySelectorAll('[demo-element="input"]').forEach(s=>{s.innerHTML="Please enable microphone access in your browser settings to continue.",s.removeAttribute("contenteditable")}),t.classList.remove("cursor-before","cursor-after"),k(),S=!1,document.querySelectorAll('[ab-test="both-variants"]').forEach(s=>{s.style.display="none"})}}).catch(e=>{console.error("Initial microphone permission denied:",e),P=!1,alert("Please enable microphone access in your browser settings to continue."),t||(t=r()),t&&(document.querySelectorAll('[demo-element="input"]').forEach(s=>{s.innerHTML="Please enable microphone access in your browser settings to continue.",s.removeAttribute("contenteditable")}),t.classList.remove("cursor-before","cursor-after"),k(),S=!1,document.querySelectorAll('[ab-test="both-variants"]').forEach(s=>{s.style.display="none"}))}),l&&(l.style.opacity="0",l.style.transition="opacity 0.3s ease"),D(),navigator.userAgent.toLowerCase().includes("firefox")&&(document.querySelectorAll('[wd-para-div="hero-section"]').forEach(e=>{e.style.display="none"}),document.querySelectorAll('[ab-test="both-variants"]').forEach(e=>{e.querySelectorAll(".hide-tablet").forEach(s=>{s.classList.remove("hide-tablet"),s.classList.add("hide")})})),x&&t&&t.focus({preventScroll:!0}),document.querySelectorAll('[demo-element="input"]').forEach(e=>{e.classList.add("cursor-before"),e.dataset.isFirstRecording="true",e.dataset.placeholderText=e.textContent.trim(),e.dataset.placeholderHtml=e.innerHTML,e.dataset.isPlaceholder="true",e.addEventListener("beforeinput",()=>{e.dataset.isPlaceholder==="true"&&(e.innerHTML=""),e.dataset.isPlaceholder="false",h(e)}),e.addEventListener("input",()=>{if(e.textContent.trim()===""){e.innerHTML=e.dataset.placeholderHtml,e.dataset.isPlaceholder="true";let s=document.createRange();s.setStart(e,0),s.collapse(!0);let a=window.getSelection();a.removeAllRanges(),a.addRange(s)}h(e)}),e.addEventListener("focus",()=>{}),e.addEventListener("blur",()=>{e.textContent.trim()===""&&(e.innerHTML=e.dataset.placeholderHtml,e.dataset.isPlaceholder="true",e.dataset.isFirstRecording="true",h(e))}),e.addEventListener("mousedown",s=>{if(e.dataset.isPlaceholder==="true"){s.preventDefault();let a=document.createRange();a.setStart(e,0),a.collapse(!0);let c=window.getSelection();c.removeAllRanges(),c.addRange(a)}}),e.addEventListener("keydown",s=>{if(e.dataset.isPlaceholder==="true"&&["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Home","End"].includes(s.key)){s.preventDefault();let a=document.createRange();a.setStart(e,0),a.collapse(!0);let c=window.getSelection();c.removeAllRanges(),c.addRange(a)}})});let I=new MutationObserver(()=>{K()});I.observe(t,{childList:!0,subtree:!0,characterData:!0}),o.generateAndStoreToken().catch(e=>{console.error("Initial token generation failed:",e),t||(t=r()),t&&(document.querySelectorAll('[demo-element="input"]').forEach(s=>{s.innerHTML='Our servers are busy processing requests right now. <a href="/get-started" class="text-color-primary text-weight-medium">Try our desktop app instead.</a>',s.removeAttribute("contenteditable")}),t.classList.remove("cursor-before","cursor-after"),k(),S=!1,document.querySelectorAll('[ab-test="both-variants"]').forEach(s=>{s.style.display="none"}))});let N,K=()=>{t&&(t.scrollHeight>t.clientHeight?t.style.overflowY="auto":t.style.overflowY="visible")};n.onTranscriptionReceived=e=>{e===null?(u()?.classList.remove("show"),d()?.style.setProperty("opacity","0"),b(),D()):(Q(e+"\xA0"),b(),D(),u()?.classList.remove("show"),d()?.style.setProperty("opacity","0"))},n.onError=e=>{console.error("WebSocket service error:",e),t||(t=r()),t&&(document.querySelectorAll('[demo-element="input"]').forEach(s=>{s.innerHTML='Our servers are busy processing requests right now. <a href="/get-started" class="text-color-primary text-weight-medium">Try our desktop app instead.</a>',s.removeAttribute("contenteditable")}),t.classList.remove("cursor-before","cursor-after"),k(),S=!1,g()?.classList.remove("is-speaking"),u()?.classList.remove("show"),d()?.style.setProperty("opacity","0"),document.querySelectorAll('[ab-test="both-variants"]').forEach(s=>{s.style.display="none"}))};function Q(e){if(e=e.replace(/\n/g,"<br>"),e=e.replace(/<br>(?=\s*<\/?(?:ul|ol|li))|(?<=<\/?(?:ul|ol|li)>\s*)<br>/gi,""),!t)return;t.dataset.isPlaceholder==="true"&&(t.innerHTML=""),t.dataset.isPlaceholder="false",t.classList.remove("no-cursor");let s=C(t);if(s?F(t,e,s):t.textContent.trim()===""?t.innerHTML=e:t.innerHTML+=e,K(),t.dataset.previousText=t.textContent,t.dataset.isFirstRecording==="true"&&(t.classList.remove("cursor-before"),t.classList.add("cursor-after"),t.dataset.isFirstRecording="false"),typeof posthog<"u"){let c=document.querySelector(".w-tab-link.w--current"),y=c?c.textContent.trim().toLowerCase().replace(/\s+/g,"_"):"Unknown";posthog.capture("demo_transcription_completed",{transcribed_text:e,tab_name:y})}if(!G){G=!0,console.log("\u{1F3A8} Applying post-recording UI updates (first recording completed)"),document.querySelectorAll('[ab-test="download-button"]').forEach(f=>{f.style.display="block",f.style.visibility="visible"});let c=document.querySelectorAll('[demo-element="start-recording"]'),y=document.querySelectorAll('[demo-element="stop-recording"]');c.forEach(f=>f.classList.add("is-secondary")),y.forEach(f=>f.classList.add("is-secondary")),document.querySelectorAll('[ab-test="both-variants"] .wd-para').forEach(f=>{f.classList.add("text-style-muted")}),console.log("\u2705 Post-recording UI updates applied")}h(t),b()}async function J(){if(t||(t=r()),!t)return;m.forEach(a=>{a&&a.classList.remove("glow-purple")}),document.querySelectorAll(".wd-tab-link").forEach(a=>{a.classList.contains("w--current")||a.classList.add("pointer-events-none")}),n.resetSession(),n.connectWebSocketInBackground();let s=t.innerHTML||"";s&&!s.includes("Flow is listening")&&!s.includes("Converting...")&&!s.includes("Error")&&(t.dataset.previousText=s),t.classList.add("no-cursor");try{E.currentTime=0,E.play()}catch(a){console.error("Error playing start dictation sound:",a)}if(!i.mediaRecorder&&!await i.setupRecorder()){t.dataset.previousText?t.innerHTML=t.dataset.previousText:t.innerHTML="",t.classList.remove("no-cursor");return}if(!i.isRecording()){v=!0,await i.startRecording(c=>{n.sendAudioChunk(c)}),l&&(l.style.opacity="1"),d()?.style.setProperty("opacity","1"),g()?.classList.remove("is-speaking"),u()?.classList.remove("show");let a=document.querySelector(".wave-svg");a&&(a.style.opacity="1"),N=l.animate([{transform:"scale(1)"},{transform:"scale(1.3)"},{transform:"scale(1)"}],{duration:1500,iterations:1/0}),k(),Y(),i.setupAudioAnalysis(),B=setInterval(()=>{let c=i.getVolumeScale(),y=1+c*2,f=g();f&&(c>.06?f.classList.add("is-speaking"):f.classList.remove("is-speaking")),l.animate([{transform:`scale(${y})`}],{duration:300,fill:"forwards"});let j=document.querySelector(".wave-path");if(j){let q=40+c*300,U=Date.now()/1e3,H=R=>q*.3*Math.sin(R/1440*Math.PI*2+U*.8),$=R=>q*.2*Math.sin(R/720*Math.PI*2+U*1.2),V=R=>q*.1*Math.sin(R/360*Math.PI*2+U*1.8),te=`
|
|
1
|
+
"use strict";(()=>{var M=class{constructor(){this.mediaStream=null,this.mediaRecorder=null,this.audioChunks=[],this.audioContext=null,this.analyser=null,this.dataArray=null,this.mediaStreamSource=null,this.processor=null,this.intSamples=[],this.BUFFER_SIZE=1024,this.TARGET_SAMPLE_RATE=16e3}blobToBase64(o){return new Promise((i,n)=>{let r=new FileReader;r.onloadend=()=>{typeof r.result=="string"?i(r.result.split(",")[1]):n(new Error("Failed to convert blob to base64"))},r.onerror=n,r.readAsDataURL(o)})}async convertIntSamplesToWAV(){let i=this.intSamples.length*1*2+44,n=new ArrayBuffer(i),r=new DataView(n),t=0,l=(d,y,u)=>{for(let m=0;m<u.length;m++)d.setUint8(y+m,u.charCodeAt(m))};l(r,0,"RIFF"),t+=4,r.setUint32(t,36+this.intSamples.length*1*2,!0),t+=4,l(r,t,"WAVE"),t+=4,l(r,t,"fmt "),t+=4,r.setUint32(t,16,!0),t+=4,r.setUint16(t,1,!0),t+=2,r.setUint16(t,1,!0),t+=2,r.setUint32(t,this.TARGET_SAMPLE_RATE,!0),t+=4,r.setUint32(t,this.TARGET_SAMPLE_RATE*1*2,!0),t+=4,r.setUint16(t,1*2,!0),t+=2,r.setUint16(t,16,!0),t+=2,l(r,t,"data"),t+=4,r.setUint32(t,this.intSamples.length*1*2,!0),t+=4;for(let d=0;d<this.intSamples.length;d++)r.setInt16(t,this.intSamples[d],!0),t+=2;return new Blob([r],{type:"audio/wav"})}async requestMicrophonePermission(){try{return this.mediaStream=await navigator.mediaDevices.getUserMedia({audio:!0}),this.mediaStream.getAudioTracks().forEach(o=>{o.enabled=!1}),!0}catch(o){return console.error("Initial microphone permission denied:",o),!1}}async setupRecorder(){try{return this.mediaStream&&this.mediaStream.getAudioTracks().length>0?this.mediaStream.getAudioTracks().forEach(o=>{o.enabled=!0}):this.mediaStream=await navigator.mediaDevices.getUserMedia({audio:!0}),this.mediaRecorder=new MediaRecorder(this.mediaStream),this.mediaRecorder.ondataavailable=o=>{this.audioChunks.push(o.data)},this.mediaRecorder.onstop=async()=>{this.mediaStream.getTracks().forEach(o=>{o.enabled=!1}),this.mediaRecorder=null},!0}catch(o){return console.error("Microphone access error:",o),(o.name==="NotAllowedError"||o.name==="PermissionDeniedError")&&alert("Please enable microphone access in your browser settings to continue."),!1}}async startRecording(o){this.mediaRecorder.state==="inactive"&&(this.audioChunks=[],this.mediaRecorder.start(),this.intSamples=[],this.audioContext||(this.audioContext=new AudioContext),this.mediaStreamSource=this.audioContext.createMediaStreamSource(this.mediaStream),this.processor=this.audioContext.createScriptProcessor(this.BUFFER_SIZE,1,1),this.processor.onaudioprocess=async i=>{let n=i.inputBuffer.getChannelData(0),r=Math.ceil(this.BUFFER_SIZE*this.TARGET_SAMPLE_RATE/this.audioContext.sampleRate),t=new OfflineAudioContext(1,r,this.TARGET_SAMPLE_RATE),l=this.audioContext.createBuffer(1,n.length,this.audioContext.sampleRate);l.copyToChannel(n,0);let d=t.createBufferSource();d.buffer=l,d.connect(t.destination),d.start();let u=(await t.startRendering()).getChannelData(0),m=new Int16Array(u.length),b=0;for(let h=0;h<u.length;h++){let g=Math.max(-1,Math.min(1,u[h]));m[h]=g<0?g*32768:g*32767,this.intSamples.push(m[h]),b+=u[h]*u[h]}let R=Math.sqrt(b/u.length),L=new Uint8Array(m.buffer),C="";for(let h=0;h<L.length;h++)C+=String.fromCharCode(L[h]);let F=btoa(C);o&&o({audio:F,volume:R,packetDuration:this.BUFFER_SIZE/this.audioContext.sampleRate})},this.mediaStreamSource.connect(this.processor),this.processor.connect(this.audioContext.destination))}async stopRecording(){this.mediaRecorder&&this.mediaRecorder.state==="recording"&&this.mediaRecorder.stop(),this.processor&&(this.processor.disconnect(),this.processor=null),this.mediaStreamSource&&(this.mediaStreamSource.disconnect(),this.mediaStreamSource=null)}setupAudioAnalysis(){return this.audioContext||(this.audioContext=new AudioContext),this.analyser=this.audioContext.createAnalyser(),this.audioContext.createMediaStreamSource(this.mediaStream).connect(this.analyser),this.analyser.fftSize=32,this.dataArray=new Uint8Array(this.analyser.frequencyBinCount),{analyser:this.analyser,dataArray:this.dataArray}}getVolumeScale(){if(!this.analyser||!this.dataArray)return 0;this.analyser.getByteFrequencyData(this.dataArray);let o=this.dataArray.reduce((r,t)=>r+t,0)/this.dataArray.length,i=8,n=0;return o>i&&(n=Math.pow((o-i)/(255-i),1.5)),n}getIntSamples(){return this.intSamples}async closeAudioContext(){this.audioContext&&(await this.audioContext.close(),this.audioContext=null)}isRecording(){return this.mediaRecorder&&this.mediaRecorder.state==="recording"}};var W=class{constructor(){this.storageKeys={accessToken:"accessToken",tokenExpiration:"tokenExpiration"}}async generateAndStoreToken(){try{let o=await fetch("https://api.wisprflow.ai/api/v1/dash/webflow_demo/generate_token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_id:"webflow_demo"})});if(!o.ok)throw new Error(`Token generation failed with status: ${o.status}`);let i=await o.json();return localStorage.setItem(this.storageKeys.accessToken,i.access_token),localStorage.setItem(this.storageKeys.tokenExpiration,(Date.now()+i.expires_in*1e3).toString()),i.access_token}catch(o){throw console.error("Token generation failed:",o),o}}async getValidToken(){let o=localStorage.getItem(this.storageKeys.tokenExpiration);return!o||Date.now()>=parseInt(o)?await this.generateAndStoreToken():localStorage.getItem(this.storageKeys.accessToken)}};var _=class{constructor(o,i){this.tokenService=o,this.audioService=i,this.websocket=null,this.isWebSocketReady=!1,this.audioChunkBuffer=[],this.isBufferFlushNeeded=!1,this.bufferStartTime=null,this.packetPosition=0,this.transcriptionReceived=!1,this.commitTimeout=null,this.onTranscriptionReceived=null,this.onError=null}async setupWebSocket(){this.websocket&&this.websocket.readyState===WebSocket.CLOSED&&(this.websocket=null),this.websocket&&(this.websocket.readyState===WebSocket.OPEN||this.websocket.readyState===WebSocket.CONNECTING)&&(this.websocket.onclose=null,this.websocket.close(),this.websocket=null);let o=await this.tokenService.getValidToken(),i=`wss://api.wisprflow.ai/api/v1/dash/client_ws?client_key=Bearer ${o}`;console.log("Connecting to WebSocket"),this.websocket=new WebSocket(i),this.websocket.onopen=()=>{let r=new URLSearchParams(window.location.search).get("type")==="email"?"email":"other";this.websocket.send(JSON.stringify({type:"auth",access_token:`Bearer ${o}`,context:{app:{type:r}}}))},this.websocket.onmessage=n=>{try{let r=JSON.parse(n.data);if(r.status==="error"||r.status==="auth_error"){console.error("WebSocket error:",r),this.triggerFallback();return}if(r.status==="text"&&r.final)if(this.transcriptionReceived=!0,this.commitTimeout&&(clearTimeout(this.commitTimeout),this.commitTimeout=null),r.body&&r.body.text===null)console.log("Empty recording detected, skipping text display"),this.onTranscriptionReceived&&this.onTranscriptionReceived(null);else{let t="No speech detected.";r.body&&r.body.text?t=r.body.text:r.body.status==="formatted"?t=r.body.llm_text:r.body.status==="raw_transcript"&&(t=r.body.asr_text),this.onTranscriptionReceived&&this.onTranscriptionReceived(t)}}catch(r){console.error("WebSocket message parsing error:",r),this.triggerFallback()}},this.websocket.onclose=n=>{console.log("WebSocket closed:",n.code,n.reason),this.websocket=null,this.isWebSocketReady=!1},this.websocket.onerror=n=>{console.error("WebSocket error:",n)}}async connectWebSocketInBackground(){if(this.websocket&&this.websocket.readyState===WebSocket.CONNECTING){console.log("\u23F3 WebSocket already connecting, skipping duplicate call");return}try{this.isWebSocketReady=!1,await this.setupWebSocket();let o=0,i=50;for(;(!this.websocket||this.websocket.readyState!==WebSocket.OPEN)&&o<i;)await new Promise(n=>setTimeout(n,100)),o++;this.websocket&&this.websocket.readyState===WebSocket.OPEN?(this.isWebSocketReady=!0,console.log("\u2705 WebSocket marked as ready for streaming")):(console.log("WebSocket connection failed, will use fallback"),this.isWebSocketReady=!1)}catch(o){console.error("WebSocket background connection failed:",o),this.isWebSocketReady=!1}}flushAudioBuffer(){if(!this.isBufferFlushNeeded||this.audioChunkBuffer.length===0)return;console.log(`Flushing ${this.audioChunkBuffer.length} buffered audio chunks...`),this.audioChunkBuffer.forEach(i=>{try{this.websocket&&this.websocket.readyState===WebSocket.OPEN&&this.websocket.send(JSON.stringify(i))}catch(n){console.error(`Error sending buffered chunk ${i.position}:`,n)}});let o=this.bufferStartTime?Date.now()-this.bufferStartTime:0;console.log(`Buffer flushed! Buffering lasted ${o}ms`),this.audioChunkBuffer=[],this.isBufferFlushNeeded=!1,this.bufferStartTime=null}sendAudioChunk(o){let i={type:"append",position:this.packetPosition,final:!1,audio_packets:{packets:[o.audio],volumes:[o.volume],packet_duration:o.packetDuration,audio_encoding:"wav",byte_encoding:"base64"}};this.isWebSocketReady&&this.websocket&&this.websocket.readyState===WebSocket.OPEN?(this.isBufferFlushNeeded&&this.flushAudioBuffer(),this.websocket.send(JSON.stringify(i))):(this.audioChunkBuffer.push(i),this.isBufferFlushNeeded=!0,this.bufferStartTime||(this.bufferStartTime=Date.now()),this.packetPosition===0&&console.log("WebSocket not ready yet, buffering audio chunks")),this.packetPosition++}async commitRecording(){if(this.transcriptionReceived=!1,this.isWebSocketReady&&this.websocket&&this.websocket.readyState===WebSocket.OPEN)try{this.websocket.send(JSON.stringify({type:"commit",total_packets:this.packetPosition})),this.commitTimeout=setTimeout(()=>{this.transcriptionReceived||(console.log("WebSocket timeout, falling back to Fetch"),this.triggerFallback())},4e3)}catch(o){console.error("WebSocket commit failed:",o),this.triggerFallback()}else console.log("WebSocket not available, using Fetch fallback"),this.triggerFallback()}triggerFallback(){this.commitTimeout&&(clearTimeout(this.commitTimeout),this.commitTimeout=null),this.sendAudioToServerFallback()}async sendAudioToServerFallback(){try{console.log("Using Fetch API fallback with collected samples");let o=await this.audioService.convertIntSamplesToWAV(),i=await this.audioService.blobToBase64(o),n=await this.tokenService.getValidToken(),r=await fetch("https://api.wisprflow.ai/api/v1/dash/client_api",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({audio:i,properties:{language:""}})});if(!r.ok)throw new Error("Fallback server error");let t=await r.json();if(t.text===null){console.log("Empty fallback recording detected, skipping text display"),this.onTranscriptionReceived&&this.onTranscriptionReceived(null);return}this.onTranscriptionReceived&&this.onTranscriptionReceived(t.text)}catch(o){console.error("Fallback also failed:",o),this.onError&&this.onError(o)}}resetSession(){this.audioChunkBuffer=[],this.isBufferFlushNeeded=!1,this.bufferStartTime=null,this.packetPosition=0,this.transcriptionReceived=!1,this.commitTimeout&&(clearTimeout(this.commitTimeout),this.commitTimeout=null)}isReady(){return this.isWebSocketReady}};async function z(S="control"){let o=new W,i=new M,n=new _(o,i),r=()=>document.querySelector('.w--tab-active [demo-element="input"]'),t=r(),l=document.querySelector('[demo-element="gradient"]'),d=()=>document.querySelector(".wd_pill-wrap"),y=()=>document.querySelector(".wd_pill"),u=()=>y()?.querySelector(".wd_pill-lottie-wrap"),m=document.querySelectorAll('[demo-element="start-recording"]'),b=document.querySelectorAll('[demo-element="stop-recording"]'),R=new Audio("https://dl.dropbox.com/scl/fi/zv8278qh9ovwq0r89rch1/dictation-start.wav?rlkey=pk241hf4c8qv7780qsq2m4cgv&st=wgpy7vop&dl=0"),L=new Audio("https://dl.dropbox.com/scl/fi/4mkbgr7om46imcp0l86yd/dictation-stop.wav?rlkey=4t5uwvg9kufphlu58natjn43t&st=9or4oqr0&dl=0");function C(e){let s=document.getSelection();return s.rangeCount>0&&e.contains(s.focusNode)?s.getRangeAt(0):null}function F(e,s,a){a.deleteContents();let c=document.createElement("div");c.innerHTML=s;let p=document.createDocumentFragment();for(;c.firstChild;)p.appendChild(c.firstChild);a.insertNode(p),a.collapse(!1);let f=document.getSelection();f.removeAllRanges(),f.addRange(a)}function h(e){e.dataset.isPlaceholder==="true"?(e.classList.remove("cursor-after"),e.classList.add("cursor-before"),e.style.color="#1a1a1a80"):(e.classList.remove("cursor-before"),e.classList.add("cursor-after"),e.style.color="#1a1a1a")}let g=()=>{m.forEach(e=>{e&&(e.style.display="flex")}),document.querySelectorAll('[demo-element="start-recording-text"]').forEach(e=>{e&&(e.style.display="block")})},k=()=>{m.forEach(e=>{e&&(e.style.display="none")}),document.querySelectorAll('[demo-element="start-recording-text"]').forEach(e=>{e&&(e.style.display="none")})},Y=()=>{b.forEach(e=>{e&&(e.style.display="flex")}),document.querySelectorAll('[demo-element="stop-recording-text"]').forEach(e=>{e&&(e.style.display="block")})},I=()=>{b.forEach(e=>{e&&(e.style.display="none")}),document.querySelectorAll('[demo-element="stop-recording-text"]').forEach(e=>{e&&(e.style.display="none")})},x=window.matchMedia("(min-width: 992px)").matches,v=!1,T=!1,w=!0,P=!0,B=null,V=!1;i.requestMicrophonePermission().then(e=>{if(P=!1,!e){if(alert("Please enable microphone access in your browser settings to continue."),t||(t=r()),!t)return;document.querySelectorAll('[demo-element="input"]').forEach(s=>{s.innerHTML="Please enable microphone access in your browser settings to continue.",s.removeAttribute("contenteditable")}),t.classList.remove("cursor-before","cursor-after"),k(),w=!1,document.querySelectorAll('[ab-test="both-variants"]').forEach(s=>{s.style.display="none"})}}).catch(e=>{console.error("Initial microphone permission denied:",e),P=!1,alert("Please enable microphone access in your browser settings to continue."),t||(t=r()),t&&(document.querySelectorAll('[demo-element="input"]').forEach(s=>{s.innerHTML="Please enable microphone access in your browser settings to continue.",s.removeAttribute("contenteditable")}),t.classList.remove("cursor-before","cursor-after"),k(),w=!1,document.querySelectorAll('[ab-test="both-variants"]').forEach(s=>{s.style.display="none"}))}),l&&(l.style.opacity="0",l.style.transition="opacity 0.3s ease"),I(),navigator.userAgent.toLowerCase().includes("firefox")&&(document.querySelectorAll('[wd-para-div="hero-section"]').forEach(e=>{e.style.display="none"}),document.querySelectorAll('[ab-test="both-variants"]').forEach(e=>{e.querySelectorAll(".hide-tablet").forEach(s=>{s.classList.remove("hide-tablet"),s.classList.add("hide")})})),x&&t&&t.focus({preventScroll:!0}),document.querySelectorAll('[demo-element="input"]').forEach(e=>{e.classList.add("cursor-before"),e.dataset.isFirstRecording="true",e.dataset.placeholderText=e.textContent.trim(),e.dataset.placeholderHtml=e.innerHTML,e.dataset.isPlaceholder="true",e.addEventListener("beforeinput",()=>{e.dataset.isPlaceholder==="true"&&(e.innerHTML=""),e.dataset.isPlaceholder="false",h(e)}),e.addEventListener("input",()=>{if(e.textContent.trim()===""){e.innerHTML=e.dataset.placeholderHtml,e.dataset.isPlaceholder="true";let s=document.createRange();s.setStart(e,0),s.collapse(!0);let a=window.getSelection();a.removeAllRanges(),a.addRange(s)}h(e)}),e.addEventListener("focus",()=>{}),e.addEventListener("blur",()=>{e.textContent.trim()===""&&(e.innerHTML=e.dataset.placeholderHtml,e.dataset.isPlaceholder="true",e.dataset.isFirstRecording="true",h(e))}),e.addEventListener("mousedown",s=>{if(e.dataset.isPlaceholder==="true"){s.preventDefault();let a=document.createRange();a.setStart(e,0),a.collapse(!0);let c=window.getSelection();c.removeAllRanges(),c.addRange(a)}}),e.addEventListener("keydown",s=>{if(e.dataset.isPlaceholder==="true"&&["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Home","End"].includes(s.key)){s.preventDefault();let a=document.createRange();a.setStart(e,0),a.collapse(!0);let c=window.getSelection();c.removeAllRanges(),c.addRange(a)}})});let N=new MutationObserver(()=>{K()});N.observe(t,{childList:!0,subtree:!0,characterData:!0}),o.generateAndStoreToken().catch(e=>{console.error("Initial token generation failed:",e),t||(t=r()),t&&(document.querySelectorAll('[demo-element="input"]').forEach(s=>{s.innerHTML='Our servers are busy processing requests right now. <a href="/get-started" class="text-color-primary text-weight-medium">Try our desktop app instead.</a>',s.removeAttribute("contenteditable")}),t.classList.remove("cursor-before","cursor-after"),k(),w=!1,document.querySelectorAll('[ab-test="both-variants"]').forEach(s=>{s.style.display="none"}))});let O,K=()=>{t&&(t.scrollHeight>t.clientHeight?t.style.overflowY="auto":t.style.overflowY="visible")};n.onTranscriptionReceived=e=>{e===null?(u()?.classList.remove("show"),d()?.style.setProperty("opacity","0"),g(),I()):(Q(e+"\xA0"),g(),I(),u()?.classList.remove("show"),d()?.style.setProperty("opacity","0"))},n.onError=e=>{console.error("WebSocket service error:",e),t||(t=r()),t&&(document.querySelectorAll('[demo-element="input"]').forEach(s=>{s.innerHTML='Our servers are busy processing requests right now. <a href="/get-started" class="text-color-primary text-weight-medium">Try our desktop app instead.</a>',s.removeAttribute("contenteditable")}),t.classList.remove("cursor-before","cursor-after"),k(),w=!1,y()?.classList.remove("is-speaking"),u()?.classList.remove("show"),d()?.style.setProperty("opacity","0"),document.querySelectorAll('[ab-test="both-variants"]').forEach(s=>{s.style.display="none"}))};function Q(e){if(e=e.replace(/\n/g,"<br>"),e=e.replace(/<br>(?=\s*<\/?(?:ul|ol|li))|(?<=<\/?(?:ul|ol|li)>\s*)<br>/gi,""),!t)return;t.dataset.isPlaceholder==="true"&&(t.innerHTML=""),t.dataset.isPlaceholder="false",t.classList.remove("no-cursor");let s=C(t);if(s?F(t,e,s):t.textContent.trim()===""?t.innerHTML=e:t.innerHTML+=e,K(),t.dataset.previousText=t.textContent,t.dataset.isFirstRecording==="true"&&(t.classList.remove("cursor-before"),t.classList.add("cursor-after"),t.dataset.isFirstRecording="false"),typeof posthog<"u"){let c=document.querySelector(".w-tab-link.w--current"),p=c?c.textContent.trim().toLowerCase().replace(/\s+/g,"_"):"Unknown";posthog.capture("demo_transcription_completed",{transcribed_text:e,tab_name:p})}if(!V){V=!0,console.log("\u{1F3A8} Applying post-recording UI updates (first recording completed)"),document.querySelectorAll('[ab-test="download-button"]').forEach(f=>{f.style.display="block",f.style.visibility="visible"});let c=document.querySelectorAll('[demo-element="start-recording"]'),p=document.querySelectorAll('[demo-element="stop-recording"]');c.forEach(f=>f.classList.add("is-secondary")),p.forEach(f=>f.classList.add("is-secondary")),document.querySelectorAll('[ab-test="both-variants"] .wd-para').forEach(f=>{f.classList.add("text-style-muted")}),console.log("\u2705 Post-recording UI updates applied")}h(t),g()}async function J(){if(t||(t=r()),!t)return;m.forEach(a=>{a&&a.classList.remove("glow-purple")}),document.querySelectorAll(".wd-tab-link").forEach(a=>{a.classList.contains("w--current")||a.classList.add("pointer-events-none")}),n.resetSession(),n.connectWebSocketInBackground();let s=t.innerHTML||"";s&&!s.includes("Flow is listening")&&!s.includes("Converting...")&&!s.includes("Error")&&(t.dataset.previousText=s),t.classList.add("no-cursor");try{R.currentTime=0,R.play()}catch(a){console.error("Error playing start dictation sound:",a)}if(!i.mediaRecorder&&!await i.setupRecorder()){t.dataset.previousText?t.innerHTML=t.dataset.previousText:t.innerHTML="",t.classList.remove("no-cursor");return}if(!i.isRecording()){v=!0,await i.startRecording(c=>{n.sendAudioChunk(c)}),l&&(l.style.opacity="1"),d()?.style.setProperty("opacity","1"),y()?.classList.remove("is-speaking"),u()?.classList.remove("show");let a=document.querySelector(".wave-svg");a&&(a.style.opacity="1"),O=l.animate([{transform:"scale(1)"},{transform:"scale(1.3)"},{transform:"scale(1)"}],{duration:1500,iterations:1/0}),k(),Y(),i.setupAudioAnalysis(),B=setInterval(()=>{let c=i.getVolumeScale(),p=1+c*2,f=y();f&&(c>.06?f.classList.add("is-speaking"):f.classList.remove("is-speaking")),l.animate([{transform:`scale(${p})`}],{duration:300,fill:"forwards"});let j=document.querySelector(".wave-path");if(j){let q=40+c*300,U=Date.now()/1e3,H=E=>q*.3*Math.sin(E/1440*Math.PI*2+U*.8),$=E=>q*.2*Math.sin(E/720*Math.PI*2+U*1.2),G=E=>q*.1*Math.sin(E/360*Math.PI*2+U*1.8),te=`
|
|
2
2
|
M0,160
|
|
3
3
|
C120,${100+H(120)}
|
|
4
4
|
240,${220+$(240)}
|
|
5
|
-
480,${160+
|
|
5
|
+
480,${160+G(480)}
|
|
6
6
|
C720,${100+H(720)}
|
|
7
7
|
900,${220+$(900)}
|
|
8
|
-
1080,${160+
|
|
8
|
+
1080,${160+G(1080)}
|
|
9
9
|
C1260,${100+H(1260)}
|
|
10
10
|
1440,${220+$(1440)}
|
|
11
|
-
1440,${160+
|
|
11
|
+
1440,${160+G(1440)}
|
|
12
12
|
L1440,320 L0,320 Z
|
|
13
|
-
`;j.setAttribute("d",te)}},50)}}async function
|
|
13
|
+
`;j.setAttribute("d",te)}},50)}}async function D(){try{L.play()}catch(s){console.error("Error playing stop dictation sound:",s)}if(i.isRecording()){await i.stopRecording(),v=!1,l&&(l.style.opacity="0"),y()?.classList.remove("is-speaking"),d()?.style.setProperty("opacity","1"),u()?.classList.add("show");let s=document.querySelector(".wave-svg");s&&(s.style.opacity="0"),O&&O.cancel()}B&&(clearInterval(B),B=null),await i.closeAudioContext(),await n.commitRecording(),document.querySelectorAll(".wd-tab-link").forEach(s=>{s.classList.remove("pointer-events-none")})}let X=100,A=null;document.addEventListener("keydown",e=>{console.log("Key pressed:",e.key),x&&e.key==="Control"&&!T&&w&&!v&&(e.preventDefault(),T=!0,A=setTimeout(()=>{T&&J(!0)},X))}),document.addEventListener("keyup",async e=>{x&&e.key==="Control"&&(T=!1,clearTimeout(A),v&&await D())}),m.forEach(e=>{e&&e.addEventListener("click",s=>{s.preventDefault(),!P&&w&&J()})}),b.forEach(e=>{e&&e.addEventListener("click",async s=>{s.preventDefault(),!P&&await D()})});async function Z(){T=!1,A&&(clearTimeout(A),A=null),v&&await D(),y()?.classList.remove("is-speaking"),u()?.classList.remove("show"),d()?.style.setProperty("opacity","0")}function ee(){let e=document.querySelector(".wd-tab-link.w--current");if(e){let s=new URL(window.location);e.getAttribute("app-type")==="email"?s.searchParams.set("type","email"):s.searchParams.delete("type"),window.history.replaceState({},"",s)}}document.addEventListener("click",e=>{e.target.closest(".wd-tab-link")&&(x&&setTimeout(()=>{let a=r();if(a&&(a.focus(),a.dataset.isPlaceholder==="false")){let c=document.createRange(),p=window.getSelection();c.selectNodeContents(a),c.collapse(!1),p.removeAllRanges(),p.addRange(c)}},250),setTimeout(()=>{let a=r();a&&a!==t&&(t=a,N.disconnect(),N.observe(t,{childList:!0,subtree:!0,characterData:!0}))},320),setTimeout(()=>{ee()},100))}),window.addEventListener("blur",Z),document.addEventListener("visibilitychange",()=>{document.hidden&&Z()})}document.addEventListener("DOMContentLoaded",async function(){document.body.style.visibility="visible",await z(),console.log("Web demo initialized successfully")});window.addEventListener("pageshow",S=>{S.persisted&&(console.log("Page restored from bfcache - reloading..."),location.reload())});})();
|