@livekit/react-native 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -17
- package/android/build.gradle +5 -3
- package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
- package/android/gradlew +154 -105
- package/android/src/main/AndroidManifest.xml +1 -2
- package/android/src/main/java/com/livekit/reactnative/video/SimulcastVideoEncoderFactoryWrapper.kt +249 -0
- package/lib/commonjs/components/VideoView.js +7 -3
- package/lib/commonjs/components/VideoView.js.map +1 -1
- package/lib/commonjs/components/ViewPortDetector.js.map +1 -1
- package/lib/commonjs/index.js +11 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/components/VideoView.js +7 -3
- package/lib/module/components/VideoView.js.map +1 -1
- package/lib/module/components/ViewPortDetector.js.map +1 -1
- package/lib/module/index.js +11 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/components/VideoView.d.ts +2 -1
- package/lib/typescript/components/ViewPortDetector.d.ts +3 -3
- package/livekit-react-native.podspec +1 -1
- package/package.json +15 -12
- package/src/components/VideoView.tsx +6 -2
- package/src/components/ViewPortDetector.tsx +4 -2
- package/src/index.tsx +10 -1
package/README.md
CHANGED
|
@@ -1,40 +1,91 @@
|
|
|
1
|
-
<!--BEGIN_BANNER_IMAGE
|
|
1
|
+
<!--BEGIN_BANNER_IMAGE-->
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="/.github/banner_dark.png">
|
|
4
|
+
<source media="(prefers-color-scheme: light)" srcset="/.github/banner_light.png">
|
|
5
|
+
<img style="width:100%;" alt="The LiveKit icon, the name of the repository and some sample code in the background." src="/.github/banner_light.png">
|
|
6
|
+
</picture>
|
|
7
|
+
<!--END_BANNER_IMAGE-->
|
|
2
8
|
|
|
3
9
|
# livekit-react-native
|
|
4
10
|
|
|
5
|
-
<!--BEGIN_DESCRIPTION-->
|
|
6
|
-
LiveKit Client SDK for React Native. (beta)
|
|
7
|
-
<!--END_DESCRIPTION-->
|
|
8
|
-
|
|
9
|
-
> **Info**
|
|
10
|
-
> Beta status currently
|
|
11
|
+
<!--BEGIN_DESCRIPTION-->Use this SDK to add real-time video, audio and data features to your React Native app. By connecting to a self- or cloud-hosted <a href="https://livekit.io/">LiveKit</a> server, you can quickly build applications like interactive live streaming or video calls with just a few lines of code.<!--END_DESCRIPTION-->
|
|
11
12
|
|
|
12
13
|
## Installation
|
|
13
14
|
|
|
14
15
|
### NPM
|
|
15
16
|
|
|
16
17
|
```sh
|
|
17
|
-
npm install @livekit/react-native
|
|
18
|
+
npm install @livekit/react-native @livekit/react-native-webrtc
|
|
18
19
|
```
|
|
19
20
|
|
|
20
21
|
### Yarn
|
|
21
22
|
|
|
22
23
|
```sh
|
|
23
|
-
yarn add @livekit/react-native
|
|
24
|
+
yarn add @livekit/react-native @livekit/react-native-webrtc
|
|
24
25
|
```
|
|
25
26
|
|
|
26
|
-
This library depends on
|
|
27
|
+
This library depends on `@livekit/react-native-webrtc`, which has additional installation instructions found here:
|
|
27
28
|
|
|
28
|
-
- [iOS Installation Guide](https://github.com/
|
|
29
|
-
- [Android Installation Guide](https://github.com/
|
|
29
|
+
- [iOS Installation Guide](https://github.com/livekit/react-native-webrtc/blob/master/Documentation/iOSInstallation.md)
|
|
30
|
+
- [Android Installation Guide](https://github.com/livekit/react-native-webrtc/blob/master/Documentation/AndroidInstallation.md)
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
----
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
Once the `@livekit/react-native-webrtc` dependency is installed, one last step is needed to finish the installation:
|
|
35
|
+
|
|
36
|
+
### Android
|
|
37
|
+
|
|
38
|
+
In your [MainApplication.java](https://github.com/livekit/client-sdk-react-native/blob/main/example/android/app/src/main/java/com/example/livekitreactnative/MainApplication.java) file:
|
|
34
39
|
|
|
35
|
-
|
|
40
|
+
```
|
|
41
|
+
import com.livekit.reactnative.video.SimulcastVideoEncoderFactoryWrapper;
|
|
42
|
+
import com.oney.WebRTCModule.WebRTCModuleOptions;
|
|
43
|
+
import com.oney.WebRTCModule.webrtcutils.H264AndSoftwareVideoDecoderFactory;
|
|
44
|
+
|
|
45
|
+
import org.webrtc.*;
|
|
46
|
+
|
|
47
|
+
public class MainApplication extends Application implements ReactApplication {
|
|
48
|
+
|
|
49
|
+
@Override
|
|
50
|
+
public void onCreate() {
|
|
51
|
+
// Place this above any other RN related initialization
|
|
52
|
+
WebRTCModuleOptions options = WebRTCModuleOptions.getInstance();
|
|
53
|
+
options.videoEncoderFactory = new SimulcastVideoEncoderFactoryWrapper(null, true, true);
|
|
54
|
+
options.videoDecoderFactory = new H264AndSoftwareVideoDecoderFactory(null);
|
|
55
|
+
// ...
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
36
59
|
|
|
37
|
-
|
|
60
|
+
### iOS
|
|
61
|
+
|
|
62
|
+
In your [AppDelegate.m](https://github.com/livekit/client-sdk-react-native/blob/main/example/ios/LivekitReactNativeExample/AppDelegate.mm) file:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
#import "WebRTCModule.h"
|
|
66
|
+
#import "WebRTCModuleOptions.h"
|
|
67
|
+
|
|
68
|
+
@implementation AppDelegate
|
|
69
|
+
|
|
70
|
+
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
|
71
|
+
{
|
|
72
|
+
// Place this above any other RN related initialization
|
|
73
|
+
RTCDefaultVideoEncoderFactory *videoEncoderFactory = [[RTCDefaultVideoEncoderFactory alloc] init];
|
|
74
|
+
RTCVideoEncoderFactorySimulcast *simulcastVideoEncoderFactory =
|
|
75
|
+
[[RTCVideoEncoderFactorySimulcast alloc] initWithPrimary:videoEncoderFactory fallback:videoEncoderFactory];
|
|
76
|
+
WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance];
|
|
77
|
+
options.videoEncoderFactory = simulcastVideoEncoderFactory;
|
|
78
|
+
//...
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Expo
|
|
83
|
+
|
|
84
|
+
LiveKit is available on Expo through development builds. [See the instructions found here](https://github.com/livekit/client-sdk-react-native/wiki/Expo-Development-Build-Instructions).
|
|
85
|
+
|
|
86
|
+
## Example app
|
|
87
|
+
|
|
88
|
+
We've included an [example app](example/) that you can try out.
|
|
38
89
|
|
|
39
90
|
## Usage
|
|
40
91
|
|
|
@@ -153,4 +204,14 @@ See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the
|
|
|
153
204
|
|
|
154
205
|
Apache License 2.0
|
|
155
206
|
|
|
156
|
-
<!--BEGIN_REPO_NAV
|
|
207
|
+
<!--BEGIN_REPO_NAV-->
|
|
208
|
+
<br/><table>
|
|
209
|
+
<thead><tr><th colspan="2">LiveKit Ecosystem</th></tr></thead>
|
|
210
|
+
<tbody>
|
|
211
|
+
<tr><td>Client SDKs</td><td><a href="https://github.com/livekit/components-js">Components</a> · <a href="https://github.com/livekit/client-sdk-js">JavaScript</a> · <a href="https://github.com/livekit/client-sdk-rust">Rust</a> · <a href="https://github.com/livekit/client-sdk-swift">iOS/macOS</a> · <a href="https://github.com/livekit/client-sdk-android">Android</a> · <a href="https://github.com/livekit/client-sdk-flutter">Flutter</a> · <a href="https://github.com/livekit/client-sdk-unity-web">Unity (web)</a> · <b>React Native (beta)</b></td></tr><tr></tr>
|
|
212
|
+
<tr><td>Server SDKs</td><td><a href="https://github.com/livekit/server-sdk-js">Node.js</a> · <a href="https://github.com/livekit/server-sdk-go">Golang</a> · <a href="https://github.com/livekit/server-sdk-ruby">Ruby</a> · <a href="https://github.com/livekit/server-sdk-kotlin">Java/Kotlin</a> · <a href="https://github.com/agence104/livekit-server-sdk-php">PHP (community)</a> · <a href="https://github.com/tradablebits/livekit-server-sdk-python">Python (community)</a></td></tr><tr></tr>
|
|
213
|
+
<tr><td>Services</td><td><a href="https://github.com/livekit/livekit">Livekit server</a> · <a href="https://github.com/livekit/egress">Egress</a> · <a href="https://github.com/livekit/ingress">Ingress</a></td></tr><tr></tr>
|
|
214
|
+
<tr><td>Resources</td><td><a href="https://docs.livekit.io">Docs</a> · <a href="https://github.com/livekit-examples">Example apps</a> · <a href="https://livekit.io/cloud">Cloud</a> · <a href="https://docs.livekit.io/oss/deployment">Self-hosting</a> · <a href="https://github.com/livekit/livekit-cli">CLI</a></td></tr>
|
|
215
|
+
</tbody>
|
|
216
|
+
</table>
|
|
217
|
+
<!--END_REPO_NAV-->
|
package/android/build.gradle
CHANGED
|
@@ -9,7 +9,7 @@ buildscript {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
dependencies {
|
|
12
|
-
classpath
|
|
12
|
+
classpath("com.android.tools.build:gradle:7.3.1")
|
|
13
13
|
// noinspection DifferentKotlinGradleVersion
|
|
14
14
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
15
15
|
}
|
|
@@ -28,14 +28,15 @@ def getExtOrIntegerDefault(name) {
|
|
|
28
28
|
|
|
29
29
|
android {
|
|
30
30
|
compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
|
|
31
|
+
namespace "com.livekit.reactnative"
|
|
31
32
|
defaultConfig {
|
|
32
33
|
minSdkVersion 16
|
|
33
34
|
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
|
|
34
35
|
versionCode 1
|
|
35
36
|
versionName "1.0"
|
|
36
|
-
|
|
37
|
+
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
+
|
|
39
40
|
buildTypes {
|
|
40
41
|
release {
|
|
41
42
|
minifyEnabled false
|
|
@@ -129,5 +130,6 @@ dependencies {
|
|
|
129
130
|
api 'com.facebook.react:react-native:+'
|
|
130
131
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
131
132
|
api 'com.github.davidliu:audioswitch:c498d866c57f1d88056d5e7e7a78d622e3b0c046'
|
|
133
|
+
api 'io.github.webrtc-sdk:android:104.5112.09'
|
|
132
134
|
implementation "androidx.annotation:annotation:1.4.0"
|
|
133
135
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
distributionBase=GRADLE_USER_HOME
|
|
2
2
|
distributionPath=wrapper/dists
|
|
3
|
-
distributionUrl=https\://services.gradle.org/distributions/gradle-
|
|
3
|
+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
|
|
4
4
|
zipStoreBase=GRADLE_USER_HOME
|
|
5
5
|
zipStorePath=wrapper/dists
|
package/android/gradlew
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
#!/
|
|
1
|
+
#!/bin/sh
|
|
2
2
|
|
|
3
3
|
#
|
|
4
|
-
# Copyright 2015 the original
|
|
4
|
+
# Copyright © 2015-2021 the original authors.
|
|
5
5
|
#
|
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
# you may not use this file except in compliance with the License.
|
|
@@ -17,67 +17,101 @@
|
|
|
17
17
|
#
|
|
18
18
|
|
|
19
19
|
##############################################################################
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
#
|
|
21
|
+
# Gradle start up script for POSIX generated by Gradle.
|
|
22
|
+
#
|
|
23
|
+
# Important for running:
|
|
24
|
+
#
|
|
25
|
+
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
|
26
|
+
# noncompliant, but you have some other compliant shell such as ksh or
|
|
27
|
+
# bash, then to run this script, type that shell name before the whole
|
|
28
|
+
# command line, like:
|
|
29
|
+
#
|
|
30
|
+
# ksh Gradle
|
|
31
|
+
#
|
|
32
|
+
# Busybox and similar reduced shells will NOT work, because this script
|
|
33
|
+
# requires all of these POSIX shell features:
|
|
34
|
+
# * functions;
|
|
35
|
+
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
|
36
|
+
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
|
37
|
+
# * compound commands having a testable exit status, especially «case»;
|
|
38
|
+
# * various built-in commands including «command», «set», and «ulimit».
|
|
39
|
+
#
|
|
40
|
+
# Important for patching:
|
|
41
|
+
#
|
|
42
|
+
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
|
43
|
+
# by Bash, Ksh, etc; in particular arrays are avoided.
|
|
44
|
+
#
|
|
45
|
+
# The "traditional" practice of packing multiple parameters into a
|
|
46
|
+
# space-separated string is a well documented source of bugs and security
|
|
47
|
+
# problems, so this is (mostly) avoided, by progressively accumulating
|
|
48
|
+
# options in "$@", and eventually passing that to Java.
|
|
49
|
+
#
|
|
50
|
+
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
|
51
|
+
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
|
52
|
+
# see the in-line comments for details.
|
|
53
|
+
#
|
|
54
|
+
# There are tweaks for specific operating systems such as AIX, CygWin,
|
|
55
|
+
# Darwin, MinGW, and NonStop.
|
|
56
|
+
#
|
|
57
|
+
# (3) This script is generated from the Groovy template
|
|
58
|
+
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
|
59
|
+
# within the Gradle project.
|
|
60
|
+
#
|
|
61
|
+
# You can find Gradle at https://github.com/gradle/gradle/.
|
|
62
|
+
#
|
|
23
63
|
##############################################################################
|
|
24
64
|
|
|
25
65
|
# Attempt to set APP_HOME
|
|
66
|
+
|
|
26
67
|
# Resolve links: $0 may be a link
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
68
|
+
app_path=$0
|
|
69
|
+
|
|
70
|
+
# Need this for daisy-chained symlinks.
|
|
71
|
+
while
|
|
72
|
+
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
|
73
|
+
[ -h "$app_path" ]
|
|
74
|
+
do
|
|
75
|
+
ls=$( ls -ld "$app_path" )
|
|
76
|
+
link=${ls#*' -> '}
|
|
77
|
+
case $link in #(
|
|
78
|
+
/*) app_path=$link ;; #(
|
|
79
|
+
*) app_path=$APP_HOME$link ;;
|
|
80
|
+
esac
|
|
37
81
|
done
|
|
38
|
-
|
|
39
|
-
cd "
|
|
40
|
-
APP_HOME="`pwd -P`"
|
|
41
|
-
cd "$SAVED" >/dev/null
|
|
82
|
+
|
|
83
|
+
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
|
42
84
|
|
|
43
85
|
APP_NAME="Gradle"
|
|
44
|
-
APP_BASE_NAME
|
|
86
|
+
APP_BASE_NAME=${0##*/}
|
|
45
87
|
|
|
46
88
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
47
89
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|
48
90
|
|
|
49
91
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
|
50
|
-
MAX_FD=
|
|
92
|
+
MAX_FD=maximum
|
|
51
93
|
|
|
52
94
|
warn () {
|
|
53
95
|
echo "$*"
|
|
54
|
-
}
|
|
96
|
+
} >&2
|
|
55
97
|
|
|
56
98
|
die () {
|
|
57
99
|
echo
|
|
58
100
|
echo "$*"
|
|
59
101
|
echo
|
|
60
102
|
exit 1
|
|
61
|
-
}
|
|
103
|
+
} >&2
|
|
62
104
|
|
|
63
105
|
# OS specific support (must be 'true' or 'false').
|
|
64
106
|
cygwin=false
|
|
65
107
|
msys=false
|
|
66
108
|
darwin=false
|
|
67
109
|
nonstop=false
|
|
68
|
-
case "
|
|
69
|
-
CYGWIN* )
|
|
70
|
-
|
|
71
|
-
;;
|
|
72
|
-
|
|
73
|
-
darwin=true
|
|
74
|
-
;;
|
|
75
|
-
MINGW* )
|
|
76
|
-
msys=true
|
|
77
|
-
;;
|
|
78
|
-
NONSTOP* )
|
|
79
|
-
nonstop=true
|
|
80
|
-
;;
|
|
110
|
+
case "$( uname )" in #(
|
|
111
|
+
CYGWIN* ) cygwin=true ;; #(
|
|
112
|
+
Darwin* ) darwin=true ;; #(
|
|
113
|
+
MSYS* | MINGW* ) msys=true ;; #(
|
|
114
|
+
NONSTOP* ) nonstop=true ;;
|
|
81
115
|
esac
|
|
82
116
|
|
|
83
117
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
|
87
121
|
if [ -n "$JAVA_HOME" ] ; then
|
|
88
122
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
89
123
|
# IBM's JDK on AIX uses strange locations for the executables
|
|
90
|
-
JAVACMD
|
|
124
|
+
JAVACMD=$JAVA_HOME/jre/sh/java
|
|
91
125
|
else
|
|
92
|
-
JAVACMD
|
|
126
|
+
JAVACMD=$JAVA_HOME/bin/java
|
|
93
127
|
fi
|
|
94
128
|
if [ ! -x "$JAVACMD" ] ; then
|
|
95
129
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
|
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
|
|
98
132
|
location of your Java installation."
|
|
99
133
|
fi
|
|
100
134
|
else
|
|
101
|
-
JAVACMD=
|
|
135
|
+
JAVACMD=java
|
|
102
136
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
103
137
|
|
|
104
138
|
Please set the JAVA_HOME variable in your environment to match the
|
|
@@ -106,80 +140,95 @@ location of your Java installation."
|
|
|
106
140
|
fi
|
|
107
141
|
|
|
108
142
|
# Increase the maximum file descriptors if we can.
|
|
109
|
-
if
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
fi
|
|
143
|
+
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|
144
|
+
case $MAX_FD in #(
|
|
145
|
+
max*)
|
|
146
|
+
MAX_FD=$( ulimit -H -n ) ||
|
|
147
|
+
warn "Could not query maximum file descriptor limit"
|
|
148
|
+
esac
|
|
149
|
+
case $MAX_FD in #(
|
|
150
|
+
'' | soft) :;; #(
|
|
151
|
+
*)
|
|
152
|
+
ulimit -n "$MAX_FD" ||
|
|
153
|
+
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
|
154
|
+
esac
|
|
122
155
|
fi
|
|
123
156
|
|
|
124
|
-
#
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
157
|
+
# Collect all arguments for the java command, stacking in reverse order:
|
|
158
|
+
# * args from the command line
|
|
159
|
+
# * the main class name
|
|
160
|
+
# * -classpath
|
|
161
|
+
# * -D...appname settings
|
|
162
|
+
# * --module-path (only if needed)
|
|
163
|
+
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
|
128
164
|
|
|
129
165
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
|
130
|
-
if
|
|
131
|
-
APP_HOME
|
|
132
|
-
CLASSPATH
|
|
133
|
-
|
|
134
|
-
JAVACMD
|
|
135
|
-
|
|
136
|
-
# We build the pattern for arguments to be converted via cygpath
|
|
137
|
-
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
|
138
|
-
SEP=""
|
|
139
|
-
for dir in $ROOTDIRSRAW ; do
|
|
140
|
-
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
|
141
|
-
SEP="|"
|
|
142
|
-
done
|
|
143
|
-
OURCYGPATTERN="(^($ROOTDIRS))"
|
|
144
|
-
# Add a user-defined pattern to the cygpath arguments
|
|
145
|
-
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
|
146
|
-
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
|
147
|
-
fi
|
|
166
|
+
if "$cygwin" || "$msys" ; then
|
|
167
|
+
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
|
168
|
+
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
|
169
|
+
|
|
170
|
+
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
|
171
|
+
|
|
148
172
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
173
|
+
for arg do
|
|
174
|
+
if
|
|
175
|
+
case $arg in #(
|
|
176
|
+
-*) false ;; # don't mess with options #(
|
|
177
|
+
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
|
178
|
+
[ -e "$t" ] ;; #(
|
|
179
|
+
*) false ;;
|
|
180
|
+
esac
|
|
181
|
+
then
|
|
182
|
+
arg=$( cygpath --path --ignore --mixed "$arg" )
|
|
158
183
|
fi
|
|
159
|
-
|
|
184
|
+
# Roll the args list around exactly as many times as the number of
|
|
185
|
+
# args, so each arg winds up back in the position where it started, but
|
|
186
|
+
# possibly modified.
|
|
187
|
+
#
|
|
188
|
+
# NB: a `for` loop captures its iteration list before it begins, so
|
|
189
|
+
# changing the positional parameters here affects neither the number of
|
|
190
|
+
# iterations, nor the values presented in `arg`.
|
|
191
|
+
shift # remove old arg
|
|
192
|
+
set -- "$@" "$arg" # push replacement arg
|
|
160
193
|
done
|
|
161
|
-
case $i in
|
|
162
|
-
0) set -- ;;
|
|
163
|
-
1) set -- "$args0" ;;
|
|
164
|
-
2) set -- "$args0" "$args1" ;;
|
|
165
|
-
3) set -- "$args0" "$args1" "$args2" ;;
|
|
166
|
-
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
|
167
|
-
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
|
168
|
-
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
|
169
|
-
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
|
170
|
-
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
|
171
|
-
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
|
172
|
-
esac
|
|
173
194
|
fi
|
|
174
195
|
|
|
175
|
-
#
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
196
|
+
# Collect all arguments for the java command;
|
|
197
|
+
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
|
198
|
+
# shell script including quotes and variable substitutions, so put them in
|
|
199
|
+
# double quotes to make sure that they get re-expanded; and
|
|
200
|
+
# * put everything else in single quotes, so that it's not re-expanded.
|
|
201
|
+
|
|
202
|
+
set -- \
|
|
203
|
+
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
|
204
|
+
-classpath "$CLASSPATH" \
|
|
205
|
+
org.gradle.wrapper.GradleWrapperMain \
|
|
206
|
+
"$@"
|
|
207
|
+
|
|
208
|
+
# Use "xargs" to parse quoted args.
|
|
209
|
+
#
|
|
210
|
+
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
|
211
|
+
#
|
|
212
|
+
# In Bash we could simply go:
|
|
213
|
+
#
|
|
214
|
+
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
|
215
|
+
# set -- "${ARGS[@]}" "$@"
|
|
216
|
+
#
|
|
217
|
+
# but POSIX shell has neither arrays nor command substitution, so instead we
|
|
218
|
+
# post-process each arg (as a line of input to sed) to backslash-escape any
|
|
219
|
+
# character that might be a shell metacharacter, then use eval to reverse
|
|
220
|
+
# that process (while maintaining the separation between arguments), and wrap
|
|
221
|
+
# the whole thing up as a single "set" statement.
|
|
222
|
+
#
|
|
223
|
+
# This will of course break if any of these variables contains a newline or
|
|
224
|
+
# an unmatched quote.
|
|
225
|
+
#
|
|
181
226
|
|
|
182
|
-
|
|
183
|
-
|
|
227
|
+
eval "set -- $(
|
|
228
|
+
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
|
229
|
+
xargs -n1 |
|
|
230
|
+
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
|
231
|
+
tr '\n' ' '
|
|
232
|
+
)" '"$@"'
|
|
184
233
|
|
|
185
|
-
exec "$JAVACMD" "$@"
|
|
234
|
+
exec "$JAVACMD" "$@"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
-
package="com.livekit.reactnative">
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
2
|
|
|
4
3
|
<uses-permission android:name="android.permission.INTERNET" />
|
|
5
4
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
package/android/src/main/java/com/livekit/reactnative/video/SimulcastVideoEncoderFactoryWrapper.kt
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
package com.livekit.reactnative.video
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import org.webrtc.EglBase
|
|
5
|
+
import org.webrtc.HardwareVideoEncoderFactory
|
|
6
|
+
import org.webrtc.SimulcastVideoEncoderFactory
|
|
7
|
+
import org.webrtc.SoftwareVideoEncoderFactory
|
|
8
|
+
import org.webrtc.VideoCodecInfo
|
|
9
|
+
import org.webrtc.VideoCodecStatus
|
|
10
|
+
import org.webrtc.VideoEncoder
|
|
11
|
+
import org.webrtc.VideoEncoderFactory
|
|
12
|
+
import org.webrtc.VideoEncoderFallback
|
|
13
|
+
import org.webrtc.VideoFrame
|
|
14
|
+
import org.webrtc.WrappedNativeVideoEncoder
|
|
15
|
+
import java.util.concurrent.Callable
|
|
16
|
+
import java.util.concurrent.ExecutorService
|
|
17
|
+
import java.util.concurrent.Executors
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
Copyright 2017, Lyo Kato <lyo.kato at gmail.com> (Original Author)
|
|
21
|
+
Copyright 2017-2021, Shiguredo Inc.
|
|
22
|
+
|
|
23
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
24
|
+
you may not use this file except in compliance with the License.
|
|
25
|
+
You may obtain a copy of the License at
|
|
26
|
+
|
|
27
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
28
|
+
|
|
29
|
+
Unless required by applicable law or agreed to in writing, software
|
|
30
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
31
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
32
|
+
See the License for the specific language governing permissions and
|
|
33
|
+
limitations under the License.
|
|
34
|
+
*/
|
|
35
|
+
open class SimulcastVideoEncoderFactoryWrapper(
|
|
36
|
+
sharedContext: EglBase.Context?,
|
|
37
|
+
enableIntelVp8Encoder: Boolean,
|
|
38
|
+
enableH264HighProfile: Boolean
|
|
39
|
+
) : VideoEncoderFactory {
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Factory that prioritizes software encoder.
|
|
43
|
+
*
|
|
44
|
+
* When the selected codec can't be handled by the software encoder,
|
|
45
|
+
* it uses the hardware encoder as a fallback. However, this class is
|
|
46
|
+
* primarily used to address an issue in libwebrtc, and does not have
|
|
47
|
+
* purposeful usecase itself.
|
|
48
|
+
*
|
|
49
|
+
* To use simulcast in libwebrtc, SimulcastEncoderAdapter is used.
|
|
50
|
+
* SimulcastEncoderAdapter takes in a primary and fallback encoder.
|
|
51
|
+
* If HardwareVideoEncoderFactory and SoftwareVideoEncoderFactory are
|
|
52
|
+
* passed in directly as primary and fallback, when H.264 is used,
|
|
53
|
+
* libwebrtc will crash.
|
|
54
|
+
*
|
|
55
|
+
* This is because SoftwareVideoEncoderFactory does not handle H.264,
|
|
56
|
+
* so [SoftwareVideoEncoderFactory.createEncoder] returns null, and
|
|
57
|
+
* the libwebrtc side does not handle nulls, regardless of whether the
|
|
58
|
+
* fallback is actually used or not.
|
|
59
|
+
*
|
|
60
|
+
* To avoid nulls, we simply pass responsibility over to the HardwareVideoEncoderFactory.
|
|
61
|
+
* This results in HardwareVideoEncoderFactory being both the primary and fallback,
|
|
62
|
+
* but there aren't any specific problems in doing so.
|
|
63
|
+
*/
|
|
64
|
+
private class FallbackFactory(private val hardwareVideoEncoderFactory: VideoEncoderFactory) :
|
|
65
|
+
VideoEncoderFactory {
|
|
66
|
+
|
|
67
|
+
private val softwareVideoEncoderFactory: VideoEncoderFactory = SoftwareVideoEncoderFactory()
|
|
68
|
+
|
|
69
|
+
override fun createEncoder(info: VideoCodecInfo): VideoEncoder? {
|
|
70
|
+
val softwareEncoder = softwareVideoEncoderFactory.createEncoder(info)
|
|
71
|
+
val hardwareEncoder = hardwareVideoEncoderFactory.createEncoder(info)
|
|
72
|
+
return if (hardwareEncoder != null && softwareEncoder != null) {
|
|
73
|
+
VideoEncoderFallback(hardwareEncoder, softwareEncoder)
|
|
74
|
+
} else {
|
|
75
|
+
softwareEncoder ?: hardwareEncoder
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
override fun getSupportedCodecs(): Array<VideoCodecInfo> {
|
|
80
|
+
val supportedCodecInfos: MutableList<VideoCodecInfo> = mutableListOf()
|
|
81
|
+
supportedCodecInfos.addAll(softwareVideoEncoderFactory.supportedCodecs)
|
|
82
|
+
supportedCodecInfos.addAll(hardwareVideoEncoderFactory.supportedCodecs)
|
|
83
|
+
return supportedCodecInfos.toTypedArray()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Wraps each stream encoder and performs the following:
|
|
90
|
+
* - Starts up a single thread
|
|
91
|
+
* - When the width/height from [initEncode] doesn't match the frame buffer's,
|
|
92
|
+
* scales the frame prior to encoding.
|
|
93
|
+
* - Always calls the encoder on the thread.
|
|
94
|
+
*/
|
|
95
|
+
private class StreamEncoderWrapper(private val encoder: VideoEncoder) : VideoEncoder {
|
|
96
|
+
|
|
97
|
+
val executor: ExecutorService = Executors.newSingleThreadExecutor()
|
|
98
|
+
var streamSettings: VideoEncoder.Settings? = null
|
|
99
|
+
|
|
100
|
+
override fun initEncode(
|
|
101
|
+
settings: VideoEncoder.Settings,
|
|
102
|
+
callback: VideoEncoder.Callback?
|
|
103
|
+
): VideoCodecStatus {
|
|
104
|
+
streamSettings = settings
|
|
105
|
+
val future = executor.submit(Callable {
|
|
106
|
+
Log.i(
|
|
107
|
+
"SimulVideoEncoderFac",
|
|
108
|
+
"""initEncode() thread=${Thread.currentThread().name} [${Thread.currentThread().id}]
|
|
109
|
+
| encoder=${encoder.implementationName}
|
|
110
|
+
| streamSettings:
|
|
111
|
+
| numberOfCores=${settings.numberOfCores}
|
|
112
|
+
| width=${settings.width}
|
|
113
|
+
| height=${settings.height}
|
|
114
|
+
| startBitrate=${settings.startBitrate}
|
|
115
|
+
| maxFramerate=${settings.maxFramerate}
|
|
116
|
+
| automaticResizeOn=${settings.automaticResizeOn}
|
|
117
|
+
| numberOfSimulcastStreams=${settings.numberOfSimulcastStreams}
|
|
118
|
+
| lossNotification=${settings.capabilities.lossNotification}
|
|
119
|
+
""".trimMargin()
|
|
120
|
+
)
|
|
121
|
+
return@Callable encoder.initEncode(settings, callback)
|
|
122
|
+
})
|
|
123
|
+
return future.get()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
override fun release(): VideoCodecStatus {
|
|
127
|
+
val future = executor.submit(Callable { return@Callable encoder.release() })
|
|
128
|
+
return future.get()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
override fun encode(
|
|
132
|
+
frame: VideoFrame,
|
|
133
|
+
encodeInfo: VideoEncoder.EncodeInfo?
|
|
134
|
+
): VideoCodecStatus {
|
|
135
|
+
val future = executor.submit(Callable {
|
|
136
|
+
//LKLog.d { "encode() buffer=${frame.buffer}, thread=${Thread.currentThread().name} " +
|
|
137
|
+
// "[${Thread.currentThread().id}]" }
|
|
138
|
+
if (streamSettings == null) {
|
|
139
|
+
return@Callable encoder.encode(frame, encodeInfo)
|
|
140
|
+
} else if (frame.buffer.width == streamSettings!!.width) {
|
|
141
|
+
return@Callable encoder.encode(frame, encodeInfo)
|
|
142
|
+
} else {
|
|
143
|
+
// The incoming buffer is different than the streamSettings received in initEncode()
|
|
144
|
+
// Need to scale.
|
|
145
|
+
val originalBuffer = frame.buffer
|
|
146
|
+
// TODO: Do we need to handle when the scale factor is weird?
|
|
147
|
+
val adaptedBuffer = originalBuffer.cropAndScale(
|
|
148
|
+
0, 0, originalBuffer.width, originalBuffer.height,
|
|
149
|
+
streamSettings!!.width, streamSettings!!.height
|
|
150
|
+
)
|
|
151
|
+
val adaptedFrame = VideoFrame(adaptedBuffer, frame.rotation, frame.timestampNs)
|
|
152
|
+
val result = encoder.encode(adaptedFrame, encodeInfo)
|
|
153
|
+
adaptedBuffer.release()
|
|
154
|
+
return@Callable result
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
return future.get()
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
override fun setRateAllocation(
|
|
161
|
+
allocation: VideoEncoder.BitrateAllocation?,
|
|
162
|
+
frameRate: Int
|
|
163
|
+
): VideoCodecStatus {
|
|
164
|
+
val future = executor.submit(Callable {
|
|
165
|
+
return@Callable encoder.setRateAllocation(
|
|
166
|
+
allocation,
|
|
167
|
+
frameRate
|
|
168
|
+
)
|
|
169
|
+
})
|
|
170
|
+
return future.get()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
override fun getScalingSettings(): VideoEncoder.ScalingSettings {
|
|
174
|
+
val future = executor.submit(Callable { return@Callable encoder.scalingSettings })
|
|
175
|
+
return future.get()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
override fun getImplementationName(): String {
|
|
179
|
+
val future = executor.submit(Callable { return@Callable encoder.implementationName })
|
|
180
|
+
return future.get()
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
override fun createNativeVideoEncoder(): Long {
|
|
184
|
+
val future = executor.submit(Callable { return@Callable encoder.createNativeVideoEncoder() })
|
|
185
|
+
return future.get()
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
override fun isHardwareEncoder(): Boolean {
|
|
189
|
+
val future = executor.submit(Callable { return@Callable encoder.isHardwareEncoder })
|
|
190
|
+
return future.get()
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
override fun setRates(rcParameters: VideoEncoder.RateControlParameters?): VideoCodecStatus {
|
|
194
|
+
val future = executor.submit(Callable { return@Callable encoder.setRates(rcParameters) })
|
|
195
|
+
return future.get()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
override fun getResolutionBitrateLimits(): Array<VideoEncoder.ResolutionBitrateLimits> {
|
|
199
|
+
val future = executor.submit(Callable { return@Callable encoder.resolutionBitrateLimits })
|
|
200
|
+
return future.get()
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
override fun getEncoderInfo(): VideoEncoder.EncoderInfo {
|
|
204
|
+
val future = executor.submit(Callable { return@Callable encoder.encoderInfo })
|
|
205
|
+
return future.get()
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private class StreamEncoderWrapperFactory(private val factory: VideoEncoderFactory) :
|
|
210
|
+
VideoEncoderFactory {
|
|
211
|
+
override fun createEncoder(videoCodecInfo: VideoCodecInfo?): VideoEncoder? {
|
|
212
|
+
val encoder = factory.createEncoder(videoCodecInfo)
|
|
213
|
+
if (encoder == null) {
|
|
214
|
+
return null
|
|
215
|
+
}
|
|
216
|
+
if (encoder is WrappedNativeVideoEncoder) {
|
|
217
|
+
return encoder
|
|
218
|
+
}
|
|
219
|
+
return StreamEncoderWrapper(encoder)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
override fun getSupportedCodecs(): Array<VideoCodecInfo> {
|
|
223
|
+
return factory.supportedCodecs
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
private val primary: VideoEncoderFactory
|
|
229
|
+
private val fallback: VideoEncoderFactory
|
|
230
|
+
private val native: SimulcastVideoEncoderFactory
|
|
231
|
+
|
|
232
|
+
init {
|
|
233
|
+
val hardwareVideoEncoderFactory = HardwareVideoEncoderFactory(
|
|
234
|
+
sharedContext, enableIntelVp8Encoder, enableH264HighProfile
|
|
235
|
+
)
|
|
236
|
+
primary = StreamEncoderWrapperFactory(hardwareVideoEncoderFactory)
|
|
237
|
+
fallback = StreamEncoderWrapperFactory(FallbackFactory(primary))
|
|
238
|
+
native = SimulcastVideoEncoderFactory(primary, fallback)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
override fun createEncoder(info: VideoCodecInfo?): VideoEncoder? {
|
|
242
|
+
return native.createEncoder(info)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
override fun getSupportedCodecs(): Array<VideoCodecInfo> {
|
|
246
|
+
return native.supportedCodecs
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
}
|
|
@@ -11,7 +11,7 @@ var _reactNative = require("react-native");
|
|
|
11
11
|
|
|
12
12
|
var _livekitClient = require("livekit-client");
|
|
13
13
|
|
|
14
|
-
var _reactNativeWebrtc = require("react-native-webrtc");
|
|
14
|
+
var _reactNativeWebrtc = require("@livekit/react-native-webrtc");
|
|
15
15
|
|
|
16
16
|
var _ViewPortDetector = _interopRequireDefault(require("./ViewPortDetector"));
|
|
17
17
|
|
|
@@ -76,8 +76,12 @@ const VideoView = _ref => {
|
|
|
76
76
|
}, /*#__PURE__*/React.createElement(_ViewPortDetector.default, {
|
|
77
77
|
onChange: isVisible => elementInfo.onVisibility(isVisible),
|
|
78
78
|
style: styles.videoView
|
|
79
|
-
}, /*#__PURE__*/React.createElement(_reactNativeWebrtc.RTCView
|
|
80
|
-
|
|
79
|
+
}, /*#__PURE__*/React.createElement(_reactNativeWebrtc.RTCView // eslint-disable-next-line react-native/no-inline-styles
|
|
80
|
+
, {
|
|
81
|
+
style: {
|
|
82
|
+
flex: 1,
|
|
83
|
+
width: '100%'
|
|
84
|
+
},
|
|
81
85
|
streamURL: (_mediaStream$toURL = mediaStream === null || mediaStream === void 0 ? void 0 : mediaStream.toURL()) !== null && _mediaStream$toURL !== void 0 ? _mediaStream$toURL : '',
|
|
82
86
|
objectFit: objectFit,
|
|
83
87
|
zOrder: zOrder,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["VideoView.tsx"],"names":["VideoView","style","videoTrack","objectFit","zOrder","mirror","elementInfo","info","VideoViewElementInfo","id","sid","something","mediaStream","setMediaStream","LocalVideoTrack","onRestarted","track","on","TrackEvent","Restarted","off","RemoteVideoTrack","isAdaptiveStream","observeElementInfo","stopObservingElementInfo","styles","container","event","onLayout","isVisible","onVisibility","videoView","
|
|
1
|
+
{"version":3,"sources":["VideoView.tsx"],"names":["VideoView","style","videoTrack","objectFit","zOrder","mirror","elementInfo","info","VideoViewElementInfo","id","sid","something","mediaStream","setMediaStream","LocalVideoTrack","onRestarted","track","on","TrackEvent","Restarted","off","RemoteVideoTrack","isAdaptiveStream","observeElementInfo","stopObservingElementInfo","styles","container","event","onLayout","isVisible","onVisibility","videoView","flex","width","toURL","StyleSheet","create","_width","_height","observe","_observing","stopObserving","height","nativeEvent","layout","handleResize","visible","visibilityChangedAt","Date","now","handleVisibilityChanged"],"mappings":"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","sourcesContent":["import * as React from 'react';\n\nimport { LayoutChangeEvent, StyleSheet, View, ViewStyle } from 'react-native';\nimport {\n ElementInfo,\n LocalVideoTrack,\n Track,\n TrackEvent,\n VideoTrack,\n} from 'livekit-client';\nimport { RTCView } from '@livekit/react-native-webrtc';\nimport { useEffect, useState } from 'react';\nimport { RemoteVideoTrack } from 'livekit-client';\nimport ViewPortDetector from './ViewPortDetector';\n\nexport type Props = {\n videoTrack?: VideoTrack | undefined;\n style?: ViewStyle;\n objectFit?: 'cover' | 'contain' | undefined;\n mirror?: boolean;\n zOrder?: number;\n};\n\nexport const VideoView = ({\n style = {},\n videoTrack,\n objectFit = 'cover',\n zOrder,\n mirror,\n}: Props) => {\n const [elementInfo] = useState(() => {\n let info = new VideoViewElementInfo();\n info.id = videoTrack?.sid;\n info.something = videoTrack;\n return info;\n });\n\n const [mediaStream, setMediaStream] = useState(videoTrack?.mediaStream);\n useEffect(() => {\n setMediaStream(videoTrack?.mediaStream);\n if (videoTrack instanceof LocalVideoTrack) {\n const onRestarted = (track: Track | null) => {\n setMediaStream(track?.mediaStream);\n };\n videoTrack.on(TrackEvent.Restarted, onRestarted);\n\n return () => {\n videoTrack.off(TrackEvent.Restarted, onRestarted);\n };\n } else {\n return () => {};\n }\n }, [videoTrack]);\n\n useEffect(() => {\n if (videoTrack instanceof RemoteVideoTrack && videoTrack.isAdaptiveStream) {\n videoTrack?.observeElementInfo(elementInfo);\n return () => {\n videoTrack?.stopObservingElementInfo(elementInfo);\n };\n } else {\n return () => {};\n }\n }, [videoTrack, elementInfo]);\n\n return (\n <View\n style={{ ...style, ...styles.container }}\n onLayout={(event) => {\n elementInfo.onLayout(event);\n }}\n >\n <ViewPortDetector\n onChange={(isVisible: boolean) => elementInfo.onVisibility(isVisible)}\n style={styles.videoView}\n >\n <RTCView\n // eslint-disable-next-line react-native/no-inline-styles\n style={{\n flex: 1,\n width: '100%',\n }}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n />\n </ViewPortDetector>\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: {},\n videoView: {\n flex: 1,\n width: '100%',\n },\n});\n\nclass VideoViewElementInfo implements ElementInfo {\n element: object = {};\n something?: any;\n id?: string;\n _width = 0;\n _height = 0;\n _observing = false;\n visible: boolean = true;\n visibilityChangedAt: number | undefined;\n pictureInPicture = false;\n handleResize?: (() => void) | undefined;\n handleVisibilityChanged?: (() => void) | undefined;\n width = () => this._width;\n height = () => this._height;\n\n observe(): void {\n this._observing = true;\n }\n stopObserving(): void {\n this._observing = false;\n }\n\n onLayout(event: LayoutChangeEvent) {\n let { width, height } = event.nativeEvent.layout;\n this._width = width;\n this._height = height;\n\n if (this._observing) {\n this.handleResize?.();\n }\n }\n onVisibility(isVisible: boolean) {\n if (this.visible !== isVisible) {\n this.visible = isVisible;\n this.visibilityChangedAt = Date.now();\n if (this._observing) {\n this.handleVisibilityChanged?.();\n }\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["ViewPortDetector.tsx"],"names":["ViewPortDetector","Component","constructor","props","state","rectTop","rectBottom","componentDidMount","disabled","startWatching","componentWillUnmount","stopWatching","UNSAFE_componentWillReceiveProps","nextProps","lastValue","interval","setInterval","view","measure","_x","_y","width","height","_pageX","_pageY","checkInViewPort","delay","clearInterval","isVisible","onChange","render","component","children"],"mappings":"AAAA;;;;;;;AAEA;;AACA;;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACe,MAAMA,gBAAN,SAA+BC,gBAA/B,
|
|
1
|
+
{"version":3,"sources":["ViewPortDetector.tsx"],"names":["ViewPortDetector","Component","constructor","props","state","rectTop","rectBottom","componentDidMount","disabled","startWatching","componentWillUnmount","stopWatching","UNSAFE_componentWillReceiveProps","nextProps","lastValue","interval","setInterval","view","measure","_x","_y","width","height","_pageX","_pageY","checkInViewPort","delay","clearInterval","isVisible","onChange","render","component","children"],"mappings":"AAAA;;;;;;;AAEA;;AACA;;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACe,MAAMA,gBAAN,SAA+BC,gBAA/B,CAEb;AAKAC,EAAAA,WAAW,CAACC,KAAD,EAAe;AACxB,UAAMA,KAAN;;AADwB,uCAJU,IAIV;;AAAA,sCAHK,IAGL;;AAAA,kCAFE,IAEF;;AAExB,SAAKC,KAAL,GAAa;AAAEC,MAAAA,OAAO,EAAE,CAAX;AAAcC,MAAAA,UAAU,EAAE;AAA1B,KAAb;AACD;;AAEDC,EAAAA,iBAAiB,GAAG;AAClB,QAAI,CAAC,KAAKJ,KAAL,CAAWK,QAAhB,EAA0B;AACxB,WAAKC,aAAL;AACD;AACF;;AAEDC,EAAAA,oBAAoB,GAAG;AACrB,SAAKC,YAAL;AACD;;AAEDC,EAAAA,gCAAgC,CAACC,SAAD,EAAmB;AACjD,QAAIA,SAAS,CAACL,QAAd,EAAwB;AACtB,WAAKG,YAAL;AACD,KAFD,MAEO;AACL,WAAKG,SAAL,GAAiB,IAAjB;AACA,WAAKL,aAAL;AACD;AACF;;AAEOA,EAAAA,aAAa,GAAG;AACtB,QAAI,KAAKM,QAAT,EAAmB;AACjB;AACD;;AACD,SAAKA,QAAL,GAAgBC,WAAW,CAAC,MAAM;AAChC,UAAI,CAAC,KAAKC,IAAV,EAAgB;AACd;AACD;;AACD,WAAKA,IAAL,CAAUC,OAAV,CAAkB,CAACC,EAAD,EAAKC,EAAL,EAASC,KAAT,EAAgBC,MAAhB,EAAwBC,MAAxB,EAAgCC,MAAhC,KAA2C;AAC3D,aAAKC,eAAL,CAAqBJ,KAArB,EAA4BC,MAA5B;AACD,OAFD;AAGD,KAP0B,EAOxB,KAAKnB,KAAL,CAAWuB,KAAX,IAAoB,GAPI,CAA3B;AAQD;;AAEOf,EAAAA,YAAY,GAAG;AACrB,SAAKI,QAAL,GAAgBY,aAAa,CAAC,KAAKZ,QAAN,CAA7B;AACD;;AAEOU,EAAAA,eAAe,CAACJ,KAAD,EAAiBC,MAAjB,EAAkC;AACvD,QAAIM,SAAJ,CADuD,CAEvD;;AACA,QAAI,CAACP,KAAD,IAAU,CAACC,MAAf,EAAuB;AACrBM,MAAAA,SAAS,GAAG,KAAZ;AACD,KAFD,MAEO;AACLA,MAAAA,SAAS,GAAG,IAAZ;AACD;;AAED,QAAI,KAAKd,SAAL,KAAmBc,SAAvB,EAAkC;AAAA;;AAChC,WAAKd,SAAL,GAAiBc,SAAjB;AACA,kDAAKzB,KAAL,EAAW0B,QAAX,gGAAsBD,SAAtB;AACD;AACF;;AAEDE,EAAAA,MAAM,GAAG;AACP,wBACE,6BAAC,iBAAD;AACE,MAAA,WAAW,EAAE,KADf;AAEE,MAAA,GAAG,EAAGC,SAAD,IAAe;AAClB,aAAKd,IAAL,GAAYc,SAAZ;AACD;AAJH,OAKM,KAAK5B,KALX,GAOG,KAAKA,KAAL,CAAW6B,QAPd,CADF;AAWD;;AA1ED","sourcesContent":["'use strict';\n\nimport React, { Component, PropsWithChildren } from 'react';\nimport { View, ViewStyle } from 'react-native';\n\nexport type Props = {\n disabled?: boolean;\n style?: ViewStyle;\n onChange?: (isVisible: boolean) => void;\n delay?: number;\n};\n\n/**\n * Detects when this is in the viewport and visible.\n *\n * Will not fire visibility changes for zero width/height components.\n */\nexport default class ViewPortDetector extends Component<\n PropsWithChildren<Props>\n> {\n private lastValue: boolean | null = null;\n private interval: any | null = null;\n private view: View | null = null;\n\n constructor(props: Props) {\n super(props);\n this.state = { rectTop: 0, rectBottom: 0 };\n }\n\n componentDidMount() {\n if (!this.props.disabled) {\n this.startWatching();\n }\n }\n\n componentWillUnmount() {\n this.stopWatching();\n }\n\n UNSAFE_componentWillReceiveProps(nextProps: Props) {\n if (nextProps.disabled) {\n this.stopWatching();\n } else {\n this.lastValue = null;\n this.startWatching();\n }\n }\n\n private startWatching() {\n if (this.interval) {\n return;\n }\n this.interval = setInterval(() => {\n if (!this.view) {\n return;\n }\n this.view.measure((_x, _y, width, height, _pageX, _pageY) => {\n this.checkInViewPort(width, height);\n });\n }, this.props.delay || 100);\n }\n\n private stopWatching() {\n this.interval = clearInterval(this.interval);\n }\n\n private checkInViewPort(width?: number, height?: number) {\n let isVisible: boolean;\n // Not visible if any of these are missing.\n if (!width || !height) {\n isVisible = false;\n } else {\n isVisible = true;\n }\n\n if (this.lastValue !== isVisible) {\n this.lastValue = isVisible;\n this.props.onChange?.(isVisible);\n }\n }\n\n render() {\n return (\n <View\n collapsable={false}\n ref={(component) => {\n this.view = component;\n }}\n {...this.props}\n >\n {this.props.children}\n </View>\n );\n }\n}\n"]}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -15,7 +15,7 @@ Object.defineProperty(exports, "AudioSession", {
|
|
|
15
15
|
});
|
|
16
16
|
exports.registerGlobals = registerGlobals;
|
|
17
17
|
|
|
18
|
-
var _reactNativeWebrtc = require("react-native-webrtc");
|
|
18
|
+
var _reactNativeWebrtc = require("@livekit/react-native-webrtc");
|
|
19
19
|
|
|
20
20
|
var _reactNativeUrlPolyfill = require("react-native-url-polyfill");
|
|
21
21
|
|
|
@@ -78,6 +78,7 @@ function registerGlobals() {
|
|
|
78
78
|
(0, _reactNativeUrlPolyfill.setupURLPolyfill)();
|
|
79
79
|
fixWebrtcAdapter();
|
|
80
80
|
shimPromiseAllSettled();
|
|
81
|
+
shimArrayAt();
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
function livekitRegisterGlobals() {
|
|
@@ -112,4 +113,13 @@ function shimPromiseAllSettled() {
|
|
|
112
113
|
|
|
113
114
|
allSettled.shim();
|
|
114
115
|
}
|
|
116
|
+
|
|
117
|
+
function shimArrayAt() {
|
|
118
|
+
// Some versions of RN don't have Array.prototype.at, which is used by sdp-transform
|
|
119
|
+
if (!Array.prototype.at) {
|
|
120
|
+
var at = require('array.prototype.at');
|
|
121
|
+
|
|
122
|
+
at.shim();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
115
125
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["index.tsx"],"names":["registerGlobals","livekitRegisterGlobals","fixWebrtcAdapter","shimPromiseAllSettled","lkGlobal","platform","Platform","OS","devicePixelRatio","PixelRatio","get","global","LiveKitReactNativeGlobal","window","navigator","undefined","userAgent","product","allSettled","require","shim"],"mappings":";;;;;;;;;;;;;;;;;AAAA;;AACA;;AACA;;AAEA;;
|
|
1
|
+
{"version":3,"sources":["index.tsx"],"names":["registerGlobals","livekitRegisterGlobals","fixWebrtcAdapter","shimPromiseAllSettled","shimArrayAt","lkGlobal","platform","Platform","OS","devicePixelRatio","PixelRatio","get","global","LiveKitReactNativeGlobal","window","navigator","undefined","userAgent","product","allSettled","require","shim","Array","prototype","at"],"mappings":";;;;;;;;;;;;;;;;;AAAA;;AACA;;AACA;;AAEA;;AAkDA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;AAjDA;AACA;AACA;AACA;AACA;AACO,SAASA,eAAT,GAA2B;AAChC;AACAC,EAAAA,sBAAsB;AACtB;AACAC,EAAAA,gBAAgB;AAChBC,EAAAA,qBAAqB;AACrBC,EAAAA,WAAW;AACZ;;AACD,SAASH,sBAAT,GAAkC;AAChC,MAAII,QAAgC,GAAG;AACrCC,IAAAA,QAAQ,EAAEC,sBAASC,EADkB;AAErCC,IAAAA,gBAAgB,EAAEC,wBAAWC,GAAX;AAFmB,GAAvC,CADgC,CAMhC;;AACAC,EAAAA,MAAM,CAACC,wBAAP,GAAkCR,QAAlC;AACD;;AAED,SAASH,gBAAT,GAA4B;AAAA;;AAC1B;AACA,MAAI,YAAAY,MAAM,UAAN,0CAAQC,SAAR,MAAsBC,SAA1B,EAAqC;AACnC;AACA,UAAM;AAAED,MAAAA;AAAF,QAAgBD,MAAtB;;AACA,QAAIC,SAAS,CAACE,SAAV,KAAwBD,SAA5B,EAAuC;AAAA;;AACrCD,MAAAA,SAAS,CAACE,SAAV,yBAAsBF,SAAS,CAACG,OAAhC,mEAA2C,SAA3C;AACD;AACF;AACF;;AAED,SAASf,qBAAT,GAAiC;AAC/B,MAAIgB,UAAU,GAAGC,OAAO,CAAC,oBAAD,CAAxB;;AACAD,EAAAA,UAAU,CAACE,IAAX;AACD;;AAED,SAASjB,WAAT,GAAuB;AACrB;AACA,MAAI,CAACkB,KAAK,CAACC,SAAN,CAAgBC,EAArB,EAAyB;AACvB,QAAIA,EAAE,GAAGJ,OAAO,CAAC,oBAAD,CAAhB;;AACAI,IAAAA,EAAE,CAACH,IAAH;AACD;AACF","sourcesContent":["import { registerGlobals as webrtcRegisterGlobals } from '@livekit/react-native-webrtc';\nimport { setupURLPolyfill } from 'react-native-url-polyfill';\nimport AudioSession from './audio/AudioSession';\nimport type { AudioConfiguration } from './audio/AudioSession';\nimport { PixelRatio, Platform } from 'react-native';\nimport type { LiveKitReactNativeInfo } from 'livekit-client';\n\n/**\n * Registers the required globals needed for LiveKit to work.\n *\n * Must be called before using LiveKit.\n */\nexport function registerGlobals() {\n webrtcRegisterGlobals();\n livekitRegisterGlobals();\n setupURLPolyfill();\n fixWebrtcAdapter();\n shimPromiseAllSettled();\n shimArrayAt();\n}\nfunction livekitRegisterGlobals() {\n let lkGlobal: LiveKitReactNativeInfo = {\n platform: Platform.OS,\n devicePixelRatio: PixelRatio.get(),\n };\n\n // @ts-ignore\n global.LiveKitReactNativeGlobal = lkGlobal;\n}\n\nfunction fixWebrtcAdapter() {\n // @ts-ignore\n if (window?.navigator !== undefined) {\n // @ts-ignore\n const { navigator } = window;\n if (navigator.userAgent === undefined) {\n navigator.userAgent = navigator.product ?? 'Unknown';\n }\n }\n}\n\nfunction shimPromiseAllSettled() {\n var allSettled = require('promise.allsettled');\n allSettled.shim();\n}\n\nfunction shimArrayAt() {\n // Some versions of RN don't have Array.prototype.at, which is used by sdp-transform\n if (!Array.prototype.at) {\n var at = require('array.prototype.at');\n at.shim();\n }\n}\n\nexport * from './components/VideoView';\nexport * from './useParticipant';\nexport * from './useRoom';\nexport { AudioSession, AudioConfiguration };\n"]}
|
|
@@ -3,7 +3,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { StyleSheet, View } from 'react-native';
|
|
5
5
|
import { LocalVideoTrack, TrackEvent } from 'livekit-client';
|
|
6
|
-
import { RTCView } from 'react-native-webrtc';
|
|
6
|
+
import { RTCView } from '@livekit/react-native-webrtc';
|
|
7
7
|
import { useEffect, useState } from 'react';
|
|
8
8
|
import { RemoteVideoTrack } from 'livekit-client';
|
|
9
9
|
import ViewPortDetector from './ViewPortDetector';
|
|
@@ -60,8 +60,12 @@ export const VideoView = _ref => {
|
|
|
60
60
|
}, /*#__PURE__*/React.createElement(ViewPortDetector, {
|
|
61
61
|
onChange: isVisible => elementInfo.onVisibility(isVisible),
|
|
62
62
|
style: styles.videoView
|
|
63
|
-
}, /*#__PURE__*/React.createElement(RTCView
|
|
64
|
-
|
|
63
|
+
}, /*#__PURE__*/React.createElement(RTCView // eslint-disable-next-line react-native/no-inline-styles
|
|
64
|
+
, {
|
|
65
|
+
style: {
|
|
66
|
+
flex: 1,
|
|
67
|
+
width: '100%'
|
|
68
|
+
},
|
|
65
69
|
streamURL: (_mediaStream$toURL = mediaStream === null || mediaStream === void 0 ? void 0 : mediaStream.toURL()) !== null && _mediaStream$toURL !== void 0 ? _mediaStream$toURL : '',
|
|
66
70
|
objectFit: objectFit,
|
|
67
71
|
zOrder: zOrder,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["VideoView.tsx"],"names":["React","StyleSheet","View","LocalVideoTrack","TrackEvent","RTCView","useEffect","useState","RemoteVideoTrack","ViewPortDetector","VideoView","style","videoTrack","objectFit","zOrder","mirror","elementInfo","info","VideoViewElementInfo","id","sid","something","mediaStream","setMediaStream","onRestarted","track","on","Restarted","off","isAdaptiveStream","observeElementInfo","stopObservingElementInfo","styles","container","event","onLayout","isVisible","onVisibility","videoView","
|
|
1
|
+
{"version":3,"sources":["VideoView.tsx"],"names":["React","StyleSheet","View","LocalVideoTrack","TrackEvent","RTCView","useEffect","useState","RemoteVideoTrack","ViewPortDetector","VideoView","style","videoTrack","objectFit","zOrder","mirror","elementInfo","info","VideoViewElementInfo","id","sid","something","mediaStream","setMediaStream","onRestarted","track","on","Restarted","off","isAdaptiveStream","observeElementInfo","stopObservingElementInfo","styles","container","event","onLayout","isVisible","onVisibility","videoView","flex","width","toURL","create","_width","_height","observe","_observing","stopObserving","height","nativeEvent","layout","handleResize","visible","visibilityChangedAt","Date","now","handleVisibilityChanged"],"mappings":"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","sourcesContent":["import * as React from 'react';\n\nimport { LayoutChangeEvent, StyleSheet, View, ViewStyle } from 'react-native';\nimport {\n ElementInfo,\n LocalVideoTrack,\n Track,\n TrackEvent,\n VideoTrack,\n} from 'livekit-client';\nimport { RTCView } from '@livekit/react-native-webrtc';\nimport { useEffect, useState } from 'react';\nimport { RemoteVideoTrack } from 'livekit-client';\nimport ViewPortDetector from './ViewPortDetector';\n\nexport type Props = {\n videoTrack?: VideoTrack | undefined;\n style?: ViewStyle;\n objectFit?: 'cover' | 'contain' | undefined;\n mirror?: boolean;\n zOrder?: number;\n};\n\nexport const VideoView = ({\n style = {},\n videoTrack,\n objectFit = 'cover',\n zOrder,\n mirror,\n}: Props) => {\n const [elementInfo] = useState(() => {\n let info = new VideoViewElementInfo();\n info.id = videoTrack?.sid;\n info.something = videoTrack;\n return info;\n });\n\n const [mediaStream, setMediaStream] = useState(videoTrack?.mediaStream);\n useEffect(() => {\n setMediaStream(videoTrack?.mediaStream);\n if (videoTrack instanceof LocalVideoTrack) {\n const onRestarted = (track: Track | null) => {\n setMediaStream(track?.mediaStream);\n };\n videoTrack.on(TrackEvent.Restarted, onRestarted);\n\n return () => {\n videoTrack.off(TrackEvent.Restarted, onRestarted);\n };\n } else {\n return () => {};\n }\n }, [videoTrack]);\n\n useEffect(() => {\n if (videoTrack instanceof RemoteVideoTrack && videoTrack.isAdaptiveStream) {\n videoTrack?.observeElementInfo(elementInfo);\n return () => {\n videoTrack?.stopObservingElementInfo(elementInfo);\n };\n } else {\n return () => {};\n }\n }, [videoTrack, elementInfo]);\n\n return (\n <View\n style={{ ...style, ...styles.container }}\n onLayout={(event) => {\n elementInfo.onLayout(event);\n }}\n >\n <ViewPortDetector\n onChange={(isVisible: boolean) => elementInfo.onVisibility(isVisible)}\n style={styles.videoView}\n >\n <RTCView\n // eslint-disable-next-line react-native/no-inline-styles\n style={{\n flex: 1,\n width: '100%',\n }}\n streamURL={mediaStream?.toURL() ?? ''}\n objectFit={objectFit}\n zOrder={zOrder}\n mirror={mirror}\n />\n </ViewPortDetector>\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: {},\n videoView: {\n flex: 1,\n width: '100%',\n },\n});\n\nclass VideoViewElementInfo implements ElementInfo {\n element: object = {};\n something?: any;\n id?: string;\n _width = 0;\n _height = 0;\n _observing = false;\n visible: boolean = true;\n visibilityChangedAt: number | undefined;\n pictureInPicture = false;\n handleResize?: (() => void) | undefined;\n handleVisibilityChanged?: (() => void) | undefined;\n width = () => this._width;\n height = () => this._height;\n\n observe(): void {\n this._observing = true;\n }\n stopObserving(): void {\n this._observing = false;\n }\n\n onLayout(event: LayoutChangeEvent) {\n let { width, height } = event.nativeEvent.layout;\n this._width = width;\n this._height = height;\n\n if (this._observing) {\n this.handleResize?.();\n }\n }\n onVisibility(isVisible: boolean) {\n if (this.visible !== isVisible) {\n this.visible = isVisible;\n this.visibilityChangedAt = Date.now();\n if (this._observing) {\n this.handleVisibilityChanged?.();\n }\n }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["ViewPortDetector.tsx"],"names":["React","Component","View","ViewPortDetector","constructor","props","state","rectTop","rectBottom","componentDidMount","disabled","startWatching","componentWillUnmount","stopWatching","UNSAFE_componentWillReceiveProps","nextProps","lastValue","interval","setInterval","view","measure","_x","_y","width","height","_pageX","_pageY","checkInViewPort","delay","clearInterval","isVisible","onChange","render","component","children"],"mappings":"AAAA;;;;;;AAEA,OAAOA,KAAP,IAAgBC,SAAhB,
|
|
1
|
+
{"version":3,"sources":["ViewPortDetector.tsx"],"names":["React","Component","View","ViewPortDetector","constructor","props","state","rectTop","rectBottom","componentDidMount","disabled","startWatching","componentWillUnmount","stopWatching","UNSAFE_componentWillReceiveProps","nextProps","lastValue","interval","setInterval","view","measure","_x","_y","width","height","_pageX","_pageY","checkInViewPort","delay","clearInterval","isVisible","onChange","render","component","children"],"mappings":"AAAA;;;;;;AAEA,OAAOA,KAAP,IAAgBC,SAAhB,QAAoD,OAApD;AACA,SAASC,IAAT,QAAgC,cAAhC;;AASA;AACA;AACA;AACA;AACA;AACA,eAAe,MAAMC,gBAAN,SAA+BF,SAA/B,CAEb;AAKAG,EAAAA,WAAW,CAACC,KAAD,EAAe;AACxB,UAAMA,KAAN;;AADwB,uCAJU,IAIV;;AAAA,sCAHK,IAGL;;AAAA,kCAFE,IAEF;;AAExB,SAAKC,KAAL,GAAa;AAAEC,MAAAA,OAAO,EAAE,CAAX;AAAcC,MAAAA,UAAU,EAAE;AAA1B,KAAb;AACD;;AAEDC,EAAAA,iBAAiB,GAAG;AAClB,QAAI,CAAC,KAAKJ,KAAL,CAAWK,QAAhB,EAA0B;AACxB,WAAKC,aAAL;AACD;AACF;;AAEDC,EAAAA,oBAAoB,GAAG;AACrB,SAAKC,YAAL;AACD;;AAEDC,EAAAA,gCAAgC,CAACC,SAAD,EAAmB;AACjD,QAAIA,SAAS,CAACL,QAAd,EAAwB;AACtB,WAAKG,YAAL;AACD,KAFD,MAEO;AACL,WAAKG,SAAL,GAAiB,IAAjB;AACA,WAAKL,aAAL;AACD;AACF;;AAEOA,EAAAA,aAAa,GAAG;AACtB,QAAI,KAAKM,QAAT,EAAmB;AACjB;AACD;;AACD,SAAKA,QAAL,GAAgBC,WAAW,CAAC,MAAM;AAChC,UAAI,CAAC,KAAKC,IAAV,EAAgB;AACd;AACD;;AACD,WAAKA,IAAL,CAAUC,OAAV,CAAkB,CAACC,EAAD,EAAKC,EAAL,EAASC,KAAT,EAAgBC,MAAhB,EAAwBC,MAAxB,EAAgCC,MAAhC,KAA2C;AAC3D,aAAKC,eAAL,CAAqBJ,KAArB,EAA4BC,MAA5B;AACD,OAFD;AAGD,KAP0B,EAOxB,KAAKnB,KAAL,CAAWuB,KAAX,IAAoB,GAPI,CAA3B;AAQD;;AAEOf,EAAAA,YAAY,GAAG;AACrB,SAAKI,QAAL,GAAgBY,aAAa,CAAC,KAAKZ,QAAN,CAA7B;AACD;;AAEOU,EAAAA,eAAe,CAACJ,KAAD,EAAiBC,MAAjB,EAAkC;AACvD,QAAIM,SAAJ,CADuD,CAEvD;;AACA,QAAI,CAACP,KAAD,IAAU,CAACC,MAAf,EAAuB;AACrBM,MAAAA,SAAS,GAAG,KAAZ;AACD,KAFD,MAEO;AACLA,MAAAA,SAAS,GAAG,IAAZ;AACD;;AAED,QAAI,KAAKd,SAAL,KAAmBc,SAAvB,EAAkC;AAAA;;AAChC,WAAKd,SAAL,GAAiBc,SAAjB;AACA,kDAAKzB,KAAL,EAAW0B,QAAX,gGAAsBD,SAAtB;AACD;AACF;;AAEDE,EAAAA,MAAM,GAAG;AACP,wBACE,oBAAC,IAAD;AACE,MAAA,WAAW,EAAE,KADf;AAEE,MAAA,GAAG,EAAGC,SAAD,IAAe;AAClB,aAAKd,IAAL,GAAYc,SAAZ;AACD;AAJH,OAKM,KAAK5B,KALX,GAOG,KAAKA,KAAL,CAAW6B,QAPd,CADF;AAWD;;AA1ED","sourcesContent":["'use strict';\n\nimport React, { Component, PropsWithChildren } from 'react';\nimport { View, ViewStyle } from 'react-native';\n\nexport type Props = {\n disabled?: boolean;\n style?: ViewStyle;\n onChange?: (isVisible: boolean) => void;\n delay?: number;\n};\n\n/**\n * Detects when this is in the viewport and visible.\n *\n * Will not fire visibility changes for zero width/height components.\n */\nexport default class ViewPortDetector extends Component<\n PropsWithChildren<Props>\n> {\n private lastValue: boolean | null = null;\n private interval: any | null = null;\n private view: View | null = null;\n\n constructor(props: Props) {\n super(props);\n this.state = { rectTop: 0, rectBottom: 0 };\n }\n\n componentDidMount() {\n if (!this.props.disabled) {\n this.startWatching();\n }\n }\n\n componentWillUnmount() {\n this.stopWatching();\n }\n\n UNSAFE_componentWillReceiveProps(nextProps: Props) {\n if (nextProps.disabled) {\n this.stopWatching();\n } else {\n this.lastValue = null;\n this.startWatching();\n }\n }\n\n private startWatching() {\n if (this.interval) {\n return;\n }\n this.interval = setInterval(() => {\n if (!this.view) {\n return;\n }\n this.view.measure((_x, _y, width, height, _pageX, _pageY) => {\n this.checkInViewPort(width, height);\n });\n }, this.props.delay || 100);\n }\n\n private stopWatching() {\n this.interval = clearInterval(this.interval);\n }\n\n private checkInViewPort(width?: number, height?: number) {\n let isVisible: boolean;\n // Not visible if any of these are missing.\n if (!width || !height) {\n isVisible = false;\n } else {\n isVisible = true;\n }\n\n if (this.lastValue !== isVisible) {\n this.lastValue = isVisible;\n this.props.onChange?.(isVisible);\n }\n }\n\n render() {\n return (\n <View\n collapsable={false}\n ref={(component) => {\n this.view = component;\n }}\n {...this.props}\n >\n {this.props.children}\n </View>\n );\n }\n}\n"]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { registerGlobals as webrtcRegisterGlobals } from 'react-native-webrtc';
|
|
1
|
+
import { registerGlobals as webrtcRegisterGlobals } from '@livekit/react-native-webrtc';
|
|
2
2
|
import { setupURLPolyfill } from 'react-native-url-polyfill';
|
|
3
3
|
import AudioSession from './audio/AudioSession';
|
|
4
4
|
import { PixelRatio, Platform } from 'react-native';
|
|
@@ -14,6 +14,7 @@ export function registerGlobals() {
|
|
|
14
14
|
setupURLPolyfill();
|
|
15
15
|
fixWebrtcAdapter();
|
|
16
16
|
shimPromiseAllSettled();
|
|
17
|
+
shimArrayAt();
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
function livekitRegisterGlobals() {
|
|
@@ -49,6 +50,15 @@ function shimPromiseAllSettled() {
|
|
|
49
50
|
allSettled.shim();
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
function shimArrayAt() {
|
|
54
|
+
// Some versions of RN don't have Array.prototype.at, which is used by sdp-transform
|
|
55
|
+
if (!Array.prototype.at) {
|
|
56
|
+
var at = require('array.prototype.at');
|
|
57
|
+
|
|
58
|
+
at.shim();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
52
62
|
export * from './components/VideoView';
|
|
53
63
|
export * from './useParticipant';
|
|
54
64
|
export * from './useRoom';
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["index.tsx"],"names":["registerGlobals","webrtcRegisterGlobals","setupURLPolyfill","AudioSession","PixelRatio","Platform","livekitRegisterGlobals","fixWebrtcAdapter","shimPromiseAllSettled","lkGlobal","platform","OS","devicePixelRatio","get","global","LiveKitReactNativeGlobal","window","navigator","undefined","userAgent","product","allSettled","require","shim"],"mappings":"AAAA,SAASA,eAAe,IAAIC,qBAA5B,QAAyD,
|
|
1
|
+
{"version":3,"sources":["index.tsx"],"names":["registerGlobals","webrtcRegisterGlobals","setupURLPolyfill","AudioSession","PixelRatio","Platform","livekitRegisterGlobals","fixWebrtcAdapter","shimPromiseAllSettled","shimArrayAt","lkGlobal","platform","OS","devicePixelRatio","get","global","LiveKitReactNativeGlobal","window","navigator","undefined","userAgent","product","allSettled","require","shim","Array","prototype","at"],"mappings":"AAAA,SAASA,eAAe,IAAIC,qBAA5B,QAAyD,8BAAzD;AACA,SAASC,gBAAT,QAAiC,2BAAjC;AACA,OAAOC,YAAP,MAAyB,sBAAzB;AAEA,SAASC,UAAT,EAAqBC,QAArB,QAAqC,cAArC;;AAGA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASL,eAAT,GAA2B;AAChCC,EAAAA,qBAAqB;AACrBK,EAAAA,sBAAsB;AACtBJ,EAAAA,gBAAgB;AAChBK,EAAAA,gBAAgB;AAChBC,EAAAA,qBAAqB;AACrBC,EAAAA,WAAW;AACZ;;AACD,SAASH,sBAAT,GAAkC;AAChC,MAAII,QAAgC,GAAG;AACrCC,IAAAA,QAAQ,EAAEN,QAAQ,CAACO,EADkB;AAErCC,IAAAA,gBAAgB,EAAET,UAAU,CAACU,GAAX;AAFmB,GAAvC,CADgC,CAMhC;;AACAC,EAAAA,MAAM,CAACC,wBAAP,GAAkCN,QAAlC;AACD;;AAED,SAASH,gBAAT,GAA4B;AAAA;;AAC1B;AACA,MAAI,YAAAU,MAAM,UAAN,0CAAQC,SAAR,MAAsBC,SAA1B,EAAqC;AACnC;AACA,UAAM;AAAED,MAAAA;AAAF,QAAgBD,MAAtB;;AACA,QAAIC,SAAS,CAACE,SAAV,KAAwBD,SAA5B,EAAuC;AAAA;;AACrCD,MAAAA,SAAS,CAACE,SAAV,yBAAsBF,SAAS,CAACG,OAAhC,mEAA2C,SAA3C;AACD;AACF;AACF;;AAED,SAASb,qBAAT,GAAiC;AAC/B,MAAIc,UAAU,GAAGC,OAAO,CAAC,oBAAD,CAAxB;;AACAD,EAAAA,UAAU,CAACE,IAAX;AACD;;AAED,SAASf,WAAT,GAAuB;AACrB;AACA,MAAI,CAACgB,KAAK,CAACC,SAAN,CAAgBC,EAArB,EAAyB;AACvB,QAAIA,EAAE,GAAGJ,OAAO,CAAC,oBAAD,CAAhB;;AACAI,IAAAA,EAAE,CAACH,IAAH;AACD;AACF;;AAED,cAAc,wBAAd;AACA,cAAc,kBAAd;AACA,cAAc,WAAd;AACA,SAASrB,YAAT","sourcesContent":["import { registerGlobals as webrtcRegisterGlobals } from '@livekit/react-native-webrtc';\nimport { setupURLPolyfill } from 'react-native-url-polyfill';\nimport AudioSession from './audio/AudioSession';\nimport type { AudioConfiguration } from './audio/AudioSession';\nimport { PixelRatio, Platform } from 'react-native';\nimport type { LiveKitReactNativeInfo } from 'livekit-client';\n\n/**\n * Registers the required globals needed for LiveKit to work.\n *\n * Must be called before using LiveKit.\n */\nexport function registerGlobals() {\n webrtcRegisterGlobals();\n livekitRegisterGlobals();\n setupURLPolyfill();\n fixWebrtcAdapter();\n shimPromiseAllSettled();\n shimArrayAt();\n}\nfunction livekitRegisterGlobals() {\n let lkGlobal: LiveKitReactNativeInfo = {\n platform: Platform.OS,\n devicePixelRatio: PixelRatio.get(),\n };\n\n // @ts-ignore\n global.LiveKitReactNativeGlobal = lkGlobal;\n}\n\nfunction fixWebrtcAdapter() {\n // @ts-ignore\n if (window?.navigator !== undefined) {\n // @ts-ignore\n const { navigator } = window;\n if (navigator.userAgent === undefined) {\n navigator.userAgent = navigator.product ?? 'Unknown';\n }\n }\n}\n\nfunction shimPromiseAllSettled() {\n var allSettled = require('promise.allsettled');\n allSettled.shim();\n}\n\nfunction shimArrayAt() {\n // Some versions of RN don't have Array.prototype.at, which is used by sdp-transform\n if (!Array.prototype.at) {\n var at = require('array.prototype.at');\n at.shim();\n }\n}\n\nexport * from './components/VideoView';\nexport * from './useParticipant';\nexport * from './useRoom';\nexport { AudioSession, AudioConfiguration };\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
1
2
|
import { ViewStyle } from 'react-native';
|
|
2
3
|
import { VideoTrack } from 'livekit-client';
|
|
3
4
|
export declare type Props = {
|
|
@@ -7,4 +8,4 @@ export declare type Props = {
|
|
|
7
8
|
mirror?: boolean;
|
|
8
9
|
zOrder?: number;
|
|
9
10
|
};
|
|
10
|
-
export declare const VideoView: ({ style, videoTrack, objectFit, zOrder, mirror, }: Props) => JSX.Element;
|
|
11
|
+
export declare const VideoView: ({ style, videoTrack, objectFit, zOrder, mirror, }: Props) => React.JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component } from 'react';
|
|
1
|
+
import React, { Component, PropsWithChildren } from 'react';
|
|
2
2
|
import { ViewStyle } from 'react-native';
|
|
3
3
|
export declare type Props = {
|
|
4
4
|
disabled?: boolean;
|
|
@@ -11,7 +11,7 @@ export declare type Props = {
|
|
|
11
11
|
*
|
|
12
12
|
* Will not fire visibility changes for zero width/height components.
|
|
13
13
|
*/
|
|
14
|
-
export default class ViewPortDetector extends Component<Props
|
|
14
|
+
export default class ViewPortDetector extends Component<PropsWithChildren<Props>> {
|
|
15
15
|
private lastValue;
|
|
16
16
|
private interval;
|
|
17
17
|
private view;
|
|
@@ -22,5 +22,5 @@ export default class ViewPortDetector extends Component<Props> {
|
|
|
22
22
|
private startWatching;
|
|
23
23
|
private stopWatching;
|
|
24
24
|
private checkInViewPort;
|
|
25
|
-
render(): JSX.Element;
|
|
25
|
+
render(): React.JSX.Element;
|
|
26
26
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livekit/react-native",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "LiveKit for React Native",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -39,27 +39,30 @@
|
|
|
39
39
|
"android"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
+
"array.prototype.at": "^1.1.1",
|
|
42
43
|
"livekit-client": "^1.8.0",
|
|
43
44
|
"promise.allsettled": "^1.0.5",
|
|
44
45
|
"react-native-url-polyfill": "^1.3.0"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@babel/core": "^7.
|
|
48
|
-
"@babel/preset-env": "^7.
|
|
49
|
-
"@babel/runtime": "^7.
|
|
48
|
+
"@babel/core": "^7.20.0",
|
|
49
|
+
"@babel/preset-env": "^7.20.0",
|
|
50
|
+
"@babel/runtime": "^7.20.0",
|
|
50
51
|
"@commitlint/config-conventional": "^16.2.1",
|
|
51
|
-
"@react-native-
|
|
52
|
+
"@livekit/react-native-webrtc": "^104.0.0-beta.0",
|
|
53
|
+
"@react-native-community/eslint-config": "^3.2.0",
|
|
52
54
|
"@release-it/conventional-changelog": "^4.2.0",
|
|
53
|
-
"@
|
|
54
|
-
"@types/
|
|
55
|
-
"@types/react
|
|
56
|
-
"@types/react-native
|
|
55
|
+
"@tsconfig/react-native": "^2.0.2",
|
|
56
|
+
"@types/jest": "^29.2.1",
|
|
57
|
+
"@types/react": "^18.0.24",
|
|
58
|
+
"@types/react-native": "^0.71.3",
|
|
57
59
|
"commitlint": "^16.2.1",
|
|
58
60
|
"eslint": "^8.23.0",
|
|
59
61
|
"eslint-config-prettier": "^8.5.0",
|
|
62
|
+
"eslint-plugin-ft-flow": "^2.0.3",
|
|
60
63
|
"eslint-plugin-prettier": "^4.2.1",
|
|
61
64
|
"husky": "^7.0.4",
|
|
62
|
-
"jest": "^
|
|
65
|
+
"jest": "^29.2.1",
|
|
63
66
|
"pod-install": "^0.1.0",
|
|
64
67
|
"prettier": "^2.5.1",
|
|
65
68
|
"react": "18.0.0",
|
|
@@ -67,12 +70,12 @@
|
|
|
67
70
|
"react-native-builder-bob": "^0.18.2",
|
|
68
71
|
"release-it": "^14.2.2",
|
|
69
72
|
"typedoc": "^0.23.14",
|
|
70
|
-
"typescript": "
|
|
73
|
+
"typescript": "4.8.4"
|
|
71
74
|
},
|
|
72
75
|
"peerDependencies": {
|
|
73
76
|
"react": "*",
|
|
74
77
|
"react-native": "*",
|
|
75
|
-
"react-native-webrtc": "^
|
|
78
|
+
"@livekit/react-native-webrtc": "^104.0.0"
|
|
76
79
|
},
|
|
77
80
|
"scripts": {
|
|
78
81
|
"test": "jest",
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
TrackEvent,
|
|
9
9
|
VideoTrack,
|
|
10
10
|
} from 'livekit-client';
|
|
11
|
-
import { RTCView } from 'react-native-webrtc';
|
|
11
|
+
import { RTCView } from '@livekit/react-native-webrtc';
|
|
12
12
|
import { useEffect, useState } from 'react';
|
|
13
13
|
import { RemoteVideoTrack } from 'livekit-client';
|
|
14
14
|
import ViewPortDetector from './ViewPortDetector';
|
|
@@ -75,7 +75,11 @@ export const VideoView = ({
|
|
|
75
75
|
style={styles.videoView}
|
|
76
76
|
>
|
|
77
77
|
<RTCView
|
|
78
|
-
|
|
78
|
+
// eslint-disable-next-line react-native/no-inline-styles
|
|
79
|
+
style={{
|
|
80
|
+
flex: 1,
|
|
81
|
+
width: '100%',
|
|
82
|
+
}}
|
|
79
83
|
streamURL={mediaStream?.toURL() ?? ''}
|
|
80
84
|
objectFit={objectFit}
|
|
81
85
|
zOrder={zOrder}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
import React, { Component } from 'react';
|
|
3
|
+
import React, { Component, PropsWithChildren } from 'react';
|
|
4
4
|
import { View, ViewStyle } from 'react-native';
|
|
5
5
|
|
|
6
6
|
export type Props = {
|
|
@@ -15,7 +15,9 @@ export type Props = {
|
|
|
15
15
|
*
|
|
16
16
|
* Will not fire visibility changes for zero width/height components.
|
|
17
17
|
*/
|
|
18
|
-
export default class ViewPortDetector extends Component<
|
|
18
|
+
export default class ViewPortDetector extends Component<
|
|
19
|
+
PropsWithChildren<Props>
|
|
20
|
+
> {
|
|
19
21
|
private lastValue: boolean | null = null;
|
|
20
22
|
private interval: any | null = null;
|
|
21
23
|
private view: View | null = null;
|
package/src/index.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { registerGlobals as webrtcRegisterGlobals } from 'react-native-webrtc';
|
|
1
|
+
import { registerGlobals as webrtcRegisterGlobals } from '@livekit/react-native-webrtc';
|
|
2
2
|
import { setupURLPolyfill } from 'react-native-url-polyfill';
|
|
3
3
|
import AudioSession from './audio/AudioSession';
|
|
4
4
|
import type { AudioConfiguration } from './audio/AudioSession';
|
|
@@ -16,6 +16,7 @@ export function registerGlobals() {
|
|
|
16
16
|
setupURLPolyfill();
|
|
17
17
|
fixWebrtcAdapter();
|
|
18
18
|
shimPromiseAllSettled();
|
|
19
|
+
shimArrayAt();
|
|
19
20
|
}
|
|
20
21
|
function livekitRegisterGlobals() {
|
|
21
22
|
let lkGlobal: LiveKitReactNativeInfo = {
|
|
@@ -43,6 +44,14 @@ function shimPromiseAllSettled() {
|
|
|
43
44
|
allSettled.shim();
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
function shimArrayAt() {
|
|
48
|
+
// Some versions of RN don't have Array.prototype.at, which is used by sdp-transform
|
|
49
|
+
if (!Array.prototype.at) {
|
|
50
|
+
var at = require('array.prototype.at');
|
|
51
|
+
at.shim();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
46
55
|
export * from './components/VideoView';
|
|
47
56
|
export * from './useParticipant';
|
|
48
57
|
export * from './useRoom';
|