# Chat Client

## Installation

`npm install @one-view/chat-client`

## Usage

### Client Initialization

Get the `aws-exports.js` file from your fellow developer and put it somewhere in your project, preferably in the root. Import the `ChatClient` class and create an instance. Pass the `username` and `awsconfig` as paramater.

```javascript
import ChatClient from '@one-view/chat-client';
import awsconfig from './aws-exports';

const username = 'your-username';
const client = new ChatClient({
    username,
    awsconfig,
});
```

### Listen to Events

Listen to chat events using `on` method. See Events for the list of available events.

```javascript
const messagesInRoom = {};

client.on('messageLoad', ({ roomId, messages }) => {
    messagesInRoom[roomId] = messages;
});

client.on('messageReceive', ({ roomId, message }) => {
    messagesInRoom[roomId].push(message);
});
```

### Join Room

Join a room to load messages. `messageLoad` event will be emitted after succesfully joined the room, otherwise `joinRoomError` will be emitted.

```javascript
// The value below will be provided by backend
const roomData = {
    roomId: 'some-room-id',
    token: 'your-jwt-token',
    subkey: 'your-subscription-key',
};

client.joinRoom(roomData);
```

### Send Message

```javascript
client.sendText(roomId, 'Hello World!');
```

### Leave Room

```javascript
client.leaveRoom(roomId);
```

## Events

Below is the list of events available to listen to using `on` method. When an event is emitted, it will call the callback function with `payload` object as parameter.

| Event Name            | Payload                                                        | Notes |
| :-------------------- | :------------------------------------------------------------- | :---- |
| `messageLoad`         | `{ roomId: string, data: Message[] }`                          |       |
| `messageLoadError`    | `{ roomId: string, data: Error[] }`                            |       |
| `messageReceive`      | `{ roomId: string, data: Message }`                            |       |
| `messageReceiveError` | `{ roomId: string, data: Error[] }`                            |       |
| `messageSend`         | `{ roomId: string, data: Message }`                            |       |
| `messageSendError`    | `{ roomId: string, data: Error[] }`                            |       |
| `roomInactive`        | `{ roomId: string }`                                           |       |
| `joinRoomError`       | `{ roomId: string, data: Error[] }`                            |       |
| `userTypingStart`     | `{ roomId: string, data: username (string) }`                  |       |
| `userTypingStart`     | `{ roomId: string, data: username (string) }`                  |       |
| `userOnline`          | `{ roomId: string, data: username (string) }`                  |       |
| `userOffline`         | `{ roomId: string, data: username (string) }`                  |       |
| `assigned`            | `{ roomId: string }`                                           |       |
| `subscriptionError`   | `{ roomId: string, data: { error: Error[], roomData: Room } }` |       |
| `pollingStart`        | `{ roomId: string }`                                           |       |
| `pollingError`        | `{ roomId: string, data: { error: Error[], roomData: Room } }` |       |

example:

```javascript
client.on('messageLoad', ({ roomId, data }) => {
    // Do something with received data
});
```

## Identity ID

```javascript
const client = new ChatClient({
    username: 'pandacare',
    identityId: 'some-unique-id',
    awsconfig,
});

client.on('messageReceive', ({ roomId, data: message }) => {
    if (message.identity_id !== client.identityId) {
        // message is from other user
    }
});
```

## Heartbeat

ChatClient will send `heartbeat` event every certain interval (default to `2000`ms) to inform the server that user is online. You can pass `heartbeatInterval` in ChatClient config to change the interval value.

```
new ChatClient({
    heartbeatInterval: 3000 // send heartbeat every 3 seconds
})
```

## User Typing Event

To let other users know that user is typing, the chat UI must send event via `typingStart` and `typingEnd` method.

React example:

```javascript
const roomId = '123'
const client = new ChatClient(...)

const App = () => {
  const [isTyping, setIsTyping] = React.useState(false)
  const [typingTimeout, setTypingTimeout] = React.useState()

  const inputHandler = () => {
    window.clearTimeout(typingTimeout)

    if (!isTyping) {
      setIsTyping(true)
      client.typingStart(roomId)
    }

    const timeout = window.setTimeout(() => {
      setIsTyping(false)
      client.typingEnd(roomId)
    }, 1000) // assume typing stop after 1 second of no input

    setTypingTimeout(timeout)
  }

  return <textarea onKeyDown={inputHandler}/>
}
```
