import { Meta } from '@storybook/blocks';

<Meta title="SDK Hooks/useVoiceFocus" />

# useVoiceFocus

The `useVoiceFocus` hook returns a function transforming a normal audio device to an Amazon Voice Focus device, and whether Amazon Voice Focus is supported.
Amazon Voice Focus related logs can be found in the browser developer tools when Amazon Voice Focus is enabled.

## Return Value

```typescript
{
  // Whether Amazon Voice Focus is supported. The default value is undefined, then changes to true or false.
  isVoiceFocusSupported: boolean | undefined;

  // A function to transform an audio input device to an Amazon Voice Focus device.
  addVoiceFocus: (device: Device) =>
    Promise<Device | VoiceFocusTransformDevice>;
}
```

## Importing

```javascript
import { useVoiceFocus } from 'amazon-chime-sdk-component-library-react';
```

## Usage

The hook depends on the `VoiceFocusProvider`. You can use it with `MeetingProvider`.
`joinInfo` here is the response of [CreateMeeting](https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_CreateMeeting.html)
from [Amazon Chime SDK Meetings endpoint](https://docs.aws.amazon.com/chime-sdk/latest/dg/meeting-namespace-migration.html).
`joinInfo` is needed here so as to decide whether download Voice Focus or Echo Reduction model according to `CreatingMeetingResponse`.

```jsx
import React from 'react';
import { VoiceFocusTransformDevice } from 'amazon-chime-sdk-js';
import {
  MeetingProvider,
  VoiceFocusProvider,
  useMeetingManager,
  useVoiceFocus,
  useAudioInputs,
} from 'amazon-chime-sdk-component-library-react';

const joinInfo = { Meeting: {} }

function voiceFocusName(name: string): VoiceFocusModelName {
  if (name && ['default', 'ns_es'].includes(name)) {
    return name as VoiceFocusModelName;
  }
  return 'default';
}

function getVoiceFocusSpecName(): VoiceFocusModelName {
  if (
    joinInfo &&
    joinInfo.Meeting?.MeetingFeatures?.Audio?.EchoReduction === 'AVAILABLE'
  ) {
    return voiceFocusName('ns_es');
  }
  return voiceFocusName('default');
}

const vfConfigValue = {
  spec: {name: getVoiceFocusSpecName()},
  createMeetingResponse: joinInfo,
};

const App = () => {
  return (
  <VoiceFocusProvider {...vfConfigValue}>
    <MeetingProvider>
      <MyChild />
    </MeetingProvider>
  </VoiceFocusProvider>
);

const MyChild = () => {
  const meetingManager = useMeetingManager();
  const { selectedDevice } = useAudioInputs();
  const [isVoiceFocusOn, setIsVoiceFocusOn] = useState(false);
  const [isVoiceFocusEnabled, setIsVoiceFocusEnabled] = useState(false);
  const { isVoiceFocusSupported, addVoiceFocus } = useVoiceFocus();

  useEffect(() => {
    if (selectedDevice instanceof VoiceFocusTransformDevice) {
      setIsVoiceFocusEnabled(true);
    } else {
      setIsVoiceFocusEnabled(false);
    }
  }, [selectedDevice]);

  useEffect(() => {
    async function toggleVoiceFocus() {
      try {
        let current = selectedDevice;
        if (isVoiceFocusOn) {
          if (typeof selectedDevice === 'string') {
            current = await addVoiceFocus(selectedDevice);
          }
        } else {
          if (selectedDevice instanceof VoiceFocusTransformDevice) {
            current = selectedDevice.getInnerDevice();
          }
        }
        await meetingManager.startAudioInputDevice(current);
      } catch (error) {
        // Handle device selection failure here
        console.error('Failed to toggle Voice Focus');
      }
    }

    toggleVoiceFocus();
  }, [isVoiceFocusOn]);

  const onClick = () => {
    setIsVoiceFocusOn((current) => !current);
  };

  return (
    <div>
      {isVoiceFocusSupported && (
        <button onClick={onClick}>
          {isVoiceFocusEnabled
            ? 'Disable Amazon Voice Focus'
            : 'Enable Amazon Voice Focus'}
        </button>
      )}
    </div>
  );
};
```

### Dependencies

- `MeetingProvider`
- `VoiceFocusProvider`
