# Client

### Getting Started

1. **Get the Huddle01 JS SDK**

   ```
   $ npm install --save huddle01-client
   ```

   OR

   ```
   $ yarn add huddle01-client
   ```

**2. Get your API Key**: You can get your access keys in the Developer section of the Huddle01 Dashboard

**3. Importing into your application:** Import modules & instantiate Huddle01 Client. Import HuddleTypes to access the types.

```typescript
import HuddleClient, { emitter, HuddleTypes } from "huddle01-client";
```

**The infrastructure mandates a schema on the URL** of the type `https://domain.com/room?roomId=C132`

Thus, on component mount, we add:

```typescript
history.push(`?roomId=${config.roomId}`);
```

Initialise a new huddle client instance

```typescript
const huddle: HuddleClient = new HuddleClient(config);
```

{% hint style="info" %}
where `config` is of type `HuddleTypes.HuddleClientConfig` which is exported from the npm package. \
Along with this, `HuddleTypes` containing types for Producer, Consumer and Peer are also exported from the npm package.
{% endhint %}

An example `config` object can be given as

```typescript
//write this as it is -- used to check for the recorder
const isRecorderBot = localStorage.getItem("bot_password") === "huddle01";

const config: HuddleTypes.HuddleClientConfig = {
  apiKey: "<API Key>",          // API KEY (issued on the dashboard)
  roomId: "C132",               // Room ID
  peerId: "rick254",            // Peer ID (needs to be unique for every peer)
  displayName: "Rick Sanchez",  // Display Name
  window,                       // Your browser's window object
  isBot,                        // bot flag
};
```

By this step, you should be connected to the Huddle servers.

**To allow recordings**, make sure to add:

```typescript
huddle && isRecorderBot && joinRoomBtn.click();
```

{% hint style="info" %}
**where**:\
**huddle:** the huddle-client object of type `HuddleClient`\
**isRecorderBot:** the boolean that checks if the user is a recorder bot or not\
**joinRoomBtn:** the button
{% endhint %}

#### Setting up event listeners

The emitter that we imported in the 1st step is used to emit events by Huddle about your application. Please refer to the demo app for application references

**The various types of events are:**

{% tabs %}
{% tab title="roomState" %}
**Trigger:** on room status changes\
**Return value:** room status of the type `string`

```javascript
emitter.on("roomState", (state: string) => {
    //do whatever (ideally switch-case between all state types)
    //for example
    switch (state) {
        case "connected":
          //code for roomState == "connected"
          break;
        case "failed":
          //code for roomState == "failed"
          break;
        case "disconnected":
          //code for roomState == "disconnected"
          break;
        default:
          setRoomState(state);
        
          break;
      }
      setRoomState(state);
});
```

{% hint style="info" %}
Please refer to the demo app for application references
{% endhint %}

**Different state types:**

| connected                          | failed                            | disconnected                            |
| ---------------------------------- | --------------------------------- | --------------------------------------- |
| successfully connected to the room | failure in connection to the room | successfully disconnected from the room |
| {% endtab %}                       |                                   |                                         |

{% tab title="error" %}
**Trigger:** an error event on client/server side\
**Return value:** the error object

```javascript
emitter.on("error", (error: any) => {
    //code for error handling
    // example : alert(error)
});
```

{% hint style="info" %}
Please refer to the demo app for application references
{% endhint %}
{% endtab %}

{% tab title="addPeer" %}
**Trigger:** new peer joins the room\
**Return value:** an entire peer object with all the details about the peer of the type `HuddleTypes.IPeer`

```javascript
emitter.on("addPeer", (peer: HuddleTypes.IPeer) => {
    //do whatever
});
```

{% hint style="info" %}
Please refer to the demo app for application references
{% endhint %}
{% endtab %}

{% tab title="addProducer" %}
**Trigger:** you have a new producer producing to the Huddle servers\
**Return value:** an producer object with details like your production media track (eg. webcam/mic/screenshare) of the type `HuddleTypes.IProducer`.

```javascript
emitter.on("addProducer", (producer: HuddleTypes.IProducer) => {
    //do whatever (ideally switch-case between all state types)
});
```

{% hint style="info" %}
Please refer to the demo app for application references
{% endhint %}

**Different state types:**

`producer.type:`

| webcam                   | mic                   | screenshare                   |
| ------------------------ | --------------------- | ----------------------------- |
| a webcam stream producer | a mic stream producer | a screenshare stream producer |
| {% endtab %}             |                       |                               |

{% tab title="addConsumer" %}
**Trigger:** you have a new consumer consuming from the Huddle servers\
**Return value:** a consumer object with details like your consumption media track (eg. webcam/mic/screenshare) of the type `HuddleTypes.IConsumer`

```javascript
emitter.on("addConsumer", (consumer: HuddleTypes.IConsumer) => {
    //do whatever (ideally switch-case between all state types)
});
```

{% hint style="info" %}
Please refer to the demo app for application references
{% endhint %}

**Different state types:**

`consumer.type:`

| webcam                   | mic                   | screenshare                   |
| ------------------------ | --------------------- | ----------------------------- |
| a webcam stream consumer | a mic stream consumer | a screenshare stream consumer |
| {% endtab %}             |                       |                               |

{% tab title="removePeer" %}
**Trigger:** one of the existing peers disconnects from the room\
**Return value:** an entire peer object with all the details about the peer of the type `HuddleTypes.IPeer`(same as the object received on the "add" event)

