@slycode/slycode 0.2.9 → 0.2.10
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/.next/BUILD_ID +1 -1
- package/dist/web/.next/build-manifest.json +2 -2
- package/dist/web/.next/server/app/_global-error.html +2 -2
- package/dist/web/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/.next/server/app/_not-found.html +1 -1
- package/dist/web/.next/server/app/_not-found.rsc +9 -9
- package/dist/web/.next/server/app/_not-found.segments/_full.segment.rsc +9 -9
- package/dist/web/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/dist/web/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
- package/dist/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/dist/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/dist/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/.next/server/app/project/[id]/page_client-reference-manifest.js +1 -1
- package/dist/web/.next/server/chunks/ssr/src_contexts_VoiceContext_tsx_cfba7292._.js +1 -1
- package/dist/web/.next/server/pages/404.html +1 -1
- package/dist/web/.next/server/pages/500.html +2 -2
- package/dist/web/.next/static/chunks/{0452f599128364c9.js → 8fb2a99c64580de7.js} +1 -1
- package/dist/web/.next/static/chunks/{2a22edae0b1198eb.js → b8e0c1aeea4a14bc.js} +1 -1
- package/dist/web/src/hooks/useVoiceRecorder.ts +7 -5
- package/dist/web/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/templates/kanban-seed.json +1 -1
- /package/dist/web/.next/static/{wK5osty7Iax92ZOE_Skb7 → _fCicMElBguqtWA_EpzdZ}/_buildManifest.js +0 -0
- /package/dist/web/.next/static/{wK5osty7Iax92ZOE_Skb7 → _fCicMElBguqtWA_EpzdZ}/_clientMiddlewareManifest.json +0 -0
- /package/dist/web/.next/static/{wK5osty7Iax92ZOE_Skb7 → _fCicMElBguqtWA_EpzdZ}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,1088,39269,9083,49996,e=>{"use strict";e.s(["VoiceProvider",()=>b,"useVoice",()=>v],1088);var r=e.i(18050),t=e.i(71645);function n(e,r){let t,n,o=(n=(t=r.split("+").map(e=>e.trim().toLowerCase()))[t.length-1],{ctrlKey:t.includes("ctrl"),shiftKey:t.includes("shift"),altKey:t.includes("alt"),metaKey:t.includes("meta")||t.includes("cmd"),key:"space"===n?" ":"escape"===n?"Escape":"enter"===n?"Enter":n});return(e.key.toLowerCase()===o.key.toLowerCase()||e.key===o.key)&&o.ctrlKey===e.ctrlKey&&o.shiftKey===e.shiftKey&&o.altKey===e.altKey&&o.metaKey===e.metaKey}let o={autoSubmitTerminal:!0,maxRecordingSeconds:300,shortcuts:{startRecording:"Ctrl+.",pauseResume:"Space",submit:"Enter",submitPasteOnly:"Shift+Enter",clear:"Escape"}},a={voice:o};var s=e.i(74080);function i({voiceState:e,elapsedSeconds:t,disabled:n,error:o,onRecord:a,onPause:s,onResume:i,onClear:d,onSubmit:l,onRetry:c,onOpenSettings:u}){let m;return(0,r.jsxs)("div",{className:`flex items-center gap-1.5 ${n?"opacity-40 pointer-events-none":""}`,children:[("idle"===e||"disabled"===e)&&(0,r.jsx)("button",{onClick:a,disabled:n,className:"rounded-md border border-void-400/30 bg-void-200/50 p-1.5 text-void-500 transition-all hover:border-red-400/40 hover:bg-red-400/10 hover:text-red-400 disabled:opacity-50 dark:border-void-500/25 dark:bg-void-700/50 dark:text-void-400 dark:hover:border-red-400/40 dark:hover:bg-red-400/10 dark:hover:text-red-400",title:"Start recording (Ctrl+.)",children:(0,r.jsx)("svg",{className:"h-4 w-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"})})}),("recording"===e||"paused"===e)&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("div",{className:"flex items-center gap-1.5 px-1",children:[(0,r.jsx)("span",{className:`inline-block h-2 w-2 rounded-full bg-red-500 ${"recording"===e?"animate-pulse":""}`}),(0,r.jsx)("span",{className:"min-w-[2.5rem] font-mono text-xs tabular-nums text-red-600 dark:text-red-400",children:(m=Math.floor(t/60),`${m}:${(t%60).toString().padStart(2,"0")}`)})]}),(0,r.jsx)("button",{onClick:"recording"===e?s:i,className:"rounded-md border border-void-400/30 bg-void-200/50 p-1.5 text-void-600 transition-all hover:border-neon-blue-400/40 hover:bg-neon-blue-400/10 hover:text-neon-blue-400 dark:border-void-500/25 dark:bg-void-700/50 dark:text-void-400 dark:hover:border-neon-blue-400/40 dark:hover:bg-neon-blue-400/10 dark:hover:text-neon-blue-400",title:"recording"===e?"Pause (Space)":"Resume (Space)",children:"recording"===e?(0,r.jsxs)("svg",{className:"h-3.5 w-3.5",fill:"currentColor",viewBox:"0 0 24 24",children:[(0,r.jsx)("rect",{x:"6",y:"4",width:"4",height:"16"}),(0,r.jsx)("rect",{x:"14",y:"4",width:"4",height:"16"})]}):(0,r.jsx)("svg",{className:"h-3.5 w-3.5",fill:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("polygon",{points:"5,3 19,12 5,21"})})}),(0,r.jsx)("button",{onClick:d,className:"rounded-md border border-void-400/30 bg-void-200/50 p-1.5 text-void-600 transition-all hover:border-red-400/40 hover:bg-red-400/10 hover:text-red-400 dark:border-void-500/25 dark:bg-void-700/50 dark:text-void-400 dark:hover:border-red-400/40 dark:hover:bg-red-400/10 dark:hover:text-red-400",title:"Clear recording (Escape)",children:(0,r.jsx)("svg",{className:"h-3.5 w-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})}),(0,r.jsx)("button",{onClick:l,className:"rounded-md border border-green-400/40 bg-green-400/15 px-2 py-1.5 text-xs font-medium text-green-600 transition-all hover:bg-green-400/25 hover:shadow-[0_0_8px_rgba(34,197,94,0.2)] dark:text-green-400",title:"Submit for transcription (Enter)",children:(0,r.jsx)("svg",{className:"h-3.5 w-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})})})]}),"transcribing"===e&&(0,r.jsxs)("div",{className:"flex items-center gap-1.5 px-1",children:[(0,r.jsxs)("svg",{className:"h-4 w-4 animate-spin text-[#2490b5] dark:text-neon-blue-400",viewBox:"0 0 24 24",fill:"none",children:[(0,r.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),(0,r.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"})]}),(0,r.jsx)("span",{className:"text-xs text-[#2490b5] dark:text-neon-blue-400",children:"Transcribing..."})]}),"error"===e&&(0,r.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,r.jsx)("span",{className:"text-xs text-red-400",title:o||"Transcription failed",children:"Failed"}),(0,r.jsx)("button",{onClick:c,className:"rounded-md border border-neon-blue-400/40 bg-neon-blue-400/15 px-1.5 py-1 text-xs font-medium text-neon-blue-400 transition-all hover:bg-neon-blue-400/25",title:"Retry transcription",children:"Retry"}),(0,r.jsx)("button",{onClick:d,className:"rounded-md border border-void-400/30 bg-void-200/50 p-1.5 text-void-600 transition-all hover:border-red-400/40 hover:bg-red-400/10 hover:text-red-400 dark:border-void-500/25 dark:bg-void-700/50 dark:text-void-400 dark:hover:border-red-400/40 dark:hover:bg-red-400/10 dark:hover:text-red-400",title:"Clear",children:(0,r.jsx)("svg",{className:"h-3.5 w-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),(0,r.jsx)("button",{onClick:u,className:"rounded-md border border-void-400/30 bg-void-200/50 p-1.5 text-void-500 transition-all hover:border-void-400/50 hover:text-void-700 dark:border-void-500/25 dark:bg-void-700/50 dark:text-void-400 dark:hover:border-void-400/50 dark:hover:text-void-300",title:"Voice settings",children:(0,r.jsxs)("svg",{className:"h-3.5 w-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:[(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"}),(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M15 12a3 3 0 11-6 0 3 3 0 016 0z"})]})})]})}function d({label:e,value:n,onChange:o}){let[a,s]=(0,t.useState)(!1),i=(0,t.useRef)(null),d=(0,t.useCallback)(e=>{if(!a)return;e.preventDefault(),e.stopPropagation();let r=[];e.ctrlKey&&r.push("Ctrl"),e.shiftKey&&r.push("Shift"),e.altKey&&r.push("Alt"),e.metaKey&&r.push("Cmd");let t=e.key;if(!["Control","Shift","Alt","Meta"].includes(t)){let e=" "===t?"Space":"Escape"===t?"Escape":"Enter"===t?"Enter":(t.length,t);r.push(e),o(r.join("+")),s(!1)}},[a,o]);return(0,r.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,r.jsx)("span",{className:"text-xs text-void-600 dark:text-void-400",children:e}),(0,r.jsx)("input",{ref:i,type:"text",value:a?"Press keys...":n,readOnly:!0,onFocus:()=>s(!0),onBlur:()=>s(!1),onKeyDown:d,className:`w-28 rounded border px-2 py-1 text-center text-xs ${a?"border-neon-blue-400 bg-neon-blue-400/10 text-neon-blue-600 dark:text-neon-blue-400":"border-void-300 bg-void-50 text-void-700 dark:border-void-600 dark:bg-void-700 dark:text-void-300"} cursor-pointer outline-none`})]})}function l({settings:e,onSave:n,onClose:o}){let a=(0,t.useRef)(null),[s,i]=(0,t.useState)({...e.shortcuts}),[l,c]=(0,t.useState)(e.autoSubmitTerminal),[u,m]=(0,t.useState)(Math.round(e.maxRecordingSeconds/60)),v=(0,t.useRef)({shortcuts:s,autoSubmit:l,maxMinutes:u});return v.current={shortcuts:s,autoSubmit:l,maxMinutes:u},(0,t.useEffect)(()=>()=>{let{shortcuts:e,autoSubmit:r,maxMinutes:t}=v.current;n({shortcuts:e,autoSubmitTerminal:r,maxRecordingSeconds:60*Math.max(1,t)})},[]),(0,t.useEffect)(()=>{let e=e=>{a.current&&!a.current.contains(e.target)&&o()};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[o]),(0,r.jsxs)("div",{ref:a,className:"w-80 rounded-lg border border-void-200 bg-white p-4 shadow-(--shadow-overlay) dark:border-void-600 dark:bg-void-800",children:[(0,r.jsx)("h3",{className:"mb-3 text-sm font-medium text-void-800 dark:text-void-200",children:"Voice Settings"}),(0,r.jsxs)("div",{className:"mb-4 space-y-2",children:[(0,r.jsx)("div",{className:"text-xs font-medium text-void-500 dark:text-void-400",children:"Keyboard Shortcuts"}),(0,r.jsx)(d,{label:"Start recording",value:s.startRecording,onChange:e=>i(r=>({...r,startRecording:e}))}),(0,r.jsx)(d,{label:"Pause / Resume",value:s.pauseResume,onChange:e=>i(r=>({...r,pauseResume:e}))}),(0,r.jsx)(d,{label:"Submit",value:s.submit,onChange:e=>i(r=>({...r,submit:e}))}),(0,r.jsx)(d,{label:"Paste only",value:s.submitPasteOnly,onChange:e=>i(r=>({...r,submitPasteOnly:e}))}),(0,r.jsx)(d,{label:"Clear / Cancel",value:s.clear,onChange:e=>i(r=>({...r,clear:e}))})]}),(0,r.jsxs)("div",{className:"space-y-3 border-t border-void-200 pt-3 dark:border-void-600",children:[(0,r.jsx)("div",{className:"text-xs font-medium text-void-500 dark:text-void-400",children:"Behaviour"}),(0,r.jsxs)("label",{className:"flex items-center justify-between gap-2",children:[(0,r.jsx)("span",{className:"text-xs text-void-600 dark:text-void-400",children:"Auto-submit (terminal)"}),(0,r.jsx)("button",{type:"button",role:"switch","aria-checked":l,onClick:()=>c(!l),className:`relative inline-flex h-5 w-9 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors ${l?"bg-green-500":"bg-void-300 dark:bg-void-600"}`,children:(0,r.jsx)("span",{className:`pointer-events-none inline-block h-4 w-4 transform rounded-full bg-white shadow transition ${l?"translate-x-4":"translate-x-0"}`})})]}),(0,r.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,r.jsx)("span",{className:"text-xs text-void-600 dark:text-void-400",children:"Max recording (min)"}),(0,r.jsx)("input",{type:"number",min:1,max:30,value:u,onChange:e=>m(parseInt(e.target.value)||5),className:"w-16 rounded border border-void-300 bg-void-50 px-2 py-1 text-center text-xs text-void-700 outline-none dark:border-void-600 dark:bg-void-700 dark:text-void-300"})]})]})]})}function c({error:e,hasRecording:n,onRetry:o,onClear:a,onClose:s}){let i=(0,t.useRef)(null);(0,t.useEffect)(()=>{let e=e=>{i.current&&!i.current.contains(e.target)&&s()};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[s]);let d=window.isSecureContext,l=!n;return(0,r.jsxs)("div",{ref:i,className:"w-72 rounded-lg border border-red-400/30 bg-white p-3 shadow-(--shadow-overlay) dark:border-red-400/20 dark:bg-void-800",children:[(0,r.jsxs)("div",{className:"mb-2 flex items-start gap-2",children:[(0,r.jsx)("svg",{className:"mt-0.5 h-4 w-4 flex-shrink-0 text-red-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"})}),(0,r.jsxs)("div",{children:[(0,r.jsx)("div",{className:"text-xs font-medium text-red-600 dark:text-red-400",children:l?"Recording Failed":"Transcription Failed"}),(0,r.jsx)("div",{className:"mt-1 text-xs text-void-600 dark:text-void-300",children:e})]})]}),(0,r.jsx)("div",{className:"mt-2 text-xs text-void-500 dark:text-void-400",children:l&&!d?"Microphone requires HTTPS or localhost. Try accessing via localhost:3003, or add this origin to chrome://flags/#unsafely-treat-insecure-origin-as-secure.":l?"Could not access the microphone.":"Your recording is preserved. You can retry or clear and start over."}),(0,r.jsxs)("div",{className:"mt-3 flex justify-end gap-2",children:[(0,r.jsx)("button",{onClick:a,className:"rounded border border-void-300 bg-void-100 px-2 py-1 text-xs text-void-600 hover:text-void-800 dark:border-void-600 dark:bg-void-700 dark:text-void-400 dark:hover:text-void-300",children:l?"Dismiss":"Clear"}),n&&o&&(0,r.jsx)("button",{onClick:o,className:"rounded border border-neon-blue-400/40 bg-neon-blue-400/15 px-2 py-1 text-xs text-neon-blue-600 hover:bg-neon-blue-400/25 dark:text-neon-blue-400",children:"Retry"})]})]})}function u(){let e=v(),n=(0,t.useRef)(null),o=(0,t.useRef)(0),[a,d]=(0,t.useState)(!1);return((0,t.useEffect)(()=>{d(!0)},[]),null===e.currentClaimantId&&a&&("idle"!==e.voiceState&&"disabled"!==e.voiceState||e.showSettings))?(0,s.createPortal)((0,r.jsxs)("div",{className:"fixed bottom-4 right-4 z-50 animate-in fade-in slide-in-from-bottom-2 duration-200 rounded-xl border border-red-400/30 bg-white/95 px-3 py-2 shadow-(--shadow-card) backdrop-blur-sm dark:border-red-400/20 dark:bg-void-800/95",ref:n,children:[(0,r.jsx)(i,{voiceState:e.voiceState,elapsedSeconds:e.elapsedSeconds,disabled:!1,error:e.error,onRecord:e.startRecording,onPause:e.pauseRecording,onResume:e.resumeRecording,onClear:e.clearRecording,onSubmit:e.submitRecording,onRetry:e.retryTranscription,onOpenSettings:()=>{Date.now()-o.current<200||e.setShowSettings(!e.showSettings)}}),e.showSettings&&(0,r.jsx)("div",{style:{position:"fixed",bottom:60,right:16,zIndex:9999},children:(0,r.jsx)(l,{settings:e.settings.voice,onSave:r=>e.updateSettings({voice:r}),onClose:()=>{o.current=Date.now(),e.setShowSettings(!1)}})}),"error"===e.voiceState&&e.error&&(0,r.jsx)("div",{style:{position:"fixed",bottom:60,right:16,zIndex:9999},children:(0,r.jsx)(c,{error:e.error,hasRecording:e.hasRecording,onRetry:()=>e.retryTranscription(),onClear:()=>e.clearRecording(),onClose:()=>e.clearRecording()})})]}),document.body):null}e.s(["VoiceControlBar",()=>i],39269),e.s(["VoiceSettingsPopover",()=>l],9083),e.s(["VoiceErrorPopup",()=>c],49996);let m=(0,t.createContext)(null);function v(){let e=(0,t.useContext)(m);if(!e)throw Error("useVoice() must be used inside <VoiceProvider>");return e}function b({children:e}){let{settings:s,updateSettings:i}=function(){let[e,r]=(0,t.useState)(a),[n,s]=(0,t.useState)(!0);return(0,t.useEffect)(()=>{fetch("/api/settings").then(e=>e.json()).then(e=>{r({...a,...e,voice:{...o,...e?.voice}})}).catch(()=>{}).finally(()=>s(!1))},[]),{settings:e,updateSettings:(0,t.useCallback)(async e=>{try{let t=await fetch("/api/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(t.ok){let e=await t.json();return r({...a,...e,voice:{...o,...e?.voice}}),e}}catch{}return null},[]),isLoading:n}}(),d=(0,t.useRef)(new Map),l=(0,t.useRef)(null),c=(0,t.useCallback)((e,r)=>{d.current.set(e,r),l.current=e},[]),v=(0,t.useCallback)(e=>{if(d.current.delete(e),l.current===e){let e=Array.from(d.current.keys());l.current=e.length>0?e[0]:null}},[]),b=(0,t.useRef)(null),[x,h]=(0,t.useState)(null),p=(0,t.useRef)(null),g=(0,t.useRef)("auto"),[f,k]=(0,t.useState)(!1),[y,R]=(0,t.useState)(!1),j=(0,t.useCallback)(e=>{let r=p.current;if(r){if("input"===r.type&&r.element){if(!document.contains(r.element))return;let t=r.element,n=t.selectionStart??t.value.length,o=t.selectionEnd??t.value.length;t.focus(),t.setSelectionRange(n,o),document.execCommand("insertText",!1,e)}else if("terminal"===r.type&&r.terminalId){let t=d.current.get(r.terminalId);if(!t)return;let n="auto"===g.current&&s.voice.autoSubmitTerminal;t.sendInput(e),n&&setTimeout(()=>t.sendInput("\r"),300)}g.current="auto"}},[s.voice.autoSubmitTerminal]),w=(0,t.useCallback)(e=>{b.current?b.current.onTranscriptionComplete(e):j(e)},[j]),C=function({maxRecordingSeconds:e,onTranscriptionComplete:r}){let[n,o]=(0,t.useState)("idle"),[a,s]=(0,t.useState)(0),[i,d]=(0,t.useState)(null),[l,c]=(0,t.useState)(null),u=(0,t.useRef)(null),m=(0,t.useRef)([]),v=(0,t.useRef)(null),b=(0,t.useRef)(null),x=(0,t.useRef)(null),h=(0,t.useRef)(0),p=(0,t.useRef)(!1),g=(0,t.useRef)(r);(0,t.useEffect)(()=>{g.current=r},[r]);let f=(0,t.useCallback)(()=>{v.current||(v.current=setInterval(()=>{s(e=>e+1)},1e3))},[]),k=(0,t.useCallback)(()=>{v.current&&(clearInterval(v.current),v.current=null)},[]);(0,t.useEffect)(()=>{"recording"===n&&a-h.current>=e&&(u.current?.state==="recording"&&u.current.pause(),p.current=!0,k(),o("paused"))},[n,a,e,k]),(0,t.useEffect)(()=>()=>{if(k(),u.current?.state!=="inactive")try{u.current?.stop()}catch{}x.current?.getTracks().forEach(e=>e.stop())},[k]);let y=(0,t.useCallback)(()=>new Promise(e=>{let r=u.current;r&&"inactive"!==r.state?(r.ondataavailable=e=>{e.data.size>0&&m.current.push(e.data)},r.onstop=()=>{e(new Blob(m.current,{type:m.current[0]?.type||"audio/webm"}))},r.stop()):e(new Blob(m.current,{type:m.current[0]?.type||"audio/webm"}))}),[]),R=(0,t.useCallback)(async e=>{let r=new FormData;r.append("audio",e,"recording.webm");let t=await fetch("/api/transcribe",{method:"POST",body:r}),n=await t.json();if(!t.ok)throw Error(n.error||"Transcription failed");return n.text},[]),j=(0,t.useCallback)(()=>{x.current?.getTracks().forEach(e=>e.stop()),x.current=null},[]),w=(0,t.useCallback)(async()=>{if("idle"===n||"disabled"===n)try{d(null),c(null),m.current=[],b.current=null,s(0),h.current=0;let e=await navigator.mediaDevices.getUserMedia({audio:!0});x.current=e;let r=MediaRecorder.isTypeSupported("audio/webm;codecs=opus")?"audio/webm;codecs=opus":MediaRecorder.isTypeSupported("audio/mp4")?"audio/mp4":"",t=new MediaRecorder(e,r?{mimeType:r}:void 0);u.current=t,t.ondataavailable=e=>{e.data.size>0&&m.current.push(e.data)},t.start(1e3),o("recording"),f()}catch(r){let e=r.message;e.includes("Permission")||e.includes("NotAllowed")?d("Microphone permission denied. Please allow microphone access."):d(e||"Failed to start recording"),o("error"),j()}},[n,f,j]),C=(0,t.useCallback)(()=>{"recording"===n&&(u.current?.state==="recording"&&u.current.pause(),k(),o("paused"))},[n,k]),S=(0,t.useCallback)(()=>{"paused"===n&&(u.current?.state==="paused"&&u.current.resume(),p.current&&(h.current=a,p.current=!1),f(),o("recording"))},[n,a,f]),N=(0,t.useCallback)(()=>{if(k(),u.current?.state!=="inactive")try{u.current?.stop()}catch{}m.current=[],b.current=null,s(0),d(null),c(null),j(),o("idle")},[k,j]),E=(0,t.useCallback)(async()=>{if("recording"===n||"paused"===n){k(),o("transcribing");try{let e=await y();b.current=e,j();let r=await R(e);c(r),s(0),m.current=[],o("idle"),g.current?.(r)}catch(e){d(e.message||"Transcription failed"),o("error")}}},[n,k,y,R,j]),T=(0,t.useCallback)(async()=>{if("error"===n&&b.current){o("transcribing"),d(null);try{let e=await R(b.current);c(e),b.current=null,m.current=[],s(0),o("idle"),g.current?.(e)}catch(e){d(e.message||"Transcription failed"),o("error")}}},[n,R]);return{state:n,elapsedSeconds:a,error:i,transcribedText:l,hasRecording:null!==b.current||m.current.length>0,startRecording:w,pauseRecording:C,resumeRecording:S,clearRecording:N,submitRecording:E,retryTranscription:T}}({maxRecordingSeconds:s.voice.maxRecordingSeconds,onTranscriptionComplete:w}),S=(0,t.useCallback)(e=>{b.current&&b.current.id!==e.id&&(b.current.onRelease?.(),"idle"!==C.state&&"disabled"!==C.state&&C.clearRecording()),b.current=e,h(e.id)},[C]),N=(0,t.useCallback)(e=>{b.current?.id===e.id&&("idle"!==C.state&&"error"!==C.state&&"disabled"!==C.state&&C.clearRecording(),b.current=null,h(null))},[C]);(0,t.useEffect)(()=>{let e=e=>{let r=e.target;if(r.closest("[data-voice-target]")&&("INPUT"===r.tagName||"TEXTAREA"===r.tagName))return void R(!0);if(r.closest("[data-terminal-id]")){let e=r.closest("[data-terminal-id]").dataset.terminalId;e&&d.current.has(e)&&(l.current=e,R(!0))}},r=()=>{setTimeout(()=>{let e=document.activeElement;if(!e)return void R(!1);let r=e.closest("[data-voice-target]")&&("INPUT"===e.tagName||"TEXTAREA"===e.tagName),t=e.closest("[data-terminal-id]");r||t||R(!1)},100)};return document.addEventListener("focusin",e),document.addEventListener("focusout",r),()=>{document.removeEventListener("focusin",e),document.removeEventListener("focusout",r)}},[]);let E=(0,t.useCallback)(()=>{if(b.current)b.current.onRecordStart?.(),C.startRecording();else{let e=document.activeElement;if(e&&("INPUT"===e.tagName||"TEXTAREA"===e.tagName)&&e.closest("[data-voice-target]"))p.current={type:"input",element:e};else if(e?.closest("[data-terminal-id]")){let r=e.closest("[data-terminal-id]").dataset.terminalId||l.current;if(!(r&&d.current.has(r)))return;p.current={type:"terminal",terminalId:r}}else{if(!(l.current&&d.current.has(l.current)))return;p.current={type:"terminal",terminalId:l.current}}C.startRecording()}},[C]),T=(0,t.useCallback)(()=>{g.current="paste",C.submitRecording()},[C]),P=(0,t.useCallback)(()=>{"recording"===C.state?C.pauseRecording():"paused"===C.state&&C.resumeRecording()},[C]);!function({voiceState:e,shortcuts:r,callbacks:o,enabled:a,hasFieldFocus:s,suspended:i}){let d=(0,t.useRef)(o),l=(0,t.useRef)(e),c=(0,t.useRef)(r),u=(0,t.useRef)(s),m=(0,t.useRef)(i);(0,t.useEffect)(()=>{d.current=o,l.current=e,c.current=r,u.current=s,m.current=i}),(0,t.useEffect)(()=>{if(!a)return;let e=e=>{if(m.current)return;let r=l.current,t=c.current,o=d.current;if("idle"===r&&u.current&&n(e,t.startRecording)){e.preventDefault(),e.stopPropagation(),o.onStartRecording();return}if("recording"===r||"paused"===r){if(n(e,t.pauseResume)){e.preventDefault(),e.stopPropagation(),o.onPauseResume();return}if(n(e,t.submitPasteOnly)){e.preventDefault(),e.stopPropagation(),o.onSubmitPasteOnly();return}if(n(e,t.submit)){e.preventDefault(),e.stopPropagation(),o.onSubmit();return}if(n(e,t.clear)){e.preventDefault(),e.stopPropagation(),o.onClear();return}}};return document.addEventListener("keydown",e,!0),()=>document.removeEventListener("keydown",e,!0)},[a])}({voiceState:C.state,shortcuts:s.voice.shortcuts,callbacks:{onStartRecording:E,onPauseResume:P,onSubmit:C.submitRecording,onSubmitPasteOnly:T,onClear:C.clearRecording},enabled:!0,hasFieldFocus:!!b.current||y,suspended:f});let L={voiceState:C.state,elapsedSeconds:C.elapsedSeconds,error:C.error,hasRecording:C.hasRecording,startRecording:C.startRecording,pauseRecording:C.pauseRecording,resumeRecording:C.resumeRecording,clearRecording:C.clearRecording,submitRecording:C.submitRecording,retryTranscription:C.retryTranscription,claimVoiceControl:S,releaseVoiceControl:N,currentClaimantId:x,settings:s,updateSettings:i,registerTerminal:c,unregisterTerminal:v,submitModeRef:g,showSettings:f,setShowSettings:k,hasFieldFocus:y,setHasFieldFocus:R};return(0,r.jsxs)(m.Provider,{value:L,children:[e,(0,r.jsx)(u,{})]})}}]);
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,1088,39269,9083,49996,e=>{"use strict";e.s(["VoiceProvider",()=>b,"useVoice",()=>v],1088);var r=e.i(18050),t=e.i(71645);function n(e,r){let t,n,o=(n=(t=r.split("+").map(e=>e.trim().toLowerCase()))[t.length-1],{ctrlKey:t.includes("ctrl"),shiftKey:t.includes("shift"),altKey:t.includes("alt"),metaKey:t.includes("meta")||t.includes("cmd"),key:"space"===n?" ":"escape"===n?"Escape":"enter"===n?"Enter":n});return(e.key.toLowerCase()===o.key.toLowerCase()||e.key===o.key)&&o.ctrlKey===e.ctrlKey&&o.shiftKey===e.shiftKey&&o.altKey===e.altKey&&o.metaKey===e.metaKey}let o={autoSubmitTerminal:!0,maxRecordingSeconds:300,shortcuts:{startRecording:"Ctrl+.",pauseResume:"Space",submit:"Enter",submitPasteOnly:"Shift+Enter",clear:"Escape"}},a={voice:o};var s=e.i(74080);function i({voiceState:e,elapsedSeconds:t,disabled:n,error:o,onRecord:a,onPause:s,onResume:i,onClear:d,onSubmit:c,onRetry:l,onOpenSettings:u}){let m;return(0,r.jsxs)("div",{className:`flex items-center gap-1.5 ${n?"opacity-40 pointer-events-none":""}`,children:[("idle"===e||"disabled"===e)&&(0,r.jsx)("button",{onClick:a,disabled:n,className:"rounded-md border border-void-400/30 bg-void-200/50 p-1.5 text-void-500 transition-all hover:border-red-400/40 hover:bg-red-400/10 hover:text-red-400 disabled:opacity-50 dark:border-void-500/25 dark:bg-void-700/50 dark:text-void-400 dark:hover:border-red-400/40 dark:hover:bg-red-400/10 dark:hover:text-red-400",title:"Start recording (Ctrl+.)",children:(0,r.jsx)("svg",{className:"h-4 w-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z"})})}),("recording"===e||"paused"===e)&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("div",{className:"flex items-center gap-1.5 px-1",children:[(0,r.jsx)("span",{className:`inline-block h-2 w-2 rounded-full bg-red-500 ${"recording"===e?"animate-pulse":""}`}),(0,r.jsx)("span",{className:"min-w-[2.5rem] font-mono text-xs tabular-nums text-red-600 dark:text-red-400",children:(m=Math.floor(t/60),`${m}:${(t%60).toString().padStart(2,"0")}`)})]}),(0,r.jsx)("button",{onClick:"recording"===e?s:i,className:"rounded-md border border-void-400/30 bg-void-200/50 p-1.5 text-void-600 transition-all hover:border-neon-blue-400/40 hover:bg-neon-blue-400/10 hover:text-neon-blue-400 dark:border-void-500/25 dark:bg-void-700/50 dark:text-void-400 dark:hover:border-neon-blue-400/40 dark:hover:bg-neon-blue-400/10 dark:hover:text-neon-blue-400",title:"recording"===e?"Pause (Space)":"Resume (Space)",children:"recording"===e?(0,r.jsxs)("svg",{className:"h-3.5 w-3.5",fill:"currentColor",viewBox:"0 0 24 24",children:[(0,r.jsx)("rect",{x:"6",y:"4",width:"4",height:"16"}),(0,r.jsx)("rect",{x:"14",y:"4",width:"4",height:"16"})]}):(0,r.jsx)("svg",{className:"h-3.5 w-3.5",fill:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("polygon",{points:"5,3 19,12 5,21"})})}),(0,r.jsx)("button",{onClick:d,className:"rounded-md border border-void-400/30 bg-void-200/50 p-1.5 text-void-600 transition-all hover:border-red-400/40 hover:bg-red-400/10 hover:text-red-400 dark:border-void-500/25 dark:bg-void-700/50 dark:text-void-400 dark:hover:border-red-400/40 dark:hover:bg-red-400/10 dark:hover:text-red-400",title:"Clear recording (Escape)",children:(0,r.jsx)("svg",{className:"h-3.5 w-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})}),(0,r.jsx)("button",{onClick:c,className:"rounded-md border border-green-400/40 bg-green-400/15 px-2 py-1.5 text-xs font-medium text-green-600 transition-all hover:bg-green-400/25 hover:shadow-[0_0_8px_rgba(34,197,94,0.2)] dark:text-green-400",title:"Submit for transcription (Enter)",children:(0,r.jsx)("svg",{className:"h-3.5 w-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})})})]}),"transcribing"===e&&(0,r.jsxs)("div",{className:"flex items-center gap-1.5 px-1",children:[(0,r.jsxs)("svg",{className:"h-4 w-4 animate-spin text-[#2490b5] dark:text-neon-blue-400",viewBox:"0 0 24 24",fill:"none",children:[(0,r.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),(0,r.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"})]}),(0,r.jsx)("span",{className:"text-xs text-[#2490b5] dark:text-neon-blue-400",children:"Transcribing..."})]}),"error"===e&&(0,r.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,r.jsx)("span",{className:"text-xs text-red-400",title:o||"Transcription failed",children:"Failed"}),(0,r.jsx)("button",{onClick:l,className:"rounded-md border border-neon-blue-400/40 bg-neon-blue-400/15 px-1.5 py-1 text-xs font-medium text-neon-blue-400 transition-all hover:bg-neon-blue-400/25",title:"Retry transcription",children:"Retry"}),(0,r.jsx)("button",{onClick:d,className:"rounded-md border border-void-400/30 bg-void-200/50 p-1.5 text-void-600 transition-all hover:border-red-400/40 hover:bg-red-400/10 hover:text-red-400 dark:border-void-500/25 dark:bg-void-700/50 dark:text-void-400 dark:hover:border-red-400/40 dark:hover:bg-red-400/10 dark:hover:text-red-400",title:"Clear",children:(0,r.jsx)("svg",{className:"h-3.5 w-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),(0,r.jsx)("button",{onClick:u,className:"rounded-md border border-void-400/30 bg-void-200/50 p-1.5 text-void-500 transition-all hover:border-void-400/50 hover:text-void-700 dark:border-void-500/25 dark:bg-void-700/50 dark:text-void-400 dark:hover:border-void-400/50 dark:hover:text-void-300",title:"Voice settings",children:(0,r.jsxs)("svg",{className:"h-3.5 w-3.5",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:[(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"}),(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M15 12a3 3 0 11-6 0 3 3 0 016 0z"})]})})]})}function d({label:e,value:n,onChange:o}){let[a,s]=(0,t.useState)(!1),i=(0,t.useRef)(null),d=(0,t.useCallback)(e=>{if(!a)return;e.preventDefault(),e.stopPropagation();let r=[];e.ctrlKey&&r.push("Ctrl"),e.shiftKey&&r.push("Shift"),e.altKey&&r.push("Alt"),e.metaKey&&r.push("Cmd");let t=e.key;if(!["Control","Shift","Alt","Meta"].includes(t)){let e=" "===t?"Space":"Escape"===t?"Escape":"Enter"===t?"Enter":(t.length,t);r.push(e),o(r.join("+")),s(!1)}},[a,o]);return(0,r.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,r.jsx)("span",{className:"text-xs text-void-600 dark:text-void-400",children:e}),(0,r.jsx)("input",{ref:i,type:"text",value:a?"Press keys...":n,readOnly:!0,onFocus:()=>s(!0),onBlur:()=>s(!1),onKeyDown:d,className:`w-28 rounded border px-2 py-1 text-center text-xs ${a?"border-neon-blue-400 bg-neon-blue-400/10 text-neon-blue-600 dark:text-neon-blue-400":"border-void-300 bg-void-50 text-void-700 dark:border-void-600 dark:bg-void-700 dark:text-void-300"} cursor-pointer outline-none`})]})}function c({settings:e,onSave:n,onClose:o}){let a=(0,t.useRef)(null),[s,i]=(0,t.useState)({...e.shortcuts}),[c,l]=(0,t.useState)(e.autoSubmitTerminal),[u,m]=(0,t.useState)(Math.round(e.maxRecordingSeconds/60)),v=(0,t.useRef)({shortcuts:s,autoSubmit:c,maxMinutes:u});return v.current={shortcuts:s,autoSubmit:c,maxMinutes:u},(0,t.useEffect)(()=>()=>{let{shortcuts:e,autoSubmit:r,maxMinutes:t}=v.current;n({shortcuts:e,autoSubmitTerminal:r,maxRecordingSeconds:60*Math.max(1,t)})},[]),(0,t.useEffect)(()=>{let e=e=>{a.current&&!a.current.contains(e.target)&&o()};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[o]),(0,r.jsxs)("div",{ref:a,className:"w-80 rounded-lg border border-void-200 bg-white p-4 shadow-(--shadow-overlay) dark:border-void-600 dark:bg-void-800",children:[(0,r.jsx)("h3",{className:"mb-3 text-sm font-medium text-void-800 dark:text-void-200",children:"Voice Settings"}),(0,r.jsxs)("div",{className:"mb-4 space-y-2",children:[(0,r.jsx)("div",{className:"text-xs font-medium text-void-500 dark:text-void-400",children:"Keyboard Shortcuts"}),(0,r.jsx)(d,{label:"Start recording",value:s.startRecording,onChange:e=>i(r=>({...r,startRecording:e}))}),(0,r.jsx)(d,{label:"Pause / Resume",value:s.pauseResume,onChange:e=>i(r=>({...r,pauseResume:e}))}),(0,r.jsx)(d,{label:"Submit",value:s.submit,onChange:e=>i(r=>({...r,submit:e}))}),(0,r.jsx)(d,{label:"Paste only",value:s.submitPasteOnly,onChange:e=>i(r=>({...r,submitPasteOnly:e}))}),(0,r.jsx)(d,{label:"Clear / Cancel",value:s.clear,onChange:e=>i(r=>({...r,clear:e}))})]}),(0,r.jsxs)("div",{className:"space-y-3 border-t border-void-200 pt-3 dark:border-void-600",children:[(0,r.jsx)("div",{className:"text-xs font-medium text-void-500 dark:text-void-400",children:"Behaviour"}),(0,r.jsxs)("label",{className:"flex items-center justify-between gap-2",children:[(0,r.jsx)("span",{className:"text-xs text-void-600 dark:text-void-400",children:"Auto-submit (terminal)"}),(0,r.jsx)("button",{type:"button",role:"switch","aria-checked":c,onClick:()=>l(!c),className:`relative inline-flex h-5 w-9 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors ${c?"bg-green-500":"bg-void-300 dark:bg-void-600"}`,children:(0,r.jsx)("span",{className:`pointer-events-none inline-block h-4 w-4 transform rounded-full bg-white shadow transition ${c?"translate-x-4":"translate-x-0"}`})})]}),(0,r.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,r.jsx)("span",{className:"text-xs text-void-600 dark:text-void-400",children:"Max recording (min)"}),(0,r.jsx)("input",{type:"number",min:1,max:30,value:u,onChange:e=>m(parseInt(e.target.value)||5),className:"w-16 rounded border border-void-300 bg-void-50 px-2 py-1 text-center text-xs text-void-700 outline-none dark:border-void-600 dark:bg-void-700 dark:text-void-300"})]})]})]})}function l({error:e,hasRecording:n,onRetry:o,onClear:a,onClose:s}){let i=(0,t.useRef)(null);(0,t.useEffect)(()=>{let e=e=>{i.current&&!i.current.contains(e.target)&&s()};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[s]);let d=window.isSecureContext,c=!n;return(0,r.jsxs)("div",{ref:i,className:"w-72 rounded-lg border border-red-400/30 bg-white p-3 shadow-(--shadow-overlay) dark:border-red-400/20 dark:bg-void-800",children:[(0,r.jsxs)("div",{className:"mb-2 flex items-start gap-2",children:[(0,r.jsx)("svg",{className:"mt-0.5 h-4 w-4 flex-shrink-0 text-red-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,r.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"})}),(0,r.jsxs)("div",{children:[(0,r.jsx)("div",{className:"text-xs font-medium text-red-600 dark:text-red-400",children:c?"Recording Failed":"Transcription Failed"}),(0,r.jsx)("div",{className:"mt-1 text-xs text-void-600 dark:text-void-300",children:e})]})]}),(0,r.jsx)("div",{className:"mt-2 text-xs text-void-500 dark:text-void-400",children:c&&!d?"Microphone requires HTTPS or localhost. Try accessing via localhost:3003, or add this origin to chrome://flags/#unsafely-treat-insecure-origin-as-secure.":c?"Could not access the microphone.":"Your recording is preserved. You can retry or clear and start over."}),(0,r.jsxs)("div",{className:"mt-3 flex justify-end gap-2",children:[(0,r.jsx)("button",{onClick:a,className:"rounded border border-void-300 bg-void-100 px-2 py-1 text-xs text-void-600 hover:text-void-800 dark:border-void-600 dark:bg-void-700 dark:text-void-400 dark:hover:text-void-300",children:c?"Dismiss":"Clear"}),n&&o&&(0,r.jsx)("button",{onClick:o,className:"rounded border border-neon-blue-400/40 bg-neon-blue-400/15 px-2 py-1 text-xs text-neon-blue-600 hover:bg-neon-blue-400/25 dark:text-neon-blue-400",children:"Retry"})]})]})}function u(){let e=v(),n=(0,t.useRef)(null),o=(0,t.useRef)(0),[a,d]=(0,t.useState)(!1);return((0,t.useEffect)(()=>{d(!0)},[]),null===e.currentClaimantId&&a&&("idle"!==e.voiceState&&"disabled"!==e.voiceState||e.showSettings))?(0,s.createPortal)((0,r.jsxs)("div",{className:"fixed bottom-4 right-4 z-50 animate-in fade-in slide-in-from-bottom-2 duration-200 rounded-xl border border-red-400/30 bg-white/95 px-3 py-2 shadow-(--shadow-card) backdrop-blur-sm dark:border-red-400/20 dark:bg-void-800/95",ref:n,children:[(0,r.jsx)(i,{voiceState:e.voiceState,elapsedSeconds:e.elapsedSeconds,disabled:!1,error:e.error,onRecord:e.startRecording,onPause:e.pauseRecording,onResume:e.resumeRecording,onClear:e.clearRecording,onSubmit:e.submitRecording,onRetry:e.retryTranscription,onOpenSettings:()=>{Date.now()-o.current<200||e.setShowSettings(!e.showSettings)}}),e.showSettings&&(0,r.jsx)("div",{style:{position:"fixed",bottom:60,right:16,zIndex:9999},children:(0,r.jsx)(c,{settings:e.settings.voice,onSave:r=>e.updateSettings({voice:r}),onClose:()=>{o.current=Date.now(),e.setShowSettings(!1)}})}),"error"===e.voiceState&&e.error&&(0,r.jsx)("div",{style:{position:"fixed",bottom:60,right:16,zIndex:9999},children:(0,r.jsx)(l,{error:e.error,hasRecording:e.hasRecording,onRetry:()=>e.retryTranscription(),onClear:()=>e.clearRecording(),onClose:()=>e.clearRecording()})})]}),document.body):null}e.s(["VoiceControlBar",()=>i],39269),e.s(["VoiceSettingsPopover",()=>c],9083),e.s(["VoiceErrorPopup",()=>l],49996);let m=(0,t.createContext)(null);function v(){let e=(0,t.useContext)(m);if(!e)throw Error("useVoice() must be used inside <VoiceProvider>");return e}function b({children:e}){let{settings:s,updateSettings:i}=function(){let[e,r]=(0,t.useState)(a),[n,s]=(0,t.useState)(!0);return(0,t.useEffect)(()=>{fetch("/api/settings").then(e=>e.json()).then(e=>{r({...a,...e,voice:{...o,...e?.voice}})}).catch(()=>{}).finally(()=>s(!1))},[]),{settings:e,updateSettings:(0,t.useCallback)(async e=>{try{let t=await fetch("/api/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(t.ok){let e=await t.json();return r({...a,...e,voice:{...o,...e?.voice}}),e}}catch{}return null},[]),isLoading:n}}(),d=(0,t.useRef)(new Map),c=(0,t.useRef)(null),l=(0,t.useCallback)((e,r)=>{d.current.set(e,r),c.current=e},[]),v=(0,t.useCallback)(e=>{if(d.current.delete(e),c.current===e){let e=Array.from(d.current.keys());c.current=e.length>0?e[0]:null}},[]),b=(0,t.useRef)(null),[x,h]=(0,t.useState)(null),p=(0,t.useRef)(null),g=(0,t.useRef)("auto"),[f,k]=(0,t.useState)(!1),[y,R]=(0,t.useState)(!1),j=(0,t.useCallback)(e=>{let r=p.current;if(r){if("input"===r.type&&r.element){if(!document.contains(r.element))return;let t=r.element,n=t.selectionStart??t.value.length,o=t.selectionEnd??t.value.length;t.focus(),t.setSelectionRange(n,o),document.execCommand("insertText",!1,e)}else if("terminal"===r.type&&r.terminalId){let t=d.current.get(r.terminalId);if(!t)return;let n="auto"===g.current&&s.voice.autoSubmitTerminal;t.sendInput(e),n&&setTimeout(()=>t.sendInput("\r"),300)}g.current="auto"}},[s.voice.autoSubmitTerminal]),w=(0,t.useCallback)(e=>{b.current?b.current.onTranscriptionComplete(e):j(e)},[j]),S=function({maxRecordingSeconds:e,onTranscriptionComplete:r}){let[n,o]=(0,t.useState)("idle"),[a,s]=(0,t.useState)(0),[i,d]=(0,t.useState)(null),[c,l]=(0,t.useState)(null),u=(0,t.useRef)(null),m=(0,t.useRef)([]),v=(0,t.useRef)(null),b=(0,t.useRef)(null),x=(0,t.useRef)(null),h=(0,t.useRef)(0),p=(0,t.useRef)(!1),g=(0,t.useRef)(r);(0,t.useEffect)(()=>{g.current=r},[r]);let f=(0,t.useCallback)(()=>{v.current||(v.current=setInterval(()=>{s(e=>e+1)},1e3))},[]),k=(0,t.useCallback)(()=>{v.current&&(clearInterval(v.current),v.current=null)},[]);(0,t.useEffect)(()=>{"recording"===n&&a-h.current>=e&&(u.current?.state==="recording"&&u.current.pause(),p.current=!0,k(),o("paused"))},[n,a,e,k]),(0,t.useEffect)(()=>()=>{if(k(),u.current?.state!=="inactive")try{u.current?.stop()}catch{}x.current?.getTracks().forEach(e=>e.stop())},[k]);let y=(0,t.useCallback)(()=>new Promise(e=>{let r=u.current;r&&"inactive"!==r.state?(r.ondataavailable=e=>{e.data.size>0&&m.current.push(e.data)},r.onstop=()=>{e(new Blob(m.current,{type:m.current[0]?.type||"audio/webm"}))},r.stop()):e(new Blob(m.current,{type:m.current[0]?.type||"audio/webm"}))}),[]),R=(0,t.useCallback)(async e=>{let r=new FormData;r.append("audio",e,"recording.webm");let t=await fetch("/api/transcribe",{method:"POST",body:r}),n=await t.json();if(!t.ok)throw Error(n.error||"Transcription failed");return n.text},[]),j=(0,t.useCallback)(()=>{x.current?.getTracks().forEach(e=>e.stop()),x.current=null},[]),w=(0,t.useCallback)(async()=>{if("idle"===n||"disabled"===n)try{d(null),l(null),m.current=[],b.current=null,s(0),h.current=0;let e=await navigator.mediaDevices.getUserMedia({audio:!0});x.current=e;let r=MediaRecorder.isTypeSupported("audio/ogg;codecs=opus")?"audio/ogg;codecs=opus":MediaRecorder.isTypeSupported("audio/webm;codecs=opus")?"audio/webm;codecs=opus":MediaRecorder.isTypeSupported("audio/mp4")?"audio/mp4":"",t=new MediaRecorder(e,r?{mimeType:r}:void 0);u.current=t,t.ondataavailable=e=>{e.data.size>0&&m.current.push(e.data)},t.start(1e3),o("recording"),f()}catch(r){let e=r.message;e.includes("Permission")||e.includes("NotAllowed")?d("Microphone permission denied. Please allow microphone access."):d(e||"Failed to start recording"),o("error"),j()}},[n,f,j]),S=(0,t.useCallback)(()=>{"recording"===n&&(u.current?.state==="recording"&&u.current.pause(),k(),o("paused"))},[n,k]),C=(0,t.useCallback)(()=>{"paused"===n&&(u.current?.state==="paused"&&u.current.resume(),p.current&&(h.current=a,p.current=!1),f(),o("recording"))},[n,a,f]),N=(0,t.useCallback)(()=>{if(k(),u.current?.state!=="inactive")try{u.current?.stop()}catch{}m.current=[],b.current=null,s(0),d(null),l(null),j(),o("idle")},[k,j]),E=(0,t.useCallback)(async()=>{if("recording"===n||"paused"===n){k(),o("transcribing");try{let e=await y();b.current=e,j();let r=await R(e);l(r),s(0),m.current=[],o("idle"),g.current?.(r)}catch(e){d(e.message||"Transcription failed"),o("error")}}},[n,k,y,R,j]),T=(0,t.useCallback)(async()=>{if("error"===n&&b.current){o("transcribing"),d(null);try{let e=await R(b.current);l(e),b.current=null,m.current=[],s(0),o("idle"),g.current?.(e)}catch(e){d(e.message||"Transcription failed"),o("error")}}},[n,R]);return{state:n,elapsedSeconds:a,error:i,transcribedText:c,hasRecording:null!==b.current||m.current.length>0,startRecording:w,pauseRecording:S,resumeRecording:C,clearRecording:N,submitRecording:E,retryTranscription:T}}({maxRecordingSeconds:s.voice.maxRecordingSeconds,onTranscriptionComplete:w}),C=(0,t.useCallback)(e=>{b.current&&b.current.id!==e.id&&(b.current.onRelease?.(),"idle"!==S.state&&"disabled"!==S.state&&S.clearRecording()),b.current=e,h(e.id)},[S]),N=(0,t.useCallback)(e=>{b.current?.id===e.id&&("idle"!==S.state&&"error"!==S.state&&"disabled"!==S.state&&S.clearRecording(),b.current=null,h(null))},[S]);(0,t.useEffect)(()=>{let e=e=>{let r=e.target;if(r.closest("[data-voice-target]")&&("INPUT"===r.tagName||"TEXTAREA"===r.tagName))return void R(!0);if(r.closest("[data-terminal-id]")){let e=r.closest("[data-terminal-id]").dataset.terminalId;e&&d.current.has(e)&&(c.current=e,R(!0))}},r=()=>{setTimeout(()=>{let e=document.activeElement;if(!e)return void R(!1);let r=e.closest("[data-voice-target]")&&("INPUT"===e.tagName||"TEXTAREA"===e.tagName),t=e.closest("[data-terminal-id]");r||t||R(!1)},100)};return document.addEventListener("focusin",e),document.addEventListener("focusout",r),()=>{document.removeEventListener("focusin",e),document.removeEventListener("focusout",r)}},[]);let E=(0,t.useCallback)(()=>{if(b.current)b.current.onRecordStart?.(),S.startRecording();else{let e=document.activeElement;if(e&&("INPUT"===e.tagName||"TEXTAREA"===e.tagName)&&e.closest("[data-voice-target]"))p.current={type:"input",element:e};else if(e?.closest("[data-terminal-id]")){let r=e.closest("[data-terminal-id]").dataset.terminalId||c.current;if(!(r&&d.current.has(r)))return;p.current={type:"terminal",terminalId:r}}else{if(!(c.current&&d.current.has(c.current)))return;p.current={type:"terminal",terminalId:c.current}}S.startRecording()}},[S]),T=(0,t.useCallback)(()=>{g.current="paste",S.submitRecording()},[S]),P=(0,t.useCallback)(()=>{"recording"===S.state?S.pauseRecording():"paused"===S.state&&S.resumeRecording()},[S]);!function({voiceState:e,shortcuts:r,callbacks:o,enabled:a,hasFieldFocus:s,suspended:i}){let d=(0,t.useRef)(o),c=(0,t.useRef)(e),l=(0,t.useRef)(r),u=(0,t.useRef)(s),m=(0,t.useRef)(i);(0,t.useEffect)(()=>{d.current=o,c.current=e,l.current=r,u.current=s,m.current=i}),(0,t.useEffect)(()=>{if(!a)return;let e=e=>{if(m.current)return;let r=c.current,t=l.current,o=d.current;if("idle"===r&&u.current&&n(e,t.startRecording)){e.preventDefault(),e.stopPropagation(),o.onStartRecording();return}if("recording"===r||"paused"===r){if(n(e,t.pauseResume)){e.preventDefault(),e.stopPropagation(),o.onPauseResume();return}if(n(e,t.submitPasteOnly)){e.preventDefault(),e.stopPropagation(),o.onSubmitPasteOnly();return}if(n(e,t.submit)){e.preventDefault(),e.stopPropagation(),o.onSubmit();return}if(n(e,t.clear)){e.preventDefault(),e.stopPropagation(),o.onClear();return}}};return document.addEventListener("keydown",e,!0),()=>document.removeEventListener("keydown",e,!0)},[a])}({voiceState:S.state,shortcuts:s.voice.shortcuts,callbacks:{onStartRecording:E,onPauseResume:P,onSubmit:S.submitRecording,onSubmitPasteOnly:T,onClear:S.clearRecording},enabled:!0,hasFieldFocus:!!b.current||y,suspended:f});let L={voiceState:S.state,elapsedSeconds:S.elapsedSeconds,error:S.error,hasRecording:S.hasRecording,startRecording:S.startRecording,pauseRecording:S.pauseRecording,resumeRecording:S.resumeRecording,clearRecording:S.clearRecording,submitRecording:S.submitRecording,retryTranscription:S.retryTranscription,claimVoiceControl:C,releaseVoiceControl:N,currentClaimantId:x,settings:s,updateSettings:i,registerTerminal:l,unregisterTerminal:v,submitModeRef:g,showSettings:f,setShowSettings:k,hasFieldFocus:y,setHasFieldFocus:R};return(0,r.jsxs)(m.Provider,{value:L,children:[e,(0,r.jsx)(u,{})]})}}]);
|
|
@@ -123,11 +123,13 @@ export function useVoiceRecorder({ maxRecordingSeconds, onTranscriptionComplete
|
|
|
123
123
|
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
124
124
|
streamRef.current = stream;
|
|
125
125
|
|
|
126
|
-
const mimeType = MediaRecorder.isTypeSupported('audio/
|
|
127
|
-
? 'audio/
|
|
128
|
-
: MediaRecorder.isTypeSupported('audio/
|
|
129
|
-
? 'audio/
|
|
130
|
-
: ''
|
|
126
|
+
const mimeType = MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')
|
|
127
|
+
? 'audio/ogg;codecs=opus'
|
|
128
|
+
: MediaRecorder.isTypeSupported('audio/webm;codecs=opus')
|
|
129
|
+
? 'audio/webm;codecs=opus'
|
|
130
|
+
: MediaRecorder.isTypeSupported('audio/mp4')
|
|
131
|
+
? 'audio/mp4'
|
|
132
|
+
: '';
|
|
131
133
|
|
|
132
134
|
const recorder = new MediaRecorder(stream, mimeType ? { mimeType } : undefined);
|
|
133
135
|
mediaRecorderRef.current = recorder;
|