Skip to content

Commit 6366eec

Browse files
committed
Disable mic enumeration until audio input is enabled, wire voice button to refresh devices.
1 parent c85a9ac commit 6366eec

File tree

4 files changed

+44
-179
lines changed

4 files changed

+44
-179
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ node_modules/
1515

1616
# OS files
1717
.DS_Store
18-
Thumbs.db
18+
Thumbs.db
19+
20+
.npm-cache

package-lock.json

Lines changed: 23 additions & 167 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"author": "Layercode",
33
"license": "MIT",
44
"name": "@layercode/react-sdk",
5-
"version": "2.8.2",
5+
"version": "2.8.3",
66
"description": "Layercode React SDK for integrating with React applications",
77
"type": "module",
88
"main": "./dist/index.js",
@@ -39,7 +39,7 @@
3939
"access": "public"
4040
},
4141
"dependencies": {
42-
"@layercode/js-sdk": "2.8.2"
42+
"@layercode/js-sdk": "^2.8.4"
4343
},
4444
"devDependencies": {
4545
"@rollup/plugin-commonjs": "^25.0.8",

src/index.tsx

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ interface UseLayercodeAgentOptions {
2424
onAudioInputChanged?: (audioInput: boolean) => void;
2525
onAudioOutputChanged?: (audioOutput: boolean) => void;
2626
enableAmplitudeMonitoring?: boolean;
27+
/**
28+
* When false, skips microphone device enumeration/watchers until audio input is enabled.
29+
* This prevents getUserMedia from being invoked before the user opts into voice mode.
30+
*/
31+
autoLoadInputDevices?: boolean;
2732
}
2833

2934
const normalizeDeviceId = (deviceId?: string | null): string | null => {
@@ -63,6 +68,7 @@ const useLayercodeAgent = (
6368
} = options;
6469
const websocketUrlOverride = options['_websocketUrl'];
6570
const enableAmplitudeMonitoring = options.enableAmplitudeMonitoring ?? true;
71+
const autoLoadInputDevices = options.autoLoadInputDevices ?? true;
6672

6773
const [status, setStatus] = useState('initializing');
6874
const [userAudioAmplitude, setUserAudioAmplitude] = useState(0);
@@ -83,6 +89,7 @@ const useLayercodeAgent = (
8389
const mountedRef = useRef(true);
8490
// Reference to the LayercodeClient instance
8591
const clientRef = useRef<LayercodeClient | null>(null);
92+
const shouldManageInputDevices = autoLoadInputDevices || audioInput;
8693

8794
const refreshInputDevices = useCallback(async () => {
8895
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
@@ -148,17 +155,17 @@ const useLayercodeAgent = (
148155
}, [preferredInputDeviceId]);
149156

150157
useEffect(() => {
151-
if (typeof window === 'undefined') {
158+
if (typeof window === 'undefined' || !shouldManageInputDevices) {
152159
return;
153160
}
154161

155162
refreshInputDevices().catch((error) => {
156163
console.warn('Layercode: failed to load microphone devices', error);
157164
});
158-
}, [refreshInputDevices]);
165+
}, [refreshInputDevices, shouldManageInputDevices]);
159166

160167
useEffect(() => {
161-
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
168+
if (!shouldManageInputDevices || typeof window === 'undefined' || typeof navigator === 'undefined') {
162169
return;
163170
}
164171

@@ -176,11 +183,11 @@ const useLayercodeAgent = (
176183
return () => {
177184
unsubscribe?.();
178185
};
179-
}, []);
186+
}, [shouldManageInputDevices]);
180187

181188
const createClient = useCallback(
182189
(initialConversationId: string | null) => {
183-
console.log('Creating LayercodeClient instance');
190+
console.log('Creating LayercodeClient instance with audioInput:', audioInput, 'audioOutput:', audioOutput);
184191
const client = new LayercodeClient({
185192
agentId,
186193
conversationId: initialConversationId,
@@ -310,19 +317,19 @@ const useLayercodeAgent = (
310317
}, []);
311318

312319
const setAudioInput = useCallback(
313-
(state: React.SetStateAction<boolean>) => {
320+
async (state: React.SetStateAction<boolean>) => {
314321
_setAudioInput(state);
315322
const next = typeof state === 'function' ? (state as (prev: boolean) => boolean)(audioInput) : state;
316-
clientRef.current?.setAudioInput(next);
323+
await clientRef.current?.setAudioInput(next);
317324
},
318325
[_setAudioInput, clientRef, audioInput]
319326
);
320327

321328
const setAudioOutput = useCallback(
322-
(state: React.SetStateAction<boolean>) => {
329+
async (state: React.SetStateAction<boolean>) => {
323330
_setAudioOutput(state);
324331
const next = typeof state === 'function' ? (state as (prev: boolean) => boolean)(audioOutput) : state;
325-
clientRef.current?.setAudioOutput(next);
332+
await clientRef.current?.setAudioOutput(next);
326333
},
327334
[_setAudioOutput, clientRef, audioOutput]
328335
);

0 commit comments

Comments
 (0)