UNPKG

rapida-react

Version:

An easy to use react client for building generative ai application using Rapida platform.

1 lines 8.35 kB
{"version":3,"sources":["../src/hooks/use-select-input-device-agent.ts","../src/hooks/use-observable-state.ts"],"sourcesContent":["/*\n * Copyright (c) 2024. Rapida\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * Author: Prashant <prashant@rapida.ai>\n *\n */\nimport * as React from \"react\";\nimport { useObservableState } from \"@/rapida/hooks/use-observable-state\";\nimport { BehaviorSubject } from \"rxjs\";\nimport {\n browserMediaDeviceObserver,\n agentInputMediaDeviceChangeObservable,\n} from \"@/rapida/hooks/observables/voice-agent\";\nimport { useMaybeVoiceAgent } from \"@/rapida/hooks/use-voice-agent\";\nimport { VoiceAgent } from \"@/rapida/agents/voice-agent\";\n\n/** @public */\ninterface UseMediaDeviceSelectProps {\n /**\n * this will call getUserMedia if the permissions are not yet given to enumerate the devices with device labels.\n * in some browsers multiple calls to getUserMedia result in multiple permission prompts.\n * It's generally advised only flip this to true, once a (preview) track has been acquired successfully with the\n * appropriate permissions.\n *\n * @see {@link MediaDeviceMenu}\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices | MDN enumerateDevices}\n */\n requestPermissions?: boolean;\n /**\n * this callback gets called if an error is thrown when failing to select a device and also if a user\n * denied permissions, eventhough the `requestPermissions` option is set to `true`.\n * Most commonly this will emit a MediaDeviceError\n */\n onError?: (e: Error) => void;\n}\n\n/**\n * The `useMediaDeviceSelect` hook is used to implement the `MediaDeviceSelect` component and\n * returns o.a. the list of devices of a given kind (audioinput or videoinput), the currently active device\n * and a function to set the the active device.\n *\n * @example\n * ```tsx\n * const { devices, activeDeviceId, setActiveMediaDevice } = useMediaDeviceSelect({kind: 'audioinput'});\n * ```\n * @public\n */\nexport function useSelectInputDeviceAgent({\n requestPermissions,\n onError,\n}: UseMediaDeviceSelectProps) {\n const voiceAgentContext = useMaybeVoiceAgent();\n // List of all devices.\n const deviceObserver = React.useMemo(\n () => browserMediaDeviceObserver(\"audioinput\", onError, requestPermissions),\n [requestPermissions, onError]\n );\n // @ts-ignore\n const devices: MediaDeviceInfo[] = useObservableState(\n deviceObserver,\n [] as MediaDeviceInfo[]\n );\n //\n const [currentDeviceId, setCurrentDeviceId] = React.useState<string>(\n voiceAgentContext?.inputMediaDevice ?? \"\"\n );\n const { className, activeDeviceObservable, setActiveMediaDevice } =\n React.useMemo(\n () => setupDeviceSelector(\"audioinput\", voiceAgentContext),\n [voiceAgentContext]\n );\n\n React.useEffect(() => {\n const listener = activeDeviceObservable.subscribe((deviceId) => {\n if (deviceId && deviceId !== currentDeviceId) {\n setCurrentDeviceId(deviceId);\n }\n });\n return () => {\n listener?.unsubscribe();\n };\n }, [activeDeviceObservable]);\n\n return {\n devices,\n className,\n activeDeviceId: currentDeviceId,\n setActiveMediaDevice,\n };\n}\n\nfunction setupDeviceSelector(_: MediaDeviceKind, agent?: VoiceAgent) {\n const activeDeviceSubject = new BehaviorSubject<string | undefined>(\n undefined\n );\n\n const activeDeviceObservable = agent\n ? agentInputMediaDeviceChangeObservable(agent)\n : activeDeviceSubject.asObservable();\n\n const setActiveMediaDevice = async (id: string) => {\n if (agent) {\n await agent.setInputMediaDevice(id);\n } else if (activeDeviceSubject.value !== id) {\n activeDeviceSubject.next(id);\n }\n };\n const className: string = \"media-device-select\";\n return {\n className,\n activeDeviceObservable,\n setActiveMediaDevice,\n };\n}\n","/*\n * Copyright (c) 2024. Rapida\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * Author: Prashant <prashant@rapida.ai>\n *\n */\nimport * as React from \"react\";\n// @ts-ignore\nimport type { Observable } from \"rxjs\";\n\n/**\n * @internal\n */\nexport function useObservableState<T>(\n observable: Observable<T> | undefined,\n startWith: T,\n resetWhenObservableChanges = true\n): T {\n const [state, setState] = React.useState<T>(startWith);\n React.useEffect(() => {\n if (resetWhenObservableChanges) {\n setState(startWith);\n }\n // observable state doesn't run in SSR\n if (typeof window === \"undefined\" || !observable) return;\n const subscription = observable.subscribe(setState);\n //\n return () => subscription.unsubscribe();\n }, [observable, resetWhenObservableChanges]);\n return state;\n}\n"],"mappings":";;;;;;;AAwBA,YAAYA,YAAW;;;ACAvB,YAAY,WAAW;AAOhB,SAAS,mBACd,YACA,WACA,6BAA6B,MAC1B;AACH,QAAM,CAAC,OAAO,QAAQ,IAAU,eAAY,SAAS;AACrD,EAAM,gBAAU,MAAM;AACpB,QAAI,4BAA4B;AAC9B,eAAS,SAAS;AAAA,IACpB;AAEA,QAAI,OAAO,WAAW,eAAe,CAAC,WAAY;AAClD,UAAM,eAAe,WAAW,UAAU,QAAQ;AAElD,WAAO,MAAM,aAAa,YAAY;AAAA,EACxC,GAAG,CAAC,YAAY,0BAA0B,CAAC;AAC3C,SAAO;AACT;;;ADtBA,SAAS,uBAAuB;AAuCzB,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AACF,GAA8B;AAC5B,QAAM,oBAAoB,mBAAmB;AAE7C,QAAM,iBAAuB;AAAA,IAC3B,MAAM,2BAA2B,cAAc,SAAS,kBAAkB;AAAA,IAC1E,CAAC,oBAAoB,OAAO;AAAA,EAC9B;AAEA,QAAM,UAA6B;AAAA,IACjC;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,CAAC,iBAAiB,kBAAkB,IAAU;AAAA,IAClD,mBAAmB,oBAAoB;AAAA,EACzC;AACA,QAAM,EAAE,WAAW,wBAAwB,qBAAqB,IACxD;AAAA,IACJ,MAAM,oBAAoB,cAAc,iBAAiB;AAAA,IACzD,CAAC,iBAAiB;AAAA,EACpB;AAEF,EAAM,iBAAU,MAAM;AACpB,UAAM,WAAW,uBAAuB,UAAU,CAAC,aAAa;AAC9D,UAAI,YAAY,aAAa,iBAAiB;AAC5C,2BAAmB,QAAQ;AAAA,MAC7B;AAAA,IACF,CAAC;AACD,WAAO,MAAM;AACX,gBAAU,YAAY;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,sBAAsB,CAAC;AAE3B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,GAAoB,OAAoB;AACnE,QAAM,sBAAsB,IAAI;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,yBAAyB,QAC3B,sCAAsC,KAAK,IAC3C,oBAAoB,aAAa;AAErC,QAAM,uBAAuB,OAAO,OAAe;AACjD,QAAI,OAAO;AACT,YAAM,MAAM,oBAAoB,EAAE;AAAA,IACpC,WAAW,oBAAoB,UAAU,IAAI;AAC3C,0BAAoB,KAAK,EAAE;AAAA,IAC7B;AAAA,EACF;AACA,QAAM,YAAoB;AAC1B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["React"]}