```javascript
emitter.on("removePeer", (peer: HuddleTypes.IPeer) => {
    //do whatever
});
```

{% hint style="info" %}
Please refer to the demo app for application references
{% endhint %}
{% endtab %}

{% tab title="removeProducer" %}
**Trigger:** you have closed the production of your existing producer to the Huddle servers\
**Return value:** a producer object with details like your production media track (eg. webcam/mic/screenshare) peer of the type `HuddleTypes.IProducer` (same as the object received on the "add" event)

```javascript
emitter.on("removeProducer", (producer: HuddleTypes.IProducer) => {
    //do whatever (ideally switch-case between all state types)
});
```

{% hint style="info" %}
Please refer to the demo app for application references
{% endhint %}

**Different state types:**

`producer.type:`

| webcam                   | mic                   | screenshare                   |
| ------------------------ | --------------------- | ----------------------------- |
| a webcam stream producer | a mic stream producer | a screenshare stream producer |
| {% endtab %}             |                       |                               |

{% tab title="removeConsumer" %}
**Trigger:** you have closed the production of your existing producer to the Huddle servers\
**Return value:** a consumer object with details like your consumption media track (eg. webcam/mic/screenshare) peer of the type `HuddleTypes.IConsumer` (same as the object received on the "add" event)

```typescript
emitter.on("removeConsumer", (consumer: HuddleTypes.IConsumer) => {
    //do whatever (ideally switch-case between all state types)
});
```

{% hint style="info" %}
Please refer to the demo app for application references
{% endhint %}

**Different state types:**

`consumer.type:`

| webcam                   | mic                   | screenshare                   |
| ------------------------ | --------------------- | ----------------------------- |
| a webcam stream consumer | a mic stream consumer | a screenshare stream consumer |
| {% endtab %}             |                       |                               |
| {% endtabs %}            |                       |                               |

{% hint style="info" %}
All the data/states received by events need to be maintained by you in your app. Can be achieved using React states/redux or any similar implementations.

Please refer to the demo app where we use local React states to handle these data.
{% endhint %}

#### Methods Available:

* **huddle.join()**
* **huddle.close()**

{% tabs %}
{% tab title="joinRoom()" %}

```javascript
const joinRoom = async () => {
    if (!huddle) return;
    try {
      setupEventListeners();
      await huddle.join();
    } catch (error) {
      alert(error);
    }
  };
```

{% endtab %}

{% tab title="leaveRoom()" %}

```javascript
const leaveRoom = async () => {
  if (!huddle) return;
  try {
    await huddle.close();
    setRoomState(false);
  } catch (error) {
    alert(error);
  }
};
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
`close()` can only be called after `join()` is successful
{% endhint %}

* **huddle.enableWebcam()**
* **huddle.enableMic()**
* **huddle.enableShare()**

{% tabs %}
{% tab title="enableWebcam()" %}

```javascript
  const enableWebcam = async () => {
    if (!huddle) return;
    try {
      await huddle.enableWebcam();
      setWebcamState(true);
    } catch (error) {
      alert(error);
    }
  };
```

{% endtab %}

{% tab title="enableMic()" %}

```typescript
 const enableMic = async () => {
    if (!huddle) return;
    try {
      huddle.enableMic();
      setMicState(true);
    } catch (error: any) {
      setMicState(false);
      alert(error);
    }
  };
```

{% endtab %}

{% tab title="enableShare()" %}

```typescript
 const startScreenshare = async () => {
    if (!huddle) return;
    try {
      await huddle.enableShare();
      setScreenshareState(true);
    } catch (error: any) {
      alert(error);
      setScreenshareState(false);
    }
  };
```

{% endtab %}
{% endtabs %}

* **huddle.disableWebcam()**
* **huddle.disableShare()**
* **huddle.disableMic()**

{% tabs %}
{% tab title="disableWebcam()" %}

```javascript
  const disableWebcam = async () => {
    if (!huddle) return;
    try {
      await huddle.disableWebcam();
      setWebcamState(false);
    } catch (error) {
      alert(error);
    }
  };
```

{% endtab %}

{% tab title="disableShare()" %}

```typescript
  const stopScreenshare = async () => {
    if (!huddle) return;
    try {
      await huddle.disableShare();
      setScreenshareState(false);
    } catch (error: any) {
      alert(error);
    }
  };
```

{% endtab %}

{% tab title="disableMic()" %}

```typescript
const disableMic = async () => {
    if (!huddle) return;
    try {
      huddle.disableMic();
      setMicState(false);
    } catch (error: any) {
      alert(error);
      setMicState(true);
    }
  };
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
`enable()` functions need to be called and have returned success first before calling any of the `disable()`counterparts
{% endhint %}

* **huddle.startRecording()**
* **huddle.stopRecording()**

{% tabs %}
{% tab title="startRecording()" %}

```typescript
  const startRecording = async () => {
    if (!huddle) return;
    try {
      const status: boolean = await huddle.startRecording();
      if (status) console.log("recording successfully initiated");
    } catch (error: any) {
      console.error(error);
    }
  };
```

{% endtab %}

{% tab title="stopRecording()" %}

```javascript
const stopRecorder = async () => {
    if (!huddle) return;
    try {
      const status: boolean = await huddle.stopRecording();
      if (status) console.log("recording successfully stopped");
    } catch (error: any) {
      console.error(error);
    }
  };
```

{% endtab %}
{% endtabs %}
