
# react-native-twilio-video

## Getting started

`$ npm install react-native-twilio-video --save`
#OR
`$ yarn add react-native-twilio-video`

###  Installation

#### iOS
#### Cocoapod
Run ``` pod install``` to install Twilio Video and PromiseKit Dependencies for this package
### Permission
To enable camera usage and microphone usage you will need to add the following entries to your Info.plist file:
```
<key>NSCameraUsageDescription</key>
<string>Your message to user when the camera is accessed for the first time</string>
<key>NSMicrophoneUsageDescription</key>
<string>Your message to user when the microphone is accessed for the first tim
```
#### Android

Insert the following lines inside the dependencies block in `AndroidManifest.xml`:
  	```
      <uses-permission android:name="android.permission.CAMERA" />
      <uses-permission android:name="android.permission.RECORD_AUDIO"/>
  	```

## Usage
```javascript
import React from 'react'
import { AppState, View, Platform, AppStateStatus } from 'react-native'

import { TwiRoomView, TwiPreview, TwiRemoteView, RemoteParticipant } from 'react-native-twilio-video'

import { TWIVideoViewStyles } from './styles';
import { ControlButton } from './TWIVideo.ControllButton';

interface TWIVideoViewState {
    isConnected: boolean,
    participants: Array<RemoteParticipant>,
    shareVideo: boolean,
    shareAudio: boolean,
    token: string,
    error: string,
    status: "INIT" | "LOADING" | "DONE"
}

class TWIVideoView extends React.PureComponent<any, TWIVideoViewState> {

    activeShareVideoState: boolean = true
    roomView!: TwiRoomView

    refRoomView = (r: TwiRoomView) => this.roomView = r

    constructor(props: any) {
        super(props);
        this.state = {
            isConnected: false,
            participants: [],
            shareVideo: true,
            shareAudio: true,
            token: "",
            error: "",
            status: "INIT"
        }

    }

    componentDidMount() {
        AppState.addEventListener("change", this.onAppSateChange)
        this.setState({ status: "LOADING" })
        fetch("https://api-dev.spltty.com/api/user/twilio_token", {
            method: "post",
            headers: {
                "Content-Type": "application/json",
                "Accept": "application/json"
            },
            body: JSON.stringify({
                identity: ((Math.random() * 10000) + new Date().getTime()).toFixed(0) + Platform.OS,
                platform: Platform.OS
            })
        }).then(response => {
            return response.json();
        }).then(({ data }) => {
            const { token } = data
            this.setState({ token })
        }).catch((error) => {
            this.setState({ error })
        }).then(() => {
            this.setState({ status: "DONE" })
        })
    }

    componentWillUnmount() {
        AppState.removeEventListener("change", this.onAppSateChange)
    }

    // MARK: METHOD
    connect = () => {
        const { token } = this.state
        this.roomView.nativeConnectWithOptions(
            token,
            "test"
        )
    }

    disConnect = () => {
        this.roomView.nativeDisconnect()
    }

    toggleShareVideo = () => {
        this.setState({ shareVideo: !this.state.shareVideo })
    }

    toggleShareAudio = () => {
        const { shareAudio } = this.state
        this.setState({ shareAudio: !shareAudio })
    }

    toggleCamera = () => {
        this.roomView.nativeFlipCamera()
    }

    // MARK: Listen event
    onAppSateChange = (status: AppStateStatus) => {
        switch (status) {
            case "active":
                this.setState({ shareVideo: this.activeShareVideoState })
                break;
            case "background":
                this.activeShareVideoState = this.state.shareVideo
                this.toggleShareVideo()
        }
    }

    onDidConnect = (participants: Array<RemoteParticipant>) => {

        this.setState({ participants, isConnected: true })
    }

    onDisConnected = () => {
        this.setState({ isConnected: false, participants: [] })
    }

    onParticipantConnected = (participants: Array<RemoteParticipant>) => {
        this.setState({ participants })
    }
    onParticipantDisConnected = (participants: Array<RemoteParticipant>) => {
        this.setState({ participants })
    }

    // MARK: RENDER

    renderControls = () => {
        const { isConnected, shareAudio, shareVideo, status } = this.state
        const isLoading = status === "LOADING"

        return (
            <View style={TWIVideoViewStyles.controls}>
                <ControlButton
                    size={50}
                    isLoading={isLoading}
                    onPress={this.toggleShareAudio}
                    color="orange"
                    iconStyle={{ width: 30, height: 30 }}
                    icon={shareAudio ? "https://image.flaticon.com/icons/png/512/41/41758.png" : "https://icon-library.net/images/white-microphone-icon/white-microphone-icon-6.jpg"}
                />
                <ControlButton
                    size={50}
                    isLoading={isLoading}
                    color={isConnected ? "red" : "green"}
                    onPress={isConnected ? this.disConnect : this.connect}
                    iconStyle={{ width: 30, height: 30 }}
                    icon="https://iconsplace.com/wp-content/uploads/_icons/ffffff/256/png/phone-icon-18-256.png"
                />
                <ControlButton
                    size={50}
                    isLoading={isLoading}
                    onPress={this.toggleShareVideo}
                    color="green"
                    iconStyle={{ width: 30, height: 30 }}
                    icon={shareVideo ? "https://png.pngtree.com/svg/20150629/slash_1368083.png" : "https://www.nycc.edu/themes/nycc/images/icon-play-video-white.png"}
                />
            </View>
        )
    }

    render() {
        const { shareVideo, shareAudio, participants } = this.state
        return (
            <View style={TWIVideoViewStyles.container} >

                <TwiRoomView
                    ref={this.refRoomView}
                    style={TWIVideoViewStyles.room}
                    onDidConnect={this.onDidConnect}
                    onParticipantConnected={this.onParticipantConnected}
                    onParticipantDisConnected={this.onParticipantDisConnected}
                    shareVideo={shareVideo}
                    shareAudio={shareAudio}
                    onDisConnected={this.onDisConnected}
                >

                    {participants.map(par => <TwiRemoteView
                        key={par.identity}
                        participantIdentity={par.identity}
                        style={{ flex: 1 }}
                    />)}
                    <TwiPreview
                        style={TWIVideoViewStyles.preview}
                    />
                    <ControlButton
                        containerStyle={{ position: "absolute", top: 80, left: 20, zIndex: 2 }}
                        size={50}
                        onPress={this.toggleCamera}
                        color="#BBBBBB"
                        iconStyle={{ width: 30, height: 30 }}
                        icon="https://iconsplace.com/wp-content/uploads/_icons/ffffff/256/png/rotate-camera-icon-18-256.png"
                    />

                    {this.renderControls()}
                </TwiRoomView>

            </View>
        )
    }
}

export default TWIVideoView

```
### TwiRoomView Props

