Skip to content

Commit 6327581

Browse files
authored
[Expo Compatibility] - Add support for Expo Config Plugin (#691)
* feat(config-plugin): wip on implementing expo config plugin * fix(config-plugin): add missing peerDependency on expo-build-properties * feat(config-plugin): improve typings for plugin * feat(config-plugin): rename entrypoint to index, add 'build' folder * docs(config-plugin): add docs on how to use with Expo in README.md * docs(config-plugin): add missing section about installing expo-build-properties * chore: temporary disable deploymentTarget setup * chore: update build folder
1 parent 9f74617 commit 6327581

17 files changed

+9532
-83
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ node_modules
99
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
1010

1111
## Build generated
12-
build/
1312
DerivedData/
1413
.idea
1514
## Various settings

README.md

Lines changed: 118 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Twilio Video (WebRTC) for React Native
44

55
Platforms:
6+
67
- iOS
78
- Android
89

@@ -27,6 +28,47 @@ yarn add https://github.com/blackuy/react-native-twilio-video-webrtc
2728
npm install https://github.com/blackuy/react-native-twilio-video-webrtc --save
2829
```
2930

31+
### Usage with Expo
32+
33+
To use this library with [`Expo`](https://expo.dev) we recommend using our config plugin that you can configure like the following example:
34+
35+
```json
36+
{
37+
"name": "my app",
38+
"plugins": [
39+
[
40+
"react-native-twilio-video-webrtc",
41+
{
42+
"cameraPermission": "Allow $(PRODUCT_NAME) to access your camera",
43+
"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone"
44+
}
45+
]
46+
]
47+
}
48+
```
49+
50+
Also you will need to install `expo-build-properties` package:
51+
52+
#### NPM
53+
54+
```bash
55+
npm i expo-build-properties
56+
```
57+
58+
#### Yarn
59+
60+
```bash
61+
yarn add expo-build-properties
62+
```
63+
64+
#### Expo Config Plugin Props
65+
66+
The plugin support the following properties:
67+
68+
- `cameraPermission`: Specifies the text to show when requesting the camera permission to the user.
69+
70+
- `microphonePermission`: Specifies the text to show when requesting the microphone permission to the user.
71+
3072
### iOS
3173

3274
#### Option A: Install with CocoaPods (recommended)
@@ -135,7 +177,7 @@ android {
135177
}
136178
```
137179

138-
Now you're ready to load the package in `MainApplication.java`. In the imports section, add this:
180+
Now you're ready to load the package in `MainApplication.java`. In the imports section, add this:
139181

140182
```java
141183
import com.twiliorn.library.TwilioPackage;
@@ -165,7 +207,7 @@ For most applications, you'll want to add camera and audio permissions to your `
165207
<uses-feature android:name="android.hardware.microphone" android:required="false" />
166208
```
167209

168-
Newer versions of Android have a different permissions model. You will need to use the `PermissionsAndroid`
210+
Newer versions of Android have a different permissions model. You will need to use the `PermissionsAndroid`
169211
class in `react-native` in order to request the `CAMERA` and `RECORD_AUDIO` permissions.
170212

171213
### Additional Tips
@@ -190,6 +232,7 @@ this library are not stripped. To do that, add these two lines to `proguard-rule
190232
```
191233

192234
## Docs
235+
193236
You can see the documentation [here](./docs).
194237

195238
## Usage
@@ -200,8 +243,8 @@ We have three important components to understand:
200243
import {
201244
TwilioVideo,
202245
TwilioVideoLocalView,
203-
TwilioVideoParticipantView
204-
} from 'react-native-twilio-video-webrtc'
246+
TwilioVideoParticipantView,
247+
} from "react-native-twilio-video-webrtc";
205248
```
206249

207250
- `TwilioVideo` / is responsible for connecting to rooms, events delivery and camera/audio.
@@ -210,62 +253,62 @@ import {
210253

211254
Here you can see a complete example of a simple application that uses almost all the apis:
212255

213-
````javascript
214-
import React, { Component, useRef } from 'react';
256+
```javascript
257+
import React, { Component, useRef } from "react";
215258
import {
216259
TwilioVideoLocalView,
217260
TwilioVideoParticipantView,
218-
TwilioVideo
219-
} from 'react-native-twilio-video-webrtc';
261+
TwilioVideo,
262+
} from "react-native-twilio-video-webrtc";
220263

221264
const Example = (props) => {
222265
const [isAudioEnabled, setIsAudioEnabled] = useState(true);
223266
const [isVideoEnabled, setIsVideoEnabled] = useState(true);
224-
const [status, setStatus] = useState('disconnected');
267+
const [status, setStatus] = useState("disconnected");
225268
const [participants, setParticipants] = useState(new Map());
226269
const [videoTracks, setVideoTracks] = useState(new Map());
227-
const [token, setToken] = useState('');
270+
const [token, setToken] = useState("");
228271
const twilioRef = useRef(null);
229272

230273
const _onConnectButtonPress = () => {
231274
twilioRef.current.connect({ accessToken: token });
232-
setStatus('connecting');
233-
}
234-
275+
setStatus("connecting");
276+
};
277+
235278
const _onEndButtonPress = () => {
236279
twilioRef.current.disconnect();
237280
};
238281

239282
const _onMuteButtonPress = () => {
240283
twilioRef.current
241284
.setLocalAudioEnabled(!isAudioEnabled)
242-
.then(isEnabled => setIsAudioEnabled(isEnabled));
285+
.then((isEnabled) => setIsAudioEnabled(isEnabled));
243286
};
244287

245288
const _onFlipButtonPress = () => {
246289
twilioRef.current.flipCamera();
247290
};
248291

249-
const _onRoomDidConnect = ({roomName, error}) => {
250-
console.log('onRoomDidConnect: ', roomName);
292+
const _onRoomDidConnect = ({ roomName, error }) => {
293+
console.log("onRoomDidConnect: ", roomName);
251294

252-
setStatus('connected');
295+
setStatus("connected");
253296
};
254297

255298
const _onRoomDidDisconnect = ({ roomName, error }) => {
256-
console.log('[Disconnect]ERROR: ', error);
299+
console.log("[Disconnect]ERROR: ", error);
257300

258-
setStatus('disconnected');
301+
setStatus("disconnected");
259302
};
260303

261-
const _onRoomDidFailToConnect = error => {
262-
console.log('[FailToConnect]ERROR: ', error);
304+
const _onRoomDidFailToConnect = (error) => {
305+
console.log("[FailToConnect]ERROR: ", error);
263306

264-
setStatus('disconnected');
307+
setStatus("disconnected");
265308
};
266309

267310
const _onParticipantAddedVideoTrack = ({ participant, track }) => {
268-
console.log('onParticipantAddedVideoTrack: ', participant, track);
311+
console.log("onParticipantAddedVideoTrack: ", participant, track);
269312

270313
setVideoTracks(
271314
new Map([
@@ -274,12 +317,12 @@ const Example = (props) => {
274317
track.trackSid,
275318
{ participantSid: participant.sid, videoTrackSid: track.trackSid },
276319
],
277-
]),
320+
])
278321
);
279322
};
280323

281324
const _onParticipantRemovedVideoTrack = ({ participant, track }) => {
282-
console.log('onParticipantRemovedVideoTrack: ', participant, track);
325+
console.log("onParticipantRemovedVideoTrack: ", participant, track);
283326

284327
const videoTracksLocal = videoTracks;
285328
videoTracksLocal.delete(track.trackSid);
@@ -289,84 +332,78 @@ const Example = (props) => {
289332

290333
return (
291334
<View style={styles.container}>
292-
{
293-
status === 'disconnected' &&
335+
{status === "disconnected" && (
294336
<View>
295-
<Text style={styles.welcome}>
296-
React Native Twilio Video
297-
</Text>
337+
<Text style={styles.welcome}>React Native Twilio Video</Text>
298338
<TextInput
299339
style={styles.input}
300-
autoCapitalize='none'
340+
autoCapitalize="none"
301341
value={token}
302-
onChangeText={(text) => setToken(text)}>
303-
</TextInput>
342+
onChangeText={(text) => setToken(text)}
343+
></TextInput>
304344
<Button
305345
title="Connect"
306346
style={styles.button}
307-
onPress={_onConnectButtonPress}>
308-
</Button>
347+
onPress={_onConnectButtonPress}
348+
></Button>
309349
</View>
310-
}
350+
)}
311351

312-
{
313-
(status === 'connected' || status === 'connecting') &&
314-
<View style={styles.callContainer}>
315-
{
316-
status === 'connected' &&
352+
{(status === "connected" || status === "connecting") && (
353+
<View style={styles.callContainer}>
354+
{status === "connected" && (
317355
<View style={styles.remoteGrid}>
318-
{
319-
Array.from(videoTracks, ([trackSid, trackIdentifier]) => {
320-
return (
321-
<TwilioVideoParticipantView
322-
style={styles.remoteVideo}
323-
key={trackSid}
324-
trackIdentifier={trackIdentifier}
325-
/>
326-
)
327-
})
328-
}
356+
{Array.from(videoTracks, ([trackSid, trackIdentifier]) => {
357+
return (
358+
<TwilioVideoParticipantView
359+
style={styles.remoteVideo}
360+
key={trackSid}
361+
trackIdentifier={trackIdentifier}
362+
/>
363+
);
364+
})}
329365
</View>
330-
}
331-
<View
332-
style={styles.optionsContainer}>
366+
)}
367+
<View style={styles.optionsContainer}>
333368
<TouchableOpacity
334369
style={styles.optionButton}
335-
onPress={_onEndButtonPress}>
336-
<Text style={{fontSize: 12}}>End</Text>
370+
onPress={_onEndButtonPress}
371+
>
372+
<Text style={{ fontSize: 12 }}>End</Text>
337373
</TouchableOpacity>
338374
<TouchableOpacity
339375
style={styles.optionButton}
340-
onPress={_onMuteButtonPress}>
341-
<Text style={{fontSize: 12}}>{ isAudioEnabled ? "Mute" : "Unmute" }</Text>
376+
onPress={_onMuteButtonPress}
377+
>
378+
<Text style={{ fontSize: 12 }}>
379+
{isAudioEnabled ? "Mute" : "Unmute"}
380+
</Text>
342381
</TouchableOpacity>
343382
<TouchableOpacity
344383
style={styles.optionButton}
345-
onPress={_onFlipButtonPress}>
346-
<Text style={{fontSize: 12}}>Flip</Text>
384+
onPress={_onFlipButtonPress}
385+
>
386+
<Text style={{ fontSize: 12 }}>Flip</Text>
347387
</TouchableOpacity>
348-
<TwilioVideoLocalView
349-
enabled={true}
350-
style={styles.localVideo}
351-
/>
388+
<TwilioVideoLocalView enabled={true} style={styles.localVideo} />
352389
</View>
353390
</View>
354-
}
391+
)}
355392

356393
<TwilioVideo
357-
ref={ twilioRef }
358-
onRoomDidConnect={ _onRoomDidConnect }
359-
onRoomDidDisconnect={ _onRoomDidDisconnect }
360-
onRoomDidFailToConnect= { _onRoomDidFailToConnect }
361-
onParticipantAddedVideoTrack={ _onParticipantAddedVideoTrack }
362-
onParticipantRemovedVideoTrack= { _onParticipantRemovedVideoTrack }
394+
ref={twilioRef}
395+
onRoomDidConnect={_onRoomDidConnect}
396+
onRoomDidDisconnect={_onRoomDidDisconnect}
397+
onRoomDidFailToConnect={_onRoomDidFailToConnect}
398+
onParticipantAddedVideoTrack={_onParticipantAddedVideoTrack}
399+
onParticipantRemovedVideoTrack={_onParticipantRemovedVideoTrack}
363400
/>
364401
</View>
365402
);
366-
}
403+
};
367404

368-
AppRegistry.registerComponent('Example', () => Example);
369-
````
405+
AppRegistry.registerComponent("Example", () => Example);
406+
```
370407

371408
## Run the Example Application
372409

@@ -379,18 +416,18 @@ To run the example application:
379416

380417
## Migrating from 1.x to 2.x
381418

382-
* Make sure your pod dependencies are updated. If you manually specified a pod version, you'll want to update it as follows:
419+
- Make sure your pod dependencies are updated. If you manually specified a pod version, you'll want to update it as follows:
383420

384421
```
385422
s.dependency 'TwilioVideo', '~> 2.2.0'
386423
```
387424

388-
* Both participants and tracks are uniquely identified by their `sid`/`trackSid` field.
389-
The `trackId` field no longer exists and should be replaced by `trackSid`. Commensurate with this change,
390-
participant views now expect `participantSid` and `videoTrackSid` keys in the `trackIdentity` prop (instead of
391-
`identity` and `trackId`).
425+
- Both participants and tracks are uniquely identified by their `sid`/`trackSid` field.
426+
The `trackId` field no longer exists and should be replaced by `trackSid`. Commensurate with this change,
427+
participant views now expect `participantSid` and `videoTrackSid` keys in the `trackIdentity` prop (instead of
428+
`identity` and `trackId`).
392429

393-
* Make sure you're listening to participant events via `onParticipant{Added/Removed}VideoTrack` rather than `onParticipant{Enabled/Disabled}Track`.
430+
- Make sure you're listening to participant events via `onParticipant{Added/Removed}VideoTrack` rather than `onParticipant{Enabled/Disabled}Track`.
394431

395432
## Contact
396433

app.plugin.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require("./plugin/build");

0 commit comments

Comments
 (0)