* [Inherited `View` props...](https://github.com/facebook/react-native-website/blob/master/docs/view.md#props)

- [`style`](#style)
- [`shareVideo`](#shareVideo)
- [`shareAudio`](#shareAudio)
- [`onDidConnect`](#onDidConnect)
- [`onFailedToConnect`](#onFailedToConnect)
- [`onDisConnected`](#onDisConnected)
- [`onReConnecting`](#onReConnecting)
- [`onFailedReConnect`](#onFailedReConnect)
- [`onDidReConnect`](#onDidReConnect)
- [`onParticipantConnected`](#onParticipantConnected)
- [`onParticipantDisConnected`](#onParticipantDisConnected)

---

### `style`

Used to style and layout the `TwiRoomView`. See `StyleSheet.js` and `ViewStylePropTypes.js` for more info.

| Type       | Required |
| ---------- | -------- |
| View.style | No       |

---

### `shareVideo`

Share video for other remote pacitipant or not  default is `true`

| Type | Required |
| ---- | -------- |
| bool | No       |

---

### `shareAudio`

Share audio for other remote pacitipant or not  default is `true`

| Type   | Required |
| ------ | -------- |
| bool | No       |

---

### `onDidConnect`

`Event` when connect to room successfully

| Type               | Required |
| ------------------ | -------- |
| [(participants: Array<RemoteParticipant>) => void)](colors.md) | No       |

---

### `onFailedToConnect`

`Event` when failed to connect to room

| Type   | Required |
| ------ | -------- |
| () => void | No       |

---

### `onDisConnected`

`Event` when disconnected from room

| Type     | Required |
| -------- | -------- |
| () => void | No       |

---

### `onReConnecting`

`Event` when reconnecting to a room

| Type     | Required |
| -------- | -------- |
| () => void | No       |

---

### `onFailedReConnect`

`Event` when failed to reconnect to a room

| Type     | Required |
| -------- | -------- |
| () => void  | No       |

---

### `onDidReConnect`

`Event` when reconnected to a room

| Type   | Required |
| ------ | -------- |
| () => void | No       |

---

### `onParticipantConnected`

`Event` when has any one connect to subcribing room

| Type               | Required |
| ------------------ | -------- |
| (participant: Array<RemoteParticipant>) => void | No       |

---

### `onParticipantDisConnected`

`Event` when has any one disconnect from subcribing room.

| Type   | Required |
| ------ | -------- |
| (participant: Array<RemoteParticipant>) => void | No       |

---
### TwiRemoteView Props

* [Inherited `View` props...](https://github.com/facebook/react-native-website/blob/master/docs/view.md#props)

- [`style`](#style)
- [`participantIdentity`](#participantIdentity)
- [`onPublishedVideoTrack`](#onPublishedVideoTrack)
- [`onUnPublishedVideoTrack`](#onUnPublishedVideoTrack)
- [`onPublishedAudioTrack`](#onPublishedAudioTrack)
- [`onUnPublishedAudioTrack`](#onUnPublishedAudioTrack)
- [`onSubcribeVideoTrack`](#onSubcribeVideoTrack)
- [`onUnSubcribeVideoTrack`](#onUnSubcribeVideoTrack)
- [`onSubcribeAudioTrack`](#onSubcribeAudioTrack)
- [`onUnSubcribeAudioTrack`](#onUnSubcribeAudioTrack)
- [`onEnabledVideoTrack`](#onEnabledVideoTrack)
- [`onDisabledVideoTrack`](#onDisabledVideoTrack)
- [`onEnabledAudioTrack`](#onEnabledAudioTrack)
- [`onDisabledAudioTrack`](#onDisabledAudioTrack)
- [`onFailedToSubscribeVideoTrack`](#onFailedToSubscribeVideoTrack)
- [`onEnabledVideoTrack`](#onFailedToSubscribeAudioTrack)
---

### `style`

Used to style and layout the `TwiRemoteView`. See `StyleSheet.js` and `ViewStylePropTypes.js` for more info.

| Type       | Required |
| ---------- | -------- |
| View.style | No       |

---

### `participantIdentity`

Pacitipant's identity

| Type | Required |
| ---- | -------- |
| string | yes       |

---

### `onPublishedVideoTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onUnPublishedVideoTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onPublishedAudioTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onUnPublishedAudioTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onSubcribeVideoTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onUnSubcribeVideoTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onSubcribeAudioTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onUnSubcribeAudioTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onEnabledVideoTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onDisabledVideoTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onEnabledAudioTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onDisabledAudioTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onFailedToSubscribeVideoTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---
### `onFailedToSubscribeAudioTrack`

Like this name

| Type   | Required |
| ------ | -------- |
| () => {} | No       |

---

## Maintainers

- [Tran Ty](https://github.com/tytran9597) - [Callstack](https://callstack.com/)

## License
The library is released under the MIT licence. For more information see `LICENSE`.
  