mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-01-06 23:02:28 +00:00
Compare commits
30 Commits
android-sd
...
android-sd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b768b88491 | ||
|
|
9f339c452b | ||
|
|
c34f9cf233 | ||
|
|
76642b7c4b | ||
|
|
b78989f5f2 | ||
|
|
088b5d95c2 | ||
|
|
c6e5adbe0e | ||
|
|
8bb56be317 | ||
|
|
84b917d708 | ||
|
|
18d908ce84 | ||
|
|
3987655f2a | ||
|
|
ee3b8af4cf | ||
|
|
9625be1db3 | ||
|
|
21c0745504 | ||
|
|
26c9ee5f9c | ||
|
|
9b7af64e11 | ||
|
|
f26c5570df | ||
|
|
d37a0eee3a | ||
|
|
024fc73e63 | ||
|
|
bdaabf6d3d | ||
|
|
7a677ead93 | ||
|
|
e7812c7d84 | ||
|
|
ea54713f9a | ||
|
|
5a99697ae2 | ||
|
|
ec09085a50 | ||
|
|
b731459ea4 | ||
|
|
f73d3a4063 | ||
|
|
4c3cf8c14a | ||
|
|
1f371ab055 | ||
|
|
dfeb26597b |
@@ -2,7 +2,9 @@
|
||||
|
||||
## Build your own, or use a pre-build SDK artifacts/binaries
|
||||
|
||||
Jitsi conveniently provides a pre-build SDK artifacts/binaries in its Maven repository. When you do not require any modification to the SDK itself, it's suggested to use the pre-build SDK. This avoids the complexity of building and installing your own SDK artifacts/binaries.
|
||||
Jitsi conveniently provides a pre-build SDK artifacts/binaries in its Maven repository. When you do not require any
|
||||
modification to the SDK itself or any of its dependencies, it's suggested to use the pre-build SDK. This avoids the
|
||||
complexity of building and installing your own SDK artifacts/binaries.
|
||||
|
||||
### Use pre-build SDK artifacts/binaries
|
||||
|
||||
@@ -29,7 +31,7 @@ Dependency definitions belong in the individual module `build.gradle` files:
|
||||
```gradle
|
||||
dependencies {
|
||||
// (other dependencies)
|
||||
implementation ('org.jitsi.react:jitsi-meet-sdk:+') { transitive = true }
|
||||
implementation ('org.jitsi.react:jitsi-meet-sdk:2.+') { transitive = true }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -44,49 +46,20 @@ A note on dependencies: Apart from the SDK, Jitsi also publishes a binary Maven
|
||||
|
||||
If you want to use a SDK that is built from source, you will likely benefit from composing a local Maven repository that contains these dependencies. The text below describes how you create a repository that includes both the SDK as well as these dependencies. For illustration purposes, we'll define the location of this local Maven repository as `/tmp/repo`
|
||||
|
||||
In source code form, the Android SDK dependencies are locked/pinned by package.json and package-lock.json of the Jitsi Meet project. To obtain the data, execute NPM in the parent directory:
|
||||
In source code form, the Android SDK dependencies are locked/pinned by package.json and package-lock.json of the Jitsi Meet project. To obtain the data, execute NPM in the jitsi-meet project directory:
|
||||
|
||||
$ (cd ..; npm install)
|
||||
npm install
|
||||
|
||||
This will pull in the dependencies in either binary format, or in source code format, somewhere under /node_modules/
|
||||
|
||||
At the time of writing, there are two packages pulled in in binary format.
|
||||
Third-party React Native _modules_, which Jitsi Meet SDK for Android depends on, are download by NPM in source code
|
||||
or binary form. These need to be assembled into Maven artifacts, and then published to your local Maven repository.
|
||||
A script is provided to facilitate this. From the root of the jitsi-meet project repository, run:
|
||||
|
||||
To copy React Native to your local Maven repository, you can simply copy part of the directory structure that was pulled in by NPM:
|
||||
./android/scripts/release-sdk.sh /tmp/repo
|
||||
|
||||
$ cp -r ../node_modules/react-native/android/com /tmp/repo/
|
||||
|
||||
Alternatively, you can use the scripts located in the android/scripts directory to publish these dependencies to your Maven repo.
|
||||
|
||||
Third-party React Native _modules_, which Jitsi Meet SDK for Android depends on, are download by NPM in source code form. These need to be assembled into Maven artifacts, and then published to your local Maven repository. The SDK project facilitates this.
|
||||
|
||||
To prepare, Configure the Maven repositories in which you are going to publish the SDK artifacts/binaries. In `android/sdk/build.gradle` as well as in `android/build.gradle` modify the lines that contain:
|
||||
|
||||
"file:${rootProject.projectDir}/../../jitsi-maven-repository/releases"
|
||||
|
||||
Change this value (which represents the Maven repository location used internally by the Jitsi Developers) to the location of the repository that you'd like to use:
|
||||
|
||||
"file:/tmp/repo"
|
||||
|
||||
Make sure to do this in both files! Each file should require one line to be changed.
|
||||
|
||||
To prevent artifacts from previous builds affecting you're outcome, it's good to start with cleaning your work directories:
|
||||
|
||||
$ ./gradlew clean
|
||||
|
||||
To create the release assembly for any _specific_ third-party React Native module that you need, you can execture the following commands, replace the module name in the examples below.
|
||||
|
||||
$ ./gradlew :react-native-webrtc:assembleRelease
|
||||
$ ./gradlew :react-native-webrtc:publish
|
||||
|
||||
You build and publish the SDK itself in the same way:
|
||||
|
||||
$ ./gradlew :sdk:assembleRelease
|
||||
$ ./gradlew :sdk:publish
|
||||
|
||||
Alternatively, you can assemble and publish _all_ subprojects, which include the react-native modules, but also the SDK itself, with a single command:
|
||||
|
||||
$ ./gradlew clean assembleRelease publish
|
||||
This will build and publish the SDK, and all of its dependencies to the specified Maven repository (`/tmp/repo`) in
|
||||
this example.
|
||||
|
||||
You're now ready to use the artifacts. In _your_ project, add the Maven repository that you used above (`/tmp/repo`) into your top-level `build.gradle` file:
|
||||
|
||||
@@ -104,7 +77,8 @@ Then, define the dependency `org.jitsi.react:jitsi-meet-sdk` into the `build.gra
|
||||
|
||||
implementation ('org.jitsi.react:jitsi-meet-sdk:+') { transitive = true }
|
||||
|
||||
Note that there should not be a need to explicitly add the other dependencies, as they will be pulled in as transitive dependencies of `jitsi-meet-sdk`.
|
||||
Note that there should not be a need to explicitly add the other dependencies, as they will be pulled in as transitive
|
||||
dependencies of `jitsi-meet-sdk`.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -55,45 +55,33 @@ allprojects {
|
||||
publishing {
|
||||
publications {}
|
||||
repositories {
|
||||
maven { url "file:${rootProject.projectDir}/../../jitsi-maven-repository/releases" }
|
||||
maven {
|
||||
url rootProject.ext.mavenRepo
|
||||
if (!rootProject.ext.mavenRepo.startsWith("file")) {
|
||||
credentials {
|
||||
username rootProject.ext.mavenUser
|
||||
password rootProject.ext.mavenPassword
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use the number of seconds/10 since Jan 1 2019 as the version qualifier number.
|
||||
// This will last for the next ~680 years.
|
||||
// https://stackoverflow.com/a/38643838
|
||||
def versionQualifierNumber = (int)(((new Date().getTime()/1000) - 1546297200) / 10)
|
||||
|
||||
afterEvaluate { project ->
|
||||
if (project.name.startsWith('react-native-')) {
|
||||
def npmManifest = project.file('../package.json')
|
||||
def json = new JsonSlurper().parseText(npmManifest.text)
|
||||
|
||||
// React Native modules have an npm peer dependency on react-native,
|
||||
// they do not have an npm dependency on it. Further below though we
|
||||
// choose a react-native version (range) when we represent them as
|
||||
// Maven artifacts. Effectively, we are forking the projects by not
|
||||
// complying with the full range of their npm peer dependency and,
|
||||
// consequently, we should qualify their version.
|
||||
def versionQualifier = '-jitsi-1'
|
||||
if ('react-native-background-timer' == project.name)
|
||||
versionQualifier = '-jitsi-4' // 2.1.1 + react-native 0.59
|
||||
else if ('react-native-calendar-events' == project.name)
|
||||
versionQualifier = '-jitsi-3' // 1.6.4 + react-native 0.59
|
||||
else if ('react-native-fast-image' == project.name)
|
||||
versionQualifier = '-jitsi-3' // 5.1.1 + react-native 0.59
|
||||
else if ('react-native-google-signin' == project.name)
|
||||
versionQualifier = '-jitsi-3' // 1.0.2 + react-native 0.59
|
||||
else if ('react-native-immersive' == project.name)
|
||||
versionQualifier = '-jitsi-6' // 2.0.0 + react-native 0.59
|
||||
else if ('react-native-keep-awake' == project.name)
|
||||
versionQualifier = '-jitsi-5' // 4.0.0 + react-native 0.59
|
||||
else if ('react-native-linear-gradient' == project.name)
|
||||
versionQualifier = '-jitsi-2' // 2.5.3 + react-native 0.59
|
||||
else if ('react-native-sound' == project.name)
|
||||
versionQualifier = '-jitsi-3' // 0.10.12 + react-native 0.59
|
||||
else if ('react-native-vector-icons' == project.name)
|
||||
versionQualifier = '-jitsi-4' // 6.0.2 + react-native 0.59
|
||||
else if ('react-native-webrtc' == project.name)
|
||||
versionQualifier = '-jitsi-10' // 032ee5c90e2c5ff27ab2f952217104772fcbd155 + react-native 0.59
|
||||
// Release every dependency the SDK has with a -jitsi-XXX qualified version. This allows
|
||||
// us to pin the dependencies and make sure they are always updated, no matter what.
|
||||
|
||||
project.version = "${json.version}${versionQualifier}"
|
||||
project.version = "${json.version}-jitsi-${versionQualifierNumber}"
|
||||
|
||||
project.android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
@@ -171,6 +159,11 @@ ext {
|
||||
// of ours.
|
||||
moduleGroupId = 'com.facebook.react'
|
||||
|
||||
// Maven repo where artifacts will be published
|
||||
mavenRepo = System.env.MVN_REPO ?: ""
|
||||
mavenUser = System.env.MVN_USER ?: ""
|
||||
mavenPassword = System.env.MVN_PASSWORD ?: ""
|
||||
|
||||
// Glide
|
||||
excludeAppGlideModule = true
|
||||
glideVersion = "4.7.1" // keep in sync with react-native-fast-image
|
||||
|
||||
@@ -17,5 +17,5 @@
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
appVersion=19.1.0
|
||||
sdkVersion=2.0.0
|
||||
appVersion=19.2.0
|
||||
sdkVersion=2.1.0
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CWD=$(dirname $0)
|
||||
MVN_REPO=$(realpath $1)
|
||||
RN_VERSION=$(jq -r '.dependencies."react-native"' ${CWD}/../../package.json)
|
||||
|
||||
pushd ${CWD}/../../node_modules/react-native/android/com/facebook/react/react-native/${RN_VERSION}
|
||||
|
||||
mvn \
|
||||
deploy:deploy-file \
|
||||
-Durl=file://${MVN_REPO} \
|
||||
-Dfile=react-native-${RN_VERSION}.aar \
|
||||
-Dpackaging=aar \
|
||||
-Dsources=react-native-${RN_VERSION}-sources.jar \
|
||||
-Djavadoc=react-native-${RN_VERSION}-javadoc.jar \
|
||||
-DgeneratePom=false \
|
||||
-DpomFile=react-native-${RN_VERSION}.pom
|
||||
|
||||
popd
|
||||
81
android/scripts/release-sdk.sh
Executable file
81
android/scripts/release-sdk.sh
Executable file
@@ -0,0 +1,81 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -u
|
||||
|
||||
|
||||
THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)
|
||||
DEFAULT_MVN_REPO="${THIS_DIR}/../../../jitsi-maven-repository/releases"
|
||||
THE_MVN_REPO=${MVN_REPO:-${1:-$DEFAULT_MVN_REPO}}
|
||||
MVN_HTTP=0
|
||||
DEFAULT_SDK_VERSION=$(grep sdkVersion ${THIS_DIR}/../gradle.properties | cut -d"=" -f2)
|
||||
SDK_VERSION=${OVERRIDE_SDK_VERSION:-${DEFAULT_SDK_VERSION}}
|
||||
RN_VERSION=$(jq -r '.dependencies."react-native"' ${THIS_DIR}/../../package.json)
|
||||
|
||||
if [[ $THE_MVN_REPO == http* ]]; then
|
||||
MVN_HTTP=1
|
||||
else
|
||||
MVN_REPO_PATH=$(realpath $THE_MVN_REPO)
|
||||
THE_MVN_REPO="file:${MVN_REPO_PATH}"
|
||||
fi
|
||||
|
||||
export MVN_REPO=$THE_MVN_REPO
|
||||
|
||||
echo "Releasing Jitsi Meet SDK ${SDK_VERSION}"
|
||||
echo "Using ${MVN_REPO} as the Maven repo"
|
||||
|
||||
if [[ $MVN_HTTP == 1 ]]; then
|
||||
# Push React Native
|
||||
echo "Pushing React Native ${RN_VERSION} to the Maven repo"
|
||||
pushd ${THIS_DIR}/../../node_modules/react-native/android/com/facebook/react/react-native/${RN_VERSION}
|
||||
mvn \
|
||||
deploy:deploy-file \
|
||||
-Durl=${MVN_REPO} \
|
||||
-DrepositoryId=${MVN_REPO_ID} \
|
||||
-Dfile=react-native-${RN_VERSION}.aar \
|
||||
-Dpackaging=aar \
|
||||
-DgeneratePom=false \
|
||||
-DpomFile=react-native-${RN_VERSION}.pom || true
|
||||
popd
|
||||
else
|
||||
# Check if an SDK with that same version has already been released
|
||||
if [[ -d ${MVN_REPO}/org/jitsi/react/jitsi-meet-sdk/${SDK_VERSION} ]]; then
|
||||
echo "There is already a release with that version in the Maven repo!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# First push React Native, if necessary
|
||||
if [[ ! -d ${MVN_REPO}/com/facebook/react/react-native/${RN_VERSION} ]]; then
|
||||
echo "Pushing React Native ${RN_VERSION} to the Maven repo"
|
||||
pushd ${THIS_DIR}/../../node_modules/react-native/android/com/facebook/react/react-native/${RN_VERSION}
|
||||
mvn \
|
||||
deploy:deploy-file \
|
||||
-Durl=${MVN_REPO} \
|
||||
-Dfile=react-native-${RN_VERSION}.aar \
|
||||
-Dpackaging=aar \
|
||||
-DgeneratePom=false \
|
||||
-DpomFile=react-native-${RN_VERSION}.pom
|
||||
popd
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now build and publish the Jitsi Meet SDK and its dependencies
|
||||
echo "Building and publishing the Jitsi Meet SDK"
|
||||
pushd ${THIS_DIR}/../
|
||||
./gradlew clean assembleRelease publish
|
||||
popd
|
||||
|
||||
if [[ $MVN_HTTP == 0 ]]; then
|
||||
# The artifacts are now on the Maven repo, commit them
|
||||
pushd ${MVN_REPO_PATH}
|
||||
if [[ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" == "true" ]]; then
|
||||
git add -A .
|
||||
git commit -m "Jitsi Meet SDK + dependencies"
|
||||
fi
|
||||
popd
|
||||
|
||||
# Tag the release
|
||||
git tag -a android-sdk-${SDK_VERSION}
|
||||
fi
|
||||
|
||||
# Done!
|
||||
echo "Finished! Don't forget to push the tag and the Maven repo artifacts."
|
||||
@@ -167,7 +167,7 @@ publishing {
|
||||
aarArchive(MavenPublication) {
|
||||
groupId 'org.jitsi.react'
|
||||
artifactId 'jitsi-meet-sdk'
|
||||
version project.sdkVersion
|
||||
version System.env.OVERRIDE_SDK_VERSION ?: project.sdkVersion
|
||||
|
||||
artifact("${project.buildDir}/outputs/aar/${project.name}-release.aar") {
|
||||
extension "aar"
|
||||
@@ -201,6 +201,14 @@ publishing {
|
||||
|
||||
}
|
||||
repositories {
|
||||
maven { url "file:${rootProject.projectDir}/../../jitsi-maven-repository/releases" }
|
||||
maven {
|
||||
url rootProject.ext.mavenRepo
|
||||
if (!rootProject.ext.mavenRepo.startsWith("file")) {
|
||||
credentials {
|
||||
username rootProject.ext.mavenUser
|
||||
password rootProject.ext.mavenPassword
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
debian/control
vendored
4
debian/control
vendored
@@ -36,7 +36,7 @@ Description: Configuration for web serving of Jitsi Meet
|
||||
|
||||
Package: jitsi-meet-prosody
|
||||
Architecture: all
|
||||
Depends: openssl, prosody | prosody-trunk
|
||||
Depends: openssl, prosody | prosody-trunk | prosody-0.11
|
||||
Description: Prosody configuration for Jitsi Meet
|
||||
Jitsi Meet is a WebRTC JavaScript application that uses Jitsi
|
||||
Videobridge to provide high quality, scalable video conferences.
|
||||
@@ -50,6 +50,6 @@ Description: Prosody configuration for Jitsi Meet
|
||||
|
||||
Package: jitsi-meet-tokens
|
||||
Architecture: all
|
||||
Depends: ${misc:Depends}, prosody-trunk (>= 1nightly607), libssl-dev, luarocks, jitsi-meet-prosody
|
||||
Depends: ${misc:Depends}, prosody-trunk (>= 1nightly747) | prosody-0.11 | prosody (>= 0.11.2), libssl-dev, luarocks, jitsi-meet-prosody
|
||||
Description: Prosody token authentication plugin for Jitsi Meet
|
||||
|
||||
|
||||
13
debian/jitsi-meet-prosody.postinst
vendored
13
debian/jitsi-meet-prosody.postinst
vendored
@@ -125,6 +125,19 @@ case "$1" in
|
||||
ln -sf /var/lib/prosody/$JVB_HOSTNAME.crt /etc/prosody/certs/$JVB_HOSTNAME.crt
|
||||
fi
|
||||
|
||||
PR11_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-0.11' 2>/dev/null | awk '{print $3}' || true)"
|
||||
echo "PR11_INSTALL_CHECK is $PR11_INSTALL_CHECK"
|
||||
PR_VER_INSTALLED=$(dpkg-query -f='${Version}\n' --show prosody 2>/dev/null || true)
|
||||
echo "PR_VER_INSTALLED is $PR_VER_INSTALLED"
|
||||
if [ "$PR11_INSTALL_CHECK" = "installed" ] \
|
||||
|| [ "$PR11_INSTALL_CHECK" = "unpacked" ] \
|
||||
|| dpkg --compare-versions "$PR_VER_INSTALLED" gt "0.11" ; then
|
||||
sed -i 's/storage = \"null\"/storage = \"memory\"/g' $PROSODY_HOST_CONFIG
|
||||
|
||||
# trigger a restart
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
|
||||
if [ ! -f /var/lib/prosody/$JICOFO_AUTH_DOMAIN.crt ]; then
|
||||
# prosodyctl takes care for the permissions
|
||||
# echo for using all default values
|
||||
|
||||
13
debian/jitsi-meet-tokens.postinst
vendored
13
debian/jitsi-meet-tokens.postinst
vendored
@@ -69,14 +69,17 @@ case "$1" in
|
||||
echo "Failed to install basexx - try installing it manually"
|
||||
fi
|
||||
|
||||
PR11_INSTALL_CHECK="$(dpkg-query -f '${Status}' -W 'prosody-0.11' 2>/dev/null | awk '{print $3}' || true)"
|
||||
PR_VER_INSTALLED=$(dpkg-query -f='${Version}\n' --show prosody 2>/dev/null || true)
|
||||
if [ "$PR11_INSTALL_CHECK" = "installed" ] \
|
||||
|| [ "$PR11_INSTALL_CHECK" = "unpacked" ] \
|
||||
|| dpkg --compare-versions "$PR_VER_INSTALLED" gt "0.11" ; then
|
||||
sed -i 's/module:hook/module:hook_global/g' /usr/share/jitsi-meet/prosody-plugins/mod_auth_token.lua
|
||||
fi
|
||||
|
||||
if [ -x "/etc/init.d/prosody" ]; then
|
||||
invoke-rc.d prosody restart
|
||||
fi
|
||||
|
||||
echo "This package requires BOSH Prosody module to be patched !"
|
||||
echo "Use the following command, after this package has been installed and"
|
||||
echo "after every prosody-trunk upgrade:"
|
||||
echo "sudo patch -N /usr/lib/prosody/modules/mod_bosh.lua /usr/share/jitsi-meet/prosody-plugins/mod_bosh.lua.patch"
|
||||
fi
|
||||
else
|
||||
echo "Prosody config not found at $PROSODY_HOST_CONFIG - unable to auto-configure token authentication"
|
||||
|
||||
@@ -195,6 +195,12 @@ var interfaceConfig = {
|
||||
*/
|
||||
// ANDROID_APP_PACKAGE: 'org.jitsi.meet',
|
||||
|
||||
/**
|
||||
* A UX mode where the last screen share participant is automatically
|
||||
* pinned. Note: this mode is experimental and subject to breakage.
|
||||
*/
|
||||
// AUTO_PIN_LATEST_SCREEN_SHARE: false,
|
||||
|
||||
/**
|
||||
* Override the behavior of some notifications to remain displayed until
|
||||
* explicitly dismissed through a user action. The value is how long, in
|
||||
|
||||
@@ -84,8 +84,8 @@ PODS:
|
||||
- nanopb/decode (0.3.901)
|
||||
- nanopb/encode (0.3.901)
|
||||
- ObjectiveDropboxOfficial (3.9.4)
|
||||
- React (0.59.2):
|
||||
- React/Core (= 0.59.2)
|
||||
- React (0.59.4):
|
||||
- React/Core (= 0.59.4)
|
||||
- react-native-background-timer (2.1.1):
|
||||
- React
|
||||
- react-native-calendar-events (1.6.4):
|
||||
@@ -99,50 +99,50 @@ PODS:
|
||||
- React
|
||||
- react-native-webrtc (1.69.0):
|
||||
- React
|
||||
- React/Core (0.59.2):
|
||||
- yoga (= 0.59.2.React)
|
||||
- React/CxxBridge (0.59.2):
|
||||
- React/Core (0.59.4):
|
||||
- yoga (= 0.59.4.React)
|
||||
- React/CxxBridge (0.59.4):
|
||||
- Folly (= 2018.10.22.00)
|
||||
- React/Core
|
||||
- React/cxxreact
|
||||
- React/jsiexecutor
|
||||
- React/cxxreact (0.59.2):
|
||||
- React/cxxreact (0.59.4):
|
||||
- boost-for-react-native (= 1.63.0)
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React/jsinspector
|
||||
- React/DevSupport (0.59.2):
|
||||
- React/DevSupport (0.59.4):
|
||||
- React/Core
|
||||
- React/RCTWebSocket
|
||||
- React/fishhook (0.59.2)
|
||||
- React/jsi (0.59.2):
|
||||
- React/fishhook (0.59.4)
|
||||
- React/jsi (0.59.4):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React/jsiexecutor (0.59.2):
|
||||
- React/jsiexecutor (0.59.4):
|
||||
- DoubleConversion
|
||||
- Folly (= 2018.10.22.00)
|
||||
- glog
|
||||
- React/cxxreact
|
||||
- React/jsi
|
||||
- React/jsinspector (0.59.2)
|
||||
- React/RCTActionSheet (0.59.2):
|
||||
- React/jsinspector (0.59.4)
|
||||
- React/RCTActionSheet (0.59.4):
|
||||
- React/Core
|
||||
- React/RCTAnimation (0.59.2):
|
||||
- React/RCTAnimation (0.59.4):
|
||||
- React/Core
|
||||
- React/RCTBlob (0.59.2):
|
||||
- React/RCTBlob (0.59.4):
|
||||
- React/Core
|
||||
- React/RCTImage (0.59.2):
|
||||
- React/RCTImage (0.59.4):
|
||||
- React/Core
|
||||
- React/RCTNetwork
|
||||
- React/RCTLinkingIOS (0.59.2):
|
||||
- React/RCTLinkingIOS (0.59.4):
|
||||
- React/Core
|
||||
- React/RCTNetwork (0.59.2):
|
||||
- React/RCTNetwork (0.59.4):
|
||||
- React/Core
|
||||
- React/RCTText (0.59.2):
|
||||
- React/RCTText (0.59.4):
|
||||
- React/Core
|
||||
- React/RCTWebSocket (0.59.2):
|
||||
- React/RCTWebSocket (0.59.4):
|
||||
- React/Core
|
||||
- React/fishhook
|
||||
- React/RCTBlob
|
||||
@@ -160,7 +160,7 @@ PODS:
|
||||
- SDWebImage/GIF (4.4.6):
|
||||
- FLAnimatedImage (~> 1.0)
|
||||
- SDWebImage/Core
|
||||
- yoga (0.59.2.React)
|
||||
- yoga (0.59.4.React)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Amplitude-iOS (~> 4.0.4)
|
||||
@@ -268,7 +268,7 @@ SPEC CHECKSUMS:
|
||||
GTMSessionFetcher: 32aeca0aa144acea523e1c8e053089dec2cb98ca
|
||||
nanopb: 2901f78ea1b7b4015c860c2fdd1ea2fee1a18d48
|
||||
ObjectiveDropboxOfficial: a5afefc83f6467c42c45f2253f583f2ad1ffc701
|
||||
React: 9d063e2f356c8cd2f54dd550d4507740037cbabe
|
||||
React: 5cb71fb1a15b5ce04794ab49e24b48ebe4c94e65
|
||||
react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
|
||||
react-native-calendar-events: ee9573e355711ac679e071be70789542431f4ce3
|
||||
react-native-fast-image: 47487b71169aea34868e7b38bf870b6b3f2157c5
|
||||
@@ -278,7 +278,7 @@ SPEC CHECKSUMS:
|
||||
RNSound: e157320f503bdd4f4ee6d8542e948d54f90c3c3a
|
||||
RNVectorIcons: d819334932bcda3332deb3d2c8ea4d069e0b98f9
|
||||
SDWebImage: 3f3f0c02f09798048c47a5ed0a13f17b063572d8
|
||||
yoga: 3768a3026ade0fb46a68f3a31a917cf86bc34fc4
|
||||
yoga: 596e61c9b57751d08a22b07aba310dbd3e65ab75
|
||||
|
||||
PODFILE CHECKSUM: 4a11c3d66127a9845d4a5b2c7fad49f58a9c7a89
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1000;
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
TargetAttributes = {
|
||||
13B07F861A680F5B00A75B9A = {
|
||||
@@ -185,7 +185,7 @@
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
@@ -456,6 +456,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
@@ -514,6 +515,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1000"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "NO"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>19.1.0</string>
|
||||
<string>19.2.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
||||
@@ -1,416 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 48;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
C6245F57205044120040BE68 /* JitsiMeet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6F99C4F204DE79F0001F710 /* JitsiMeet.framework */; };
|
||||
C6245F58205044150040BE68 /* WebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6A34247204DF18000E062DD /* WebRTC.framework */; };
|
||||
C6A34249204DF18000E062DD /* WebRTC.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C6A34247204DF18000E062DD /* WebRTC.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
C6F99C3B204DE6BE0001F710 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6F99C3A204DE6BE0001F710 /* AppDelegate.swift */; };
|
||||
C6F99C3D204DE6BE0001F710 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6F99C3C204DE6BE0001F710 /* ViewController.swift */; };
|
||||
C6F99C40204DE6BE0001F710 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C6F99C3E204DE6BE0001F710 /* Main.storyboard */; };
|
||||
C6F99C42204DE6BE0001F710 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C6F99C41204DE6BE0001F710 /* Assets.xcassets */; };
|
||||
C6F99C45204DE6BE0001F710 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C6F99C43204DE6BE0001F710 /* LaunchScreen.storyboard */; };
|
||||
C6F99C60204DEDC10001F710 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C6F99C4F204DE79F0001F710 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
C6F99C61204DEDC20001F710 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
C6F99C60204DEDC10001F710 /* JitsiMeet.framework in Embed Frameworks */,
|
||||
C6A34249204DF18000E062DD /* WebRTC.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
C6A34247204DF18000E062DD /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
|
||||
C6F99C37204DE6BE0001F710 /* example-pip-app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example-pip-app.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C6F99C3A204DE6BE0001F710 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
C6F99C3C204DE6BE0001F710 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
C6F99C3F204DE6BE0001F710 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
C6F99C41204DE6BE0001F710 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
C6F99C44204DE6BE0001F710 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
C6F99C46204DE6BE0001F710 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
C6F99C4F204DE79F0001F710 /* JitsiMeet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = JitsiMeet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
C6F99C34204DE6BE0001F710 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C6245F57205044120040BE68 /* JitsiMeet.framework in Frameworks */,
|
||||
C6245F58205044150040BE68 /* WebRTC.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
C6F99C2E204DE6BE0001F710 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C6F99C4D204DE79F0001F710 /* Frameworks */,
|
||||
C6F99C38204DE6BE0001F710 /* Products */,
|
||||
C6F99C4C204DE7230001F710 /* src */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C6F99C38204DE6BE0001F710 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C6F99C37204DE6BE0001F710 /* example-pip-app.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C6F99C4C204DE7230001F710 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C6F99C3A204DE6BE0001F710 /* AppDelegate.swift */,
|
||||
C6F99C41204DE6BE0001F710 /* Assets.xcassets */,
|
||||
C6F99C46204DE6BE0001F710 /* Info.plist */,
|
||||
C6F99C43204DE6BE0001F710 /* LaunchScreen.storyboard */,
|
||||
C6F99C3E204DE6BE0001F710 /* Main.storyboard */,
|
||||
C6F99C3C204DE6BE0001F710 /* ViewController.swift */,
|
||||
);
|
||||
path = src;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C6F99C4D204DE79F0001F710 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C6F99C4F204DE79F0001F710 /* JitsiMeet.framework */,
|
||||
C6A34247204DF18000E062DD /* WebRTC.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
C6F99C36204DE6BE0001F710 /* example-pip-app */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = C6F99C49204DE6BE0001F710 /* Build configuration list for PBXNativeTarget "example-pip-app" */;
|
||||
buildPhases = (
|
||||
C6A3424A204DF91D00E062DD /* Run Adjust ATS for loading JS bundle */,
|
||||
C6F99C62204DEFFE0001F710 /* Run React Packager */,
|
||||
C6F99C33204DE6BE0001F710 /* Sources */,
|
||||
C6F99C34204DE6BE0001F710 /* Frameworks */,
|
||||
C6F99C35204DE6BE0001F710 /* Resources */,
|
||||
C6F99C61204DEDC20001F710 /* Embed Frameworks */,
|
||||
C6A3426E20503ECC00E062DD /* Adjust embedded framework architectures */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "example-pip-app";
|
||||
productName = "example-pip-app";
|
||||
productReference = C6F99C37204DE6BE0001F710 /* example-pip-app.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
C6F99C2F204DE6BE0001F710 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 0920;
|
||||
ORGANIZATIONNAME = "Atlassian Inc";
|
||||
TargetAttributes = {
|
||||
C6F99C36204DE6BE0001F710 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
ProvisioningStyle = Automatic;
|
||||
SystemCapabilities = {
|
||||
com.apple.BackgroundModes = {
|
||||
enabled = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = C6F99C32204DE6BE0001F710 /* Build configuration list for PBXProject "example-pip-app" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = C6F99C2E204DE6BE0001F710;
|
||||
productRefGroup = C6F99C38204DE6BE0001F710 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
C6F99C36204DE6BE0001F710 /* example-pip-app */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
C6F99C35204DE6BE0001F710 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C6F99C45204DE6BE0001F710 /* LaunchScreen.storyboard in Resources */,
|
||||
C6F99C42204DE6BE0001F710 /* Assets.xcassets in Resources */,
|
||||
C6F99C40204DE6BE0001F710 /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
C6A3424A204DF91D00E062DD /* Run Adjust ATS for loading JS bundle */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Adjust ATS for loading JS bundle";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "../scripts/fixup-ats.sh";
|
||||
};
|
||||
C6A3426E20503ECC00E062DD /* Adjust embedded framework architectures */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Adjust embedded framework architectures";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "../scripts/fixup-frameworks.sh";
|
||||
};
|
||||
C6F99C62204DEFFE0001F710 /* Run React Packager */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run React Packager";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "../scripts/run-packager.sh";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
C6F99C33204DE6BE0001F710 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C6F99C3D204DE6BE0001F710 /* ViewController.swift in Sources */,
|
||||
C6F99C3B204DE6BE0001F710 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
C6F99C3E204DE6BE0001F710 /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
C6F99C3F204DE6BE0001F710 /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C6F99C43204DE6BE0001F710 /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
C6F99C44204DE6BE0001F710 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
C6F99C47204DE6BE0001F710 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C6F99C48204DE6BE0001F710 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.2;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
C6F99C4A204DE6BE0001F710 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
FRAMEWORK_SEARCH_PATHS = "../../node_modules/react-native-webrtc/ios";
|
||||
INFOPLIST_FILE = src/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.jitsi.example-pip-app";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
C6F99C4B204DE6BE0001F710 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
FRAMEWORK_SEARCH_PATHS = "../../node_modules/react-native-webrtc/ios";
|
||||
INFOPLIST_FILE = src/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.jitsi.example-pip-app";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
C6F99C32204DE6BE0001F710 /* Build configuration list for PBXProject "example-pip-app" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C6F99C47204DE6BE0001F710 /* Debug */,
|
||||
C6F99C48204DE6BE0001F710 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
C6F99C49204DE6BE0001F710 /* Build configuration list for PBXNativeTarget "example-pip-app" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
C6F99C4A204DE6BE0001F710 /* Debug */,
|
||||
C6F99C4B204DE6BE0001F710 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = C6F99C2F204DE6BE0001F710 /* Project object */;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import JitsiMeet
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
func application(_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
|
||||
guard let launchOptions = launchOptions else { return false }
|
||||
return JitsiMeetView.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
|
||||
// MARK: - Linking delegate methods
|
||||
|
||||
func application(_ application: UIApplication,
|
||||
continue userActivity: NSUserActivity,
|
||||
restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
|
||||
return JitsiMeetView.application(application, continue: userActivity, restorationHandler: restorationHandler)
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
|
||||
return JitsiMeetView.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"size" : "1024x1024",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" systemVersion="17A277" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="example-pip-app" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="QxY-C8-fwD">
|
||||
<rect key="frame" x="116" y="324.5" width="143" height="38"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="21"/>
|
||||
<state key="normal" title="Open Jitsi Meet"/>
|
||||
<connections>
|
||||
<action selector="openJitsiMeetWithSender:" destination="BYZ-38-t0r" eventType="touchUpInside" id="79C-XR-05w"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="QxY-C8-fwD" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="6a6-l1-7Ct"/>
|
||||
<constraint firstItem="QxY-C8-fwD" firstAttribute="centerY" secondItem="6Tk-OE-BBY" secondAttribute="centerY" id="Hfg-TH-0g2"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="videoButton" destination="QxY-C8-fwD" id="Zwa-Hx-Zub"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="32.799999999999997" y="658.92053973013503"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -1,64 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>localhost</key>
|
||||
<dict>
|
||||
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
import JitsiMeet
|
||||
|
||||
class ViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var videoButton: UIButton?
|
||||
|
||||
fileprivate var pipViewCoordinator: PiPViewCoordinator?
|
||||
fileprivate var jitsiMeetView: JitsiMeetView?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
}
|
||||
|
||||
override func viewWillTransition(to size: CGSize,
|
||||
with coordinator: UIViewControllerTransitionCoordinator) {
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
|
||||
let rect = CGRect(origin: CGPoint.zero, size: size)
|
||||
pipViewCoordinator?.resetBounds(bounds: rect)
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction func openJitsiMeet(sender: Any?) {
|
||||
cleanUp()
|
||||
|
||||
// create and configure jitsimeet view
|
||||
let jitsiMeetView = JitsiMeetView()
|
||||
jitsiMeetView.welcomePageEnabled = true
|
||||
jitsiMeetView.pictureInPictureEnabled = true
|
||||
jitsiMeetView.load(nil)
|
||||
jitsiMeetView.delegate = self
|
||||
self.jitsiMeetView = jitsiMeetView
|
||||
|
||||
// Enable jitsimeet view to be a view that can be displayed
|
||||
// on top of all the things, and let the coordinator to manage
|
||||
// the view state and interactions
|
||||
pipViewCoordinator = PiPViewCoordinator(withView: jitsiMeetView)
|
||||
pipViewCoordinator?.configureAsStickyView(withParentView: view)
|
||||
|
||||
// animate in
|
||||
jitsiMeetView.alpha = 0
|
||||
pipViewCoordinator?.show()
|
||||
}
|
||||
|
||||
fileprivate func cleanUp() {
|
||||
jitsiMeetView?.removeFromSuperview()
|
||||
jitsiMeetView = nil
|
||||
pipViewCoordinator = nil
|
||||
}
|
||||
}
|
||||
|
||||
extension ViewController: JitsiMeetViewDelegate {
|
||||
|
||||
func conferenceFailed(_ data: [AnyHashable : Any]!) {
|
||||
hideJitsiMeetViewAndCleanUp()
|
||||
}
|
||||
|
||||
func conferenceLeft(_ data: [AnyHashable : Any]!) {
|
||||
hideJitsiMeetViewAndCleanUp()
|
||||
}
|
||||
|
||||
func enterPicture(inPicture data: [AnyHashable : Any]!) {
|
||||
DispatchQueue.main.async {
|
||||
self.pipViewCoordinator?.enterPictureInPicture()
|
||||
}
|
||||
}
|
||||
|
||||
private func hideJitsiMeetViewAndCleanUp() {
|
||||
DispatchQueue.main.async {
|
||||
self.pipViewCoordinator?.hide() { _ in
|
||||
self.cleanUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:example-pip-app/example-pip-app.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:app/app.xcodeproj">
|
||||
</FileRef>
|
||||
|
||||
44
ios/scripts/release-sdk.sh
Executable file
44
ios/scripts/release-sdk.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -u
|
||||
|
||||
THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)
|
||||
PROJECT_REPO=$(realpath ${THIS_DIR}/../..)
|
||||
RELEASE_REPO=$(realpath ${THIS_DIR}/../../../jitsi-meet-ios-sdk-releases)
|
||||
SDK_VERSION=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" ${THIS_DIR}/../sdk/src/Info.plist)
|
||||
|
||||
|
||||
echo "Releasing Jitsi Meet SDK ${SDK_VERSION}"
|
||||
|
||||
pushd ${RELEASE_REPO}
|
||||
|
||||
# Generate podspec file
|
||||
cat JitsiMeetSDK.podspec.tpl | sed -e s/VERSION/${SDK_VERSION}/g > JitsiMeetSDK.podspec
|
||||
|
||||
# Cleanup
|
||||
rm -rf Frameworks/*
|
||||
|
||||
popd
|
||||
|
||||
# Build the SDK
|
||||
pushd ${PROJECT_REPO}
|
||||
rm -rf ios/sdk/JitsiMeet.framework
|
||||
xcodebuild -workspace ios/jitsi-meet.xcworkspace -scheme JitsiMeet -destination='generic/platform=iOS' -configuration Release archive
|
||||
git tag -a ios-sdk-${SDK_VERSION}
|
||||
popd
|
||||
|
||||
pushd ${RELEASE_REPO}
|
||||
|
||||
# Put the new files in the repo
|
||||
cp -r ${PROJECT_REPO}/ios/sdk/JitsiMeet.framework Frameworks/
|
||||
cp -r ${PROJECT_REPO}/node_modules/react-native-webrtc/ios/WebRTC.framework Frameworks/
|
||||
|
||||
# Add all files to git
|
||||
git add -A .
|
||||
git commit -m "${SDK_VERSION}"
|
||||
git tag ${SDK_VERSION}
|
||||
|
||||
popd
|
||||
|
||||
echo "Finished! Don't forget to push the tags and releases repo artifacts."
|
||||
echo "The new pod can be pushed to CocoaPods by doing: pod trunk push JitsiMeetSDK.podspec"
|
||||
@@ -293,7 +293,7 @@
|
||||
0BD906DC1EC0C00300C8C18E /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1000;
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = Jitsi;
|
||||
TargetAttributes = {
|
||||
0BD906E41EC0C00300C8C18E = {
|
||||
@@ -305,10 +305,11 @@
|
||||
};
|
||||
buildConfigurationList = 0BD906DF1EC0C00300C8C18E /* Build configuration list for PBXProject "sdk" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 0BD906DB1EC0C00300C8C18E;
|
||||
productRefGroup = 0BD906E61EC0C00300C8C18E /* Products */;
|
||||
@@ -486,6 +487,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
@@ -547,6 +549,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
@@ -622,8 +625,8 @@
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = On;
|
||||
SWIFT_VERSION = 4.2;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -649,8 +652,8 @@
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "";
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = On;
|
||||
SWIFT_VERSION = 4.2;
|
||||
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1000"
|
||||
LastUpgradeVersion = "1020"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.0.0</string>
|
||||
<string>2.1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
@@ -44,23 +44,23 @@
|
||||
|
||||
#pragma mak - This class is a singleton
|
||||
|
||||
+ (instancetype)sharedInstance;
|
||||
+ (instancetype _Nonnull)sharedInstance;
|
||||
|
||||
#pragma mark - Methods that the App delegate must call
|
||||
|
||||
- (BOOL)application:(UIApplication *_Nonnull)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *_Nonnull)launchOptions;
|
||||
|
||||
- (BOOL)application:(UIApplication * _Nonnull)application
|
||||
continueUserActivity:(NSUserActivity * _Nonnull)userActivity
|
||||
restorationHandler:(void (^ _Nullable)(NSArray * _Nullable))restorationHandler;
|
||||
- (BOOL)application:(UIApplication *_Nonnull)application
|
||||
continueUserActivity:(NSUserActivity *_Nonnull)userActivity
|
||||
restorationHandler:(void (^_Nullable)(NSArray<id<UIUserActivityRestoring>> *_Nonnull))restorationHandler;
|
||||
|
||||
- (BOOL)application:(UIApplication *)app
|
||||
openURL:(NSURL *)url
|
||||
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options;
|
||||
- (BOOL)application:(UIApplication *_Nonnull)app
|
||||
openURL:(NSURL *_Nonnull)url
|
||||
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *_Nonnull)options;
|
||||
|
||||
#pragma mark - Utility methods
|
||||
|
||||
- (JitsiMeetConferenceOptions *)getInitialConferenceOptions;
|
||||
- (JitsiMeetConferenceOptions *_Nonnull)getInitialConferenceOptions;
|
||||
|
||||
@end
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
continueUserActivity:(NSUserActivity *)userActivity
|
||||
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
|
||||
restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *))restorationHandler {
|
||||
|
||||
JitsiMeetConferenceOptions *options = [self optionsFromUserActivity:userActivity];
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
@property (nonatomic, readonly) BOOL welcomePageEnabled;
|
||||
|
||||
+ (instancetype)fromBuilder:(void (^)(JitsiMeetConferenceOptionsBuilder *))initBlock;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
+ (instancetype _Nonnull)fromBuilder:(void (^_Nonnull)(JitsiMeetConferenceOptionsBuilder *_Nonnull))initBlock;
|
||||
- (instancetype _Nonnull)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
@interface JitsiMeetView ()
|
||||
|
||||
+ (instancetype)viewForExternalAPIScope:(NSString *)externalAPIScope;
|
||||
+ (instancetype _Nullable)viewForExternalAPIScope:(NSString *_Nonnull)externalAPIScope;
|
||||
+ (BOOL)setPropsInViews:(NSDictionary *_Nonnull)newProps;
|
||||
|
||||
@end
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
* is an already active conference it will be automatically left prior to
|
||||
* joining the new one.
|
||||
*/
|
||||
- (void)join:(JitsiMeetConferenceOptions *)options;
|
||||
- (void)join:(JitsiMeetConferenceOptions *_Nullable)options;
|
||||
/**
|
||||
* Leaves the currently active conference.
|
||||
*/
|
||||
|
||||
@@ -130,13 +130,10 @@ internal final class JMCallKitEmitter: NSObject, CXProviderDelegate {
|
||||
|
||||
fileprivate struct JMCallKitEventListenerWrapper: Hashable {
|
||||
|
||||
public var hashValue: Int
|
||||
|
||||
internal weak var listener: JMCallKitListener?
|
||||
|
||||
public init(listener: JMCallKitListener) {
|
||||
self.listener = listener
|
||||
self.hashValue = listener.hash
|
||||
}
|
||||
|
||||
public static func ==(lhs: JMCallKitEventListenerWrapper,
|
||||
@@ -145,4 +142,8 @@ fileprivate struct JMCallKitEventListenerWrapper: Hashable {
|
||||
// necessarily equal to each other."
|
||||
return lhs.hashValue == rhs.hashValue
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(self.listener?.hash)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
},
|
||||
"title": "Chat"
|
||||
},
|
||||
"connectingOverlay": {
|
||||
"joiningRoom": "Connecting you to your meeting..."
|
||||
},
|
||||
"connection": {
|
||||
"ATTACHED": "Attached",
|
||||
"AUTHENTICATING": "Authenticating",
|
||||
|
||||
@@ -168,6 +168,13 @@ export default class LargeVideoManager {
|
||||
get id() {
|
||||
const container = this.getCurrentContainer();
|
||||
|
||||
// If a user switch for large video is in progress then provide what
|
||||
// will be the end result of the update.
|
||||
if (this.updateInProcess
|
||||
&& this.newStreamData
|
||||
&& this.newStreamData.id !== container.id) {
|
||||
return this.newStreamData.id;
|
||||
}
|
||||
|
||||
return container.id;
|
||||
}
|
||||
@@ -184,8 +191,8 @@ export default class LargeVideoManager {
|
||||
|
||||
// Include hide()/fadeOut only if we're switching between users
|
||||
// eslint-disable-next-line eqeqeq
|
||||
const isUserSwitch = this.newStreamData.id != this.id;
|
||||
const container = this.getCurrentContainer();
|
||||
const isUserSwitch = this.newStreamData.id !== container.id;
|
||||
const preUpdate = isUserSwitch ? container.hide() : Promise.resolve();
|
||||
|
||||
preUpdate.then(() => {
|
||||
|
||||
72
package-lock.json
generated
72
package-lock.json
generated
@@ -2071,9 +2071,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.0.tgz",
|
||||
"integrity": "sha512-WBmxlgH2122EzEJ6GH8o9L/FeoUKxxxZ6q6VUxoTlsE4EvbTWKJb447eyVxTEuq0LpXjlq/kCB2qgBvsYRkLvQ=="
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz",
|
||||
"integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew=="
|
||||
},
|
||||
"find-cache-dir": {
|
||||
"version": "2.1.0",
|
||||
@@ -2128,9 +2128,9 @@
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz",
|
||||
"integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA=="
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
|
||||
},
|
||||
"pify": {
|
||||
"version": "4.0.1",
|
||||
@@ -2146,9 +2146,9 @@
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
|
||||
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
|
||||
"version": "5.7.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
|
||||
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -2250,9 +2250,9 @@
|
||||
}
|
||||
},
|
||||
"@jitsi/sdp-interop": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/@jitsi/sdp-interop/-/sdp-interop-0.1.13.tgz",
|
||||
"integrity": "sha512-U/UI1W9NULZj7PgP9GVzWfvIQ4T2LJBvMj4dNKclHqLMXIZ9aSuWEeYe/Q9jB+J7vot+M9ofALtO4w5xifffoQ==",
|
||||
"version": "0.1.14",
|
||||
"resolved": "https://registry.npmjs.org/@jitsi/sdp-interop/-/sdp-interop-0.1.14.tgz",
|
||||
"integrity": "sha512-v60VAtBx9LO46c9In9oMNY+Ho5993UMOLHBg6VcrcyoVTIWIeqs/9YjjmrQ3Sf4I5aMRABNl7HTby/1lHcqFJw==",
|
||||
"requires": {
|
||||
"sdp-transform": "2.3.0"
|
||||
}
|
||||
@@ -2275,9 +2275,9 @@
|
||||
}
|
||||
},
|
||||
"@react-native-community/cli": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-1.5.1.tgz",
|
||||
"integrity": "sha512-HFCYxI6WW3SoayrOSdhYxor5CaF/SBp7W73TyvTRRNAqQdA9/NX9wMZly+UpmFQkQFkiLvgc2yqS5vT918XXUw==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-1.6.0.tgz",
|
||||
"integrity": "sha512-OV3N5O/wzjb8OTZDiFerX0gf9/KzLJOvDttU38BqIvn8+OLkH6SIgGrKked9vrKKvH5bFG6jmCmKCW5gP+tOwQ==",
|
||||
"requires": {
|
||||
"chalk": "^1.1.1",
|
||||
"commander": "^2.19.0",
|
||||
@@ -4258,9 +4258,9 @@
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
|
||||
"integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg=="
|
||||
"version": "2.20.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
|
||||
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ=="
|
||||
},
|
||||
"comment-parser": {
|
||||
"version": "0.4.2",
|
||||
@@ -4543,9 +4543,9 @@
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.13.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz",
|
||||
"integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==",
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
@@ -5519,8 +5519,8 @@
|
||||
}
|
||||
},
|
||||
"eslint-config-jitsi": {
|
||||
"version": "github:jitsi/eslint-config-jitsi#1f3fbcea8baa1ab95929a351be3977e00cb162ec",
|
||||
"from": "github:jitsi/eslint-config-jitsi#1.0.0",
|
||||
"version": "github:jitsi/eslint-config-jitsi#5f9fe4fd00be471ab6f5d06f77ffc90bba0853e8",
|
||||
"from": "github:jitsi/eslint-config-jitsi#1.0.1",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-import-resolver-node": {
|
||||
@@ -8634,10 +8634,10 @@
|
||||
}
|
||||
},
|
||||
"lib-jitsi-meet": {
|
||||
"version": "github:jitsi/lib-jitsi-meet#83af6e78a82466153e93d4a467e1459c9c97d5ee",
|
||||
"from": "github:jitsi/lib-jitsi-meet#83af6e78a82466153e93d4a467e1459c9c97d5ee",
|
||||
"version": "github:jitsi/lib-jitsi-meet#86e3badd5c04e1df72435205d28a58c8a64e343a",
|
||||
"from": "github:jitsi/lib-jitsi-meet#86e3badd5c04e1df72435205d28a58c8a64e343a",
|
||||
"requires": {
|
||||
"@jitsi/sdp-interop": "0.1.13",
|
||||
"@jitsi/sdp-interop": "0.1.14",
|
||||
"@jitsi/sdp-simulcast": "0.2.1",
|
||||
"async": "0.9.0",
|
||||
"current-executing-script": "0.1.3",
|
||||
@@ -11745,9 +11745,9 @@
|
||||
}
|
||||
},
|
||||
"react-native": {
|
||||
"version": "0.59.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.59.2.tgz",
|
||||
"integrity": "sha512-gIygrCr42rGEQnfjcAZdCOqgjC0oZtTIp+mdbUW+yqHpNUU1PbYKzUkLlvSFGeN+IUcL8WTaC1JtJvghKhaLmA==",
|
||||
"version": "0.59.4",
|
||||
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.59.4.tgz",
|
||||
"integrity": "sha512-etnXQp9IZgC8Vj5gsxZEDP4xRjJVNIj5/BSE1WcNAONG6tu6+mDBntx1jxHInwh61WYNgoQJuQGsbN5Na59ZDw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.0.0",
|
||||
"@react-native-community/cli": "^1.2.1",
|
||||
@@ -14026,9 +14026,12 @@
|
||||
}
|
||||
},
|
||||
"stacktrace-parser": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.4.tgz",
|
||||
"integrity": "sha1-ATl5IuX2Ls8whFUiyVxP4dJefU4="
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.5.tgz",
|
||||
"integrity": "sha512-fjJ563lEMEXdqUH8fZR84sczWxM+Pi3bViix1n7371mFr8sL7UPewec79+IhHkN4UMmGbXoXj58WIaF7lIciRA==",
|
||||
"requires": {
|
||||
"type-fest": "^0.3.0"
|
||||
}
|
||||
},
|
||||
"static-extend": {
|
||||
"version": "0.1.2",
|
||||
@@ -14999,6 +15002,11 @@
|
||||
"prelude-ls": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.0.tgz",
|
||||
"integrity": "sha512-fg3sfdDdJDtdHLUpeGsf/fLyG1aapk6zgFiYG5+MDUPybGrJemH4SLk5tP7hGRe8ntxjg0q5LYW53b6YpJIQ9Q=="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.16",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"js-utils": "github:jitsi/js-utils#73a67a7a60d52f8e895f50939c8fcbd1f20fe7b5",
|
||||
"jsrsasign": "8.0.12",
|
||||
"jwt-decode": "2.2.0",
|
||||
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#83af6e78a82466153e93d4a467e1459c9c97d5ee",
|
||||
"lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#86e3badd5c04e1df72435205d28a58c8a64e343a",
|
||||
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
|
||||
"lodash": "4.17.11",
|
||||
"moment": "2.19.4",
|
||||
@@ -62,7 +62,7 @@
|
||||
"react-emoji-render": "0.4.6",
|
||||
"react-i18next": "7.13.0",
|
||||
"react-linkify": "0.2.2",
|
||||
"react-native": "0.59.2",
|
||||
"react-native": "0.59.4",
|
||||
"react-native-background-timer": "2.1.1",
|
||||
"react-native-calendar-events": "1.6.4",
|
||||
"react-native-callstats": "3.58.2",
|
||||
@@ -99,7 +99,7 @@
|
||||
"clean-css": "3.4.25",
|
||||
"css-loader": "0.28.7",
|
||||
"eslint": "5.6.1",
|
||||
"eslint-config-jitsi": "github:jitsi/eslint-config-jitsi#1.0.0",
|
||||
"eslint-config-jitsi": "github:jitsi/eslint-config-jitsi#1.0.1",
|
||||
"eslint-plugin-flowtype": "2.50.3",
|
||||
"eslint-plugin-import": "2.14.0",
|
||||
"eslint-plugin-jsdoc": "3.8.0",
|
||||
|
||||
@@ -31,176 +31,70 @@ declare var APP: Object;
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function appNavigate(uri: ?string) {
|
||||
return (dispatch: Dispatch<any>, getState: Function) =>
|
||||
_appNavigateToOptionalLocation(dispatch, getState, parseURIString(uri));
|
||||
}
|
||||
return async (dispatch: Dispatch<any>, getState: Function) => {
|
||||
let location = parseURIString(uri);
|
||||
|
||||
/**
|
||||
* Triggers an in-app navigation to a specific location URI.
|
||||
*
|
||||
* @param {Dispatch} dispatch - The redux {@code dispatch} function.
|
||||
* @param {Function} getState - The redux function that gets/retrieves the redux
|
||||
* state.
|
||||
* @param {Object} newLocation - The location URI to navigate to. The value
|
||||
* cannot be undefined and is assumed to have all properties such as
|
||||
* {@code host}, {@code contextRoot}, and {@code room} defined. Depending on the
|
||||
* property, it may have a value equal to {@code undefined} and that may be
|
||||
* acceptable.
|
||||
* @private
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function _appNavigateToMandatoryLocation(
|
||||
dispatch: Dispatch<any>, getState: Function,
|
||||
newLocation: Object
|
||||
): Promise<void> {
|
||||
const { room } = newLocation;
|
||||
const locationURL = new URL(newLocation.toString());
|
||||
// If the specified location (URI) does not identify a host, use the app's
|
||||
// default.
|
||||
if (!location || !location.host) {
|
||||
const defaultLocation = parseURIString(getDefaultURL(getState));
|
||||
|
||||
dispatch(configWillLoad(locationURL));
|
||||
if (location) {
|
||||
location.host = defaultLocation.host;
|
||||
|
||||
return (
|
||||
_loadConfig(dispatch, getState, newLocation)
|
||||
.then(
|
||||
config => loadConfigSettled(/* error */ undefined, config),
|
||||
error => loadConfigSettled(error, /* config */ undefined))
|
||||
.then(() => dispatch(setRoom(room))));
|
||||
// FIXME Turn location's host, hostname, and port properties into
|
||||
// setters in order to reduce the risks of inconsistent state.
|
||||
location.hostname = defaultLocation.hostname;
|
||||
location.pathname
|
||||
= defaultLocation.pathname + location.pathname.substr(1);
|
||||
location.port = defaultLocation.port;
|
||||
location.protocol = defaultLocation.protocol;
|
||||
} else {
|
||||
location = defaultLocation;
|
||||
}
|
||||
}
|
||||
|
||||
location.protocol || (location.protocol = 'https:');
|
||||
const { contextRoot, host, room } = location;
|
||||
const locationURL = new URL(location.toString());
|
||||
|
||||
dispatch(configWillLoad(locationURL, room));
|
||||
|
||||
let protocol = location.protocol.toLowerCase();
|
||||
|
||||
// The React Native app supports an app-specific scheme which is sure to not
|
||||
// be supported by fetch.
|
||||
protocol !== 'http:' && protocol !== 'https:' && (protocol = 'https:');
|
||||
|
||||
const baseURL = `${protocol}//${host}${contextRoot || '/'}`;
|
||||
let url = `${baseURL}config.js`;
|
||||
|
||||
// XXX In order to support multiple shards, tell the room to the deployment.
|
||||
room && (url += `?room=${room.toLowerCase()}`);
|
||||
|
||||
let config;
|
||||
|
||||
try {
|
||||
config = await loadConfig(url);
|
||||
dispatch(storeConfig(baseURL, config));
|
||||
} catch (error) {
|
||||
config = restoreConfig(baseURL);
|
||||
|
||||
if (!config) {
|
||||
dispatch(loadConfigError(error, locationURL));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies that an attempt to load a configuration has completed. Due to
|
||||
* the asynchronous nature of the loading, the specified {@code config} may
|
||||
* or may not be required by the time the notification arrives.
|
||||
*
|
||||
* @param {string|undefined} error - If the loading has failed, the error
|
||||
* detailing the cause of the failure.
|
||||
* @param {Object|undefined} config - If the loading has succeeded, the
|
||||
* loaded configuration.
|
||||
* @returns {void}
|
||||
*/
|
||||
function loadConfigSettled(error, config) {
|
||||
// Due to the asynchronous nature of the loading, the specified config
|
||||
// may or may not be required by the time the notification arrives. If
|
||||
// we receive the config for a location we are no longer interested in,
|
||||
// "ignore" it - deliver it to the external API, for example, but do not
|
||||
// proceed with the appNavigate procedure/process.
|
||||
if (getState()['features/base/config'].locationURL === locationURL) {
|
||||
dispatch(setLocationURL(locationURL));
|
||||
dispatch(setConfig(config));
|
||||
dispatch(setRoom(room));
|
||||
} else {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
error || (error = new Error('Config no longer needed!'));
|
||||
|
||||
// XXX The failure could be, for example, because of a
|
||||
// certificate-related error. In which case the connection will fail
|
||||
// later in Strophe anyway.
|
||||
dispatch(loadConfigError(error, locationURL));
|
||||
|
||||
throw error;
|
||||
dispatch(loadConfigError(new Error('Config no longer needed!'), locationURL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers an in-app navigation to a specific or undefined location (URI).
|
||||
*
|
||||
* @param {Dispatch} dispatch - The redux {@code dispatch} function.
|
||||
* @param {Function} getState - The redux function that gets/retrieves the redux
|
||||
* state.
|
||||
* @param {Object} location - The location (URI) to navigate to. The value may
|
||||
* be undefined.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _appNavigateToOptionalLocation(
|
||||
dispatch: Dispatch<any>, getState: Function,
|
||||
location: Object) {
|
||||
// If the specified location (URI) does not identify a host, use the app's
|
||||
// default.
|
||||
if (!location || !location.host) {
|
||||
const defaultLocation = parseURIString(getDefaultURL(getState));
|
||||
|
||||
if (location) {
|
||||
location.host = defaultLocation.host;
|
||||
|
||||
// FIXME Turn location's host, hostname, and port properties into
|
||||
// setters in order to reduce the risks of inconsistent state.
|
||||
location.hostname = defaultLocation.hostname;
|
||||
location.pathname
|
||||
= defaultLocation.pathname + location.pathname.substr(1);
|
||||
location.port = defaultLocation.port;
|
||||
location.protocol = defaultLocation.protocol;
|
||||
} else {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
location = defaultLocation;
|
||||
}
|
||||
}
|
||||
|
||||
location.protocol || (location.protocol = 'https:');
|
||||
|
||||
return _appNavigateToMandatoryLocation(dispatch, getState, location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads config.js from a specific host.
|
||||
*
|
||||
* @param {Dispatch} dispatch - The redux {@code dispatch} function.
|
||||
* @param {Function} getState - The redux {@code getState} function.
|
||||
* @param {Object} location - The location URI which specifies the host to load
|
||||
* the config.js from.
|
||||
* @private
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
function _loadConfig(
|
||||
dispatch: Dispatch<any>,
|
||||
getState: Function,
|
||||
{ contextRoot, host, protocol, room }) {
|
||||
// XXX As the mobile/React Native app does not employ config on the
|
||||
// WelcomePage, do not download config.js from the deployment when
|
||||
// navigating to the WelcomePage - the perceived/visible navigation will be
|
||||
// faster.
|
||||
if (!room && typeof APP === 'undefined') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/* eslint-disable no-param-reassign */
|
||||
|
||||
protocol = protocol.toLowerCase();
|
||||
|
||||
// The React Native app supports an app-specific scheme which is sure to not
|
||||
// be supported by fetch (or whatever loadConfig utilizes).
|
||||
protocol !== 'http:' && protocol !== 'https:' && (protocol = 'https:');
|
||||
|
||||
// TDOO userinfo
|
||||
|
||||
const baseURL = `${protocol}//${host}${contextRoot || '/'}`;
|
||||
let url = `${baseURL}config.js`;
|
||||
|
||||
// XXX In order to support multiple shards, tell the room to the deployment.
|
||||
room && (url += `?room=${room.toLowerCase()}`);
|
||||
|
||||
/* eslint-enable no-param-reassign */
|
||||
|
||||
return loadConfig(url).then(
|
||||
/* onFulfilled */ config => {
|
||||
// FIXME If the config is no longer needed (in the terms of
|
||||
// _loadConfig) and that happened because of an intervening
|
||||
// _loadConfig for the same baseURL, then the unneeded config may be
|
||||
// stored after the needed config. Anyway.
|
||||
dispatch(storeConfig(baseURL, config));
|
||||
|
||||
return config;
|
||||
},
|
||||
/* onRejected */ error => {
|
||||
// XXX The (down)loading of config failed. Try to use the last
|
||||
// successfully fetched for that deployment. It may not match the
|
||||
// shard.
|
||||
const config = restoreConfig(baseURL);
|
||||
|
||||
if (config) {
|
||||
return config;
|
||||
}
|
||||
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
// @flow
|
||||
|
||||
export * from './App';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// @flow
|
||||
|
||||
export * from './actions';
|
||||
export * from './components';
|
||||
export * from './functions';
|
||||
|
||||
@@ -5,7 +5,8 @@ import { Text, TextInput, View } from 'react-native';
|
||||
import { connect as reduxConnect } from 'react-redux';
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
import { connect, toJid } from '../../base/connection';
|
||||
import { toJid } from '../../base/connection';
|
||||
import { connect } from '../../base/connection/actions.native';
|
||||
import {
|
||||
CustomSubmitDialog,
|
||||
FIELD_UNDERLINE,
|
||||
|
||||
@@ -117,7 +117,7 @@ export default class BaseApp extends Component<*, State> {
|
||||
render() {
|
||||
const { route: { component }, store } = this.state;
|
||||
|
||||
if (store && component) {
|
||||
if (store) {
|
||||
return (
|
||||
<I18nextProvider i18n = { i18next }>
|
||||
<Provider store = { store }>
|
||||
@@ -160,7 +160,7 @@ export default class BaseApp extends Component<*, State> {
|
||||
* @protected
|
||||
*/
|
||||
_createMainElement(component, props) {
|
||||
return React.createElement(component, props || {});
|
||||
return component ? React.createElement(component, props || {}) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,10 @@ export default {
|
||||
'LargeVideo': {
|
||||
background: ColorPalette.black
|
||||
},
|
||||
'LoadConfigOverlay': {
|
||||
background: ColorPalette.black,
|
||||
text: ColorPalette.white
|
||||
},
|
||||
'Thumbnail': {
|
||||
activeParticipantHighlight: ColorPalette.blue,
|
||||
activeParticipantTint: ColorPalette.black,
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
*
|
||||
* {
|
||||
* type: CONFIG_WILL_LOAD,
|
||||
* locationURL: URL
|
||||
* locationURL: URL,
|
||||
* room: string
|
||||
* }
|
||||
*/
|
||||
export const CONFIG_WILL_LOAD = 'CONFIG_WILL_LOAD';
|
||||
|
||||
@@ -15,15 +15,18 @@ import { setConfigFromURLParams } from './functions';
|
||||
*
|
||||
* @param {URL} locationURL - The URL of the location which necessitated the
|
||||
* loading of a configuration.
|
||||
* @param {string} room - The name of the room (conference) for which we're loading the config for.
|
||||
* @returns {{
|
||||
* type: CONFIG_WILL_LOAD,
|
||||
* locationURL: URL
|
||||
* locationURL: URL,
|
||||
* room: string
|
||||
* }}
|
||||
*/
|
||||
export function configWillLoad(locationURL: URL) {
|
||||
export function configWillLoad(locationURL: URL, room: string) {
|
||||
return {
|
||||
type: CONFIG_WILL_LOAD,
|
||||
locationURL
|
||||
locationURL,
|
||||
room
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of (redux) action which signals that a connection disconnected.
|
||||
*
|
||||
|
||||
@@ -8,16 +8,16 @@ import { toState } from '../redux';
|
||||
*
|
||||
* @param {Function|Object} stateOrGetState - The redux state or redux's
|
||||
* {@code getState} function.
|
||||
* @returns {string|undefined}
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getInviteURL(stateOrGetState: Function | Object): ?string {
|
||||
export function getInviteURL(stateOrGetState: Function | Object): string {
|
||||
const state = toState(stateOrGetState);
|
||||
const locationURL
|
||||
= state instanceof URL
|
||||
? state
|
||||
: state['features/base/connection'].locationURL;
|
||||
|
||||
return locationURL ? getURLWithoutParams(locationURL).href : undefined;
|
||||
return getURLWithoutParams(locationURL).href;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// @flow
|
||||
|
||||
export * from './actions';
|
||||
export * from './actionTypes';
|
||||
export * from './functions';
|
||||
|
||||
@@ -11,9 +11,12 @@ import {
|
||||
import {
|
||||
areDeviceLabelsInitialized,
|
||||
getDeviceIdByLabel,
|
||||
getDevicesFromURL
|
||||
getDevicesFromURL,
|
||||
setAudioOutputDeviceId
|
||||
} from './functions';
|
||||
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
||||
/**
|
||||
* Adds a pending device request.
|
||||
*
|
||||
@@ -36,11 +39,12 @@ export function addPendingDeviceRequest(request) {
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function configureInitialDevices() {
|
||||
return (dispatch, getState) => new Promise(resolve => {
|
||||
return (dispatch, getState) => {
|
||||
const deviceLabels = getDevicesFromURL(getState());
|
||||
let updateSettingsPromise;
|
||||
|
||||
if (deviceLabels) {
|
||||
dispatch(getAvailableDevices()).then(() => {
|
||||
updateSettingsPromise = dispatch(getAvailableDevices()).then(() => {
|
||||
const state = getState();
|
||||
|
||||
if (!areDeviceLabelsInitialized(state)) {
|
||||
@@ -59,7 +63,6 @@ export function configureInitialDevices() {
|
||||
responseCallback() {}
|
||||
}));
|
||||
});
|
||||
resolve();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -72,7 +75,7 @@ export function configureInitialDevices() {
|
||||
|
||||
Object.keys(deviceLabels).forEach(key => {
|
||||
const label = deviceLabels[key];
|
||||
const deviceId = getDeviceIdByLabel(state, label);
|
||||
const deviceId = getDeviceIdByLabel(state, label, key);
|
||||
|
||||
if (deviceId) {
|
||||
newSettings[devicesKeysToSettingsKeys[key]] = deviceId;
|
||||
@@ -80,13 +83,21 @@ export function configureInitialDevices() {
|
||||
});
|
||||
|
||||
dispatch(updateSettings(newSettings));
|
||||
resolve();
|
||||
});
|
||||
|
||||
} else {
|
||||
resolve();
|
||||
updateSettingsPromise = Promise.resolve();
|
||||
}
|
||||
});
|
||||
|
||||
return updateSettingsPromise
|
||||
.then(() => {
|
||||
const { audioOutputDeviceId }
|
||||
= getState()['features/base/settings'];
|
||||
|
||||
return setAudioOutputDeviceId(audioOutputDeviceId, dispatch)
|
||||
.catch(ex => logger.warn(`Failed to set audio output device.
|
||||
Default audio output device will be used instead ${ex}`));
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,19 +44,26 @@ export function getAudioOutputDeviceId() {
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @param {string} label - The label.
|
||||
* @param {string} kind - The type of the device. One of "audioInput",
|
||||
* "audioOutput", and "videoInput". Also supported is all lowercase versions
|
||||
* of the preceding types.
|
||||
* @returns {string|undefined}
|
||||
*/
|
||||
export function getDeviceIdByLabel(state: Object, label: string) {
|
||||
const types = [ 'audioInput', 'audioOutput', 'videoInput' ];
|
||||
export function getDeviceIdByLabel(state: Object, label: string, kind: string) {
|
||||
const webrtcKindToJitsiKindTranslator = {
|
||||
audioinput: 'audioInput',
|
||||
audiooutput: 'audioOutput',
|
||||
videoinput: 'videoInput'
|
||||
};
|
||||
|
||||
for (const type of types) {
|
||||
const device
|
||||
= (state['features/base/devices'].availableDevices[type] || [])
|
||||
.find(d => d.label === label);
|
||||
const kindToSearch = webrtcKindToJitsiKindTranslator[kind] || kind;
|
||||
|
||||
if (device) {
|
||||
return device.deviceId;
|
||||
}
|
||||
const device
|
||||
= (state['features/base/devices'].availableDevices[kindToSearch] || [])
|
||||
.find(d => d.label === label);
|
||||
|
||||
if (device) {
|
||||
return device.deviceId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,20 +100,14 @@ export function isFatalJitsiConnectionError(error: Object | string) {
|
||||
* Loads config.js from a specific remote server.
|
||||
*
|
||||
* @param {string} url - The URL to load.
|
||||
* @param {number} [timeout] - The timeout in milliseconds for the {@code url}
|
||||
* to load. If not specified, a default value deemed appropriate for the purpose
|
||||
* is used.
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export function loadConfig(
|
||||
url: string,
|
||||
timeout: ?number = 10 /* seconds */ * 1000 /* in milliseconds */
|
||||
): Promise<Object> {
|
||||
export function loadConfig(url: string): Promise<Object> {
|
||||
let promise;
|
||||
|
||||
if (typeof APP === 'undefined') {
|
||||
promise
|
||||
= loadScript(url, timeout)
|
||||
= loadScript(url, 2.5 * 1000 /* Timeout in ms */)
|
||||
.then(() => {
|
||||
const { config } = window;
|
||||
|
||||
|
||||
@@ -7,6 +7,11 @@ import { ColorPalette } from '../../../styles';
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The color of the spinner.
|
||||
*/
|
||||
color: ?string,
|
||||
|
||||
/**
|
||||
* Prop to set the size of the indicator. This is the same as the
|
||||
* prop of the native component.
|
||||
@@ -27,6 +32,7 @@ export default class LoadingIndicator extends Component<Props> {
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { color = ColorPalette.white } = this.props;
|
||||
let { size = 'large' } = this.props;
|
||||
|
||||
if (size === 'medium') {
|
||||
@@ -35,7 +41,7 @@ export default class LoadingIndicator extends Component<Props> {
|
||||
|
||||
const props = {
|
||||
animating: true,
|
||||
color: ColorPalette.white,
|
||||
color,
|
||||
...this.props,
|
||||
size
|
||||
};
|
||||
@@ -43,7 +49,6 @@ export default class LoadingIndicator extends Component<Props> {
|
||||
return (
|
||||
<ActivityIndicator
|
||||
animating = { true }
|
||||
color = { ColorPalette.white }
|
||||
{ ...props }
|
||||
size = { size } />
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@ import { randomHexString } from 'js-utils/random';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { APP_WILL_MOUNT } from '../app';
|
||||
import JitsiMeetJS, { browser } from '../lib-jitsi-meet';
|
||||
import { browser } from '../lib-jitsi-meet';
|
||||
import { ReducerRegistry } from '../redux';
|
||||
import { PersistenceRegistry } from '../storage';
|
||||
import { assignIfDefined } from '../util';
|
||||
@@ -136,17 +136,6 @@ function _initSettings(featureState) {
|
||||
localFlipX,
|
||||
micDeviceId
|
||||
}, settings);
|
||||
|
||||
if (settings.audioOutputDeviceId
|
||||
!== JitsiMeetJS.mediaDevices.getAudioOutputDevice()) {
|
||||
JitsiMeetJS.mediaDevices.setAudioOutputDevice(
|
||||
settings.audioOutputDeviceId
|
||||
).catch(ex => {
|
||||
logger.warn('Failed to set audio output device from local '
|
||||
+ 'storage. Default audio output device will be used'
|
||||
+ 'instead.', ex);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Things we stored in profile earlier
|
||||
|
||||
@@ -21,6 +21,7 @@ export function maybeShowSuboptimalExperienceNotification(dispatch, t) {
|
||||
&& !browser.isFirefox()
|
||||
&& !browser.isNWJS()
|
||||
&& !browser.isElectron()
|
||||
&& !(browser.isSafariWithVP8() && browser.usesPlanB())
|
||||
|
||||
// Adding react native to the list of recommended browsers is not
|
||||
// necessary for now because the function won't be executed at all
|
||||
|
||||
@@ -42,19 +42,8 @@ class AudioOutputPreview extends Component<Props> {
|
||||
|
||||
this._audioElement = null;
|
||||
|
||||
this._audioElementReady = this._audioElementReady.bind(this);
|
||||
this._onClick = this._onClick.bind(this);
|
||||
this._setAudioElement = this._setAudioElement.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the target output device on the component's audio element after
|
||||
* initial render.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
*/
|
||||
componentDidMount() {
|
||||
this._setAudioSink();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,12 +70,28 @@ class AudioOutputPreview extends Component<Props> {
|
||||
{ this.props.t('deviceSelection.testAudio') }
|
||||
</a>
|
||||
<Audio
|
||||
setRef = { this._setAudioElement }
|
||||
setRef = { this._audioElementReady }
|
||||
src = { TEST_SOUND_PATH } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_audioElementReady: (Object) => void;
|
||||
|
||||
/**
|
||||
* Sets the instance variable for the component's audio element so it can be
|
||||
* accessed directly.
|
||||
*
|
||||
* @param {Object} element - The DOM element for the component's audio.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_audioElementReady(element: Object) {
|
||||
this._audioElement = element;
|
||||
|
||||
this._setAudioSink();
|
||||
}
|
||||
|
||||
_onClick: () => void;
|
||||
|
||||
/**
|
||||
@@ -97,21 +102,7 @@ class AudioOutputPreview extends Component<Props> {
|
||||
*/
|
||||
_onClick() {
|
||||
this._audioElement
|
||||
&& this._audioElement.play();
|
||||
}
|
||||
|
||||
_setAudioElement: (Object) => void;
|
||||
|
||||
/**
|
||||
* Sets the instance variable for the component's audio element so it can be
|
||||
* accessed directly.
|
||||
*
|
||||
* @param {Object} element - The DOM element for the component's audio.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_setAudioElement(element: Object) {
|
||||
this._audioElement = element;
|
||||
&& this._audioElement.play();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +113,7 @@ class AudioOutputPreview extends Component<Props> {
|
||||
*/
|
||||
_setAudioSink() {
|
||||
this._audioElement
|
||||
&& this._audioElement.setSinkId(this.props.deviceId);
|
||||
&& this._audioElement.setSinkId(this.props.deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,31 +82,36 @@ export function processExternalDeviceRequest( // eslint-disable-line max-params
|
||||
case 'getCurrentDevices':
|
||||
dispatch(getAvailableDevices()).then(devices => {
|
||||
if (areDeviceLabelsInitialized(state)) {
|
||||
let audioInput, audioOutput, videoInput;
|
||||
const audioOutputDeviceId = getAudioOutputDeviceId();
|
||||
const { cameraDeviceId, micDeviceId } = settings;
|
||||
const deviceDescriptions = {
|
||||
audioInput: undefined,
|
||||
audioOutput: undefined,
|
||||
videoInput: undefined
|
||||
};
|
||||
const currentlyUsedDeviceIds = new Set([
|
||||
getAudioOutputDeviceId(),
|
||||
settings.micDeviceId,
|
||||
settings.cameraDeviceId
|
||||
]);
|
||||
|
||||
devices.forEach(device => {
|
||||
const { deviceId } = device;
|
||||
const { deviceId, kind } = device;
|
||||
|
||||
switch (deviceId) {
|
||||
case micDeviceId:
|
||||
audioInput = device;
|
||||
break;
|
||||
case audioOutputDeviceId:
|
||||
audioOutput = device;
|
||||
break;
|
||||
case cameraDeviceId:
|
||||
videoInput = device;
|
||||
break;
|
||||
if (currentlyUsedDeviceIds.has(deviceId)) {
|
||||
switch (kind) {
|
||||
case 'audioinput':
|
||||
deviceDescriptions.audioInput = device;
|
||||
break;
|
||||
case 'audiooutput':
|
||||
deviceDescriptions.audioOutput = device;
|
||||
break;
|
||||
case 'videoinput':
|
||||
deviceDescriptions.videoInput = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
responseCallback({
|
||||
audioInput,
|
||||
audioOutput,
|
||||
videoInput
|
||||
});
|
||||
responseCallback(deviceDescriptions);
|
||||
} else {
|
||||
// The labels are not available if the A/V permissions are
|
||||
// not yet granted.
|
||||
@@ -150,7 +155,9 @@ export function processExternalDeviceRequest( // eslint-disable-line max-params
|
||||
}
|
||||
|
||||
const { label, id } = device;
|
||||
const deviceId = label ? getDeviceIdByLabel(state, device.label) : id;
|
||||
const deviceId = label
|
||||
? getDeviceIdByLabel(state, device.label, device.kind)
|
||||
: id;
|
||||
|
||||
if (deviceId) {
|
||||
switch (device.kind) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// @flow
|
||||
|
||||
/**
|
||||
* The type of the Redux action which signals that the prompt for media
|
||||
* permission is visible or not.
|
||||
@@ -12,16 +14,6 @@
|
||||
export const MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED
|
||||
= 'MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED';
|
||||
|
||||
/**
|
||||
* The type of the Redux action which signals that a suspend was detected.
|
||||
*
|
||||
* {
|
||||
* type: SUSPEND_DETECTED
|
||||
* }
|
||||
* @public
|
||||
*/
|
||||
export const SUSPEND_DETECTED = 'SUSPEND_DETECTED';
|
||||
|
||||
/**
|
||||
* Adjust the state of the fatal error which shows/hides the reload screen. See
|
||||
* action methods's description for more info about each of the fields.
|
||||
@@ -33,3 +25,13 @@ export const SUSPEND_DETECTED = 'SUSPEND_DETECTED';
|
||||
* @public
|
||||
*/
|
||||
export const SET_FATAL_ERROR = 'SET_FATAL_ERROR';
|
||||
|
||||
/**
|
||||
* The type of the Redux action which signals that a suspend was detected.
|
||||
*
|
||||
* {
|
||||
* type: SUSPEND_DETECTED
|
||||
* }
|
||||
* @public
|
||||
*/
|
||||
export const SUSPEND_DETECTED = 'SUSPEND_DETECTED';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED,
|
||||
SET_FATAL_ERROR,
|
||||
@@ -17,7 +19,7 @@ import {
|
||||
* isVisible: {boolean}
|
||||
* }}
|
||||
*/
|
||||
export function mediaPermissionPromptVisibilityChanged(isVisible, browser) {
|
||||
export function mediaPermissionPromptVisibilityChanged(isVisible: boolean, browser: string) {
|
||||
return {
|
||||
type: MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED,
|
||||
browser,
|
||||
@@ -51,7 +53,7 @@ export function suspendDetected() {
|
||||
* fatalError: ?Error
|
||||
* }}
|
||||
*/
|
||||
export function setFatalError(fatalError) {
|
||||
export function setFatalError(fatalError: Object) {
|
||||
return {
|
||||
type: SET_FATAL_ERROR,
|
||||
fatalError
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
isFatalJitsiConnectionError
|
||||
} from '../../base/lib-jitsi-meet';
|
||||
|
||||
import ReloadButton from './ReloadButton';
|
||||
import ReloadButton from './web/ReloadButton';
|
||||
|
||||
declare var APP: Object;
|
||||
|
||||
@@ -82,6 +82,8 @@ type State = {
|
||||
|
||||
/**
|
||||
* Implements an abstract React {@link Component} for the page reload overlays.
|
||||
*
|
||||
* FIXME: This is not really an abstract class as some components and functions are very web specific.
|
||||
*/
|
||||
export default class AbstractPageReloadOverlay<P: Props>
|
||||
extends Component<P, State> {
|
||||
|
||||
3
react/features/overlay/components/_.native.js
Normal file
3
react/features/overlay/components/_.native.js
Normal file
@@ -0,0 +1,3 @@
|
||||
// @flow
|
||||
|
||||
export * from './native';
|
||||
3
react/features/overlay/components/_.web.js
Normal file
3
react/features/overlay/components/_.web.js
Normal file
@@ -0,0 +1,3 @@
|
||||
// @flow
|
||||
|
||||
export * from './web';
|
||||
@@ -1,15 +1,4 @@
|
||||
// @flow
|
||||
|
||||
export { default as OverlayContainer } from './OverlayContainer';
|
||||
export {
|
||||
default as PageReloadFilmstripOnlyOverlay
|
||||
} from './PageReloadFilmstripOnlyOverlay';
|
||||
export { default as PageReloadOverlay } from './PageReloadOverlay';
|
||||
export {
|
||||
default as SuspendedFilmstripOnlyOverlay
|
||||
} from './SuspendedFilmstripOnlyOverlay';
|
||||
export { default as SuspendedOverlay } from './SuspendedOverlay';
|
||||
export {
|
||||
default as UserMediaPermissionsFilmstripOnlyOverlay
|
||||
} from './UserMediaPermissionsFilmstripOnlyOverlay';
|
||||
export {
|
||||
default as UserMediaPermissionsOverlay
|
||||
} from './UserMediaPermissionsOverlay';
|
||||
export * from './_';
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { SafeAreaView, Text } from 'react-native';
|
||||
|
||||
import { ColorSchemeRegistry } from '../../../base/color-scheme';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { LoadingIndicator } from '../../../base/react';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { StyleType } from '../../../base/styles';
|
||||
|
||||
import OverlayFrame from './OverlayFrame';
|
||||
import styles from './styles';
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* The color schemed style of the component.
|
||||
*/
|
||||
_styles: StyleType,
|
||||
|
||||
/**
|
||||
* The Function to be invoked to translate i18n keys.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements an overlay to tell the user that there is an operation in progress in the background during connect
|
||||
* so then the app doesn't seem hung.
|
||||
*/
|
||||
class LoadConfigOverlay extends Component<Props> {
|
||||
/**
|
||||
* Determines whether this overlay needs to be rendered (according to a
|
||||
* specific redux state). Called by {@link OverlayContainer}.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @returns {boolean} - If this overlay needs to be rendered, {@code true};
|
||||
* {@code false}, otherwise.
|
||||
*/
|
||||
static needsRender(state: Object) {
|
||||
return Boolean(state['features/overlay'].loadConfigOverlayVisible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { _styles } = this.props;
|
||||
|
||||
return (
|
||||
<OverlayFrame>
|
||||
<SafeAreaView
|
||||
style = { [
|
||||
styles.loadingOverlayWrapper,
|
||||
_styles.loadingOverlayWrapper
|
||||
] }>
|
||||
<LoadingIndicator
|
||||
color = { _styles.indicatorColor }
|
||||
size = 'large'
|
||||
style = { styles.connectIndicator } />
|
||||
<Text
|
||||
style = { [
|
||||
styles.loadingOverlayText,
|
||||
_styles.loadingOverlayText
|
||||
] }>
|
||||
{ this.props.t('connectingOverlay.joiningRoom') }
|
||||
</Text>
|
||||
</SafeAreaView>
|
||||
</OverlayFrame>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps part of the Redux state to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @returns {{
|
||||
* _styles: StyleType
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
return {
|
||||
_styles: ColorSchemeRegistry.get(state, 'LoadConfigOverlay')
|
||||
};
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps)(LoadConfigOverlay));
|
||||
@@ -3,7 +3,7 @@
|
||||
import React, { Component, type Node } from 'react';
|
||||
import { SafeAreaView, View } from 'react-native';
|
||||
|
||||
import { overlayFrame as styles } from './styles';
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@code OverlayFrame}.
|
||||
@@ -3,18 +3,20 @@
|
||||
import React from 'react';
|
||||
import { Text } from 'react-native';
|
||||
|
||||
import { appNavigate, reloadNow } from '../../app';
|
||||
import { ColorSchemeRegistry } from '../../base/color-scheme';
|
||||
import { ConfirmDialog } from '../../base/dialog';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { connect } from '../../base/redux';
|
||||
import { StyleType } from '../../base/styles';
|
||||
import { appNavigate, reloadNow } from '../../../app';
|
||||
import { ColorSchemeRegistry } from '../../../base/color-scheme';
|
||||
import { ConfirmDialog } from '../../../base/dialog';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { StyleType } from '../../../base/styles';
|
||||
|
||||
import { setFatalError } from '../../actions';
|
||||
|
||||
import AbstractPageReloadOverlay, {
|
||||
abstractMapStateToProps,
|
||||
type Props as AbstractProps
|
||||
} from './AbstractPageReloadOverlay';
|
||||
import { setFatalError } from '../actions';
|
||||
} from '../AbstractPageReloadOverlay';
|
||||
|
||||
import OverlayFrame from './OverlayFrame';
|
||||
|
||||
type Props = AbstractProps & {
|
||||
5
react/features/overlay/components/native/index.js
Normal file
5
react/features/overlay/components/native/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// @flow
|
||||
|
||||
export { default as LoadConfigOverlay } from './LoadConfigOverlay';
|
||||
export { default as OverlayFrame } from './OverlayFrame';
|
||||
export { default as PageReloadOverlay } from './PageReloadOverlay';
|
||||
54
react/features/overlay/components/native/styles.js
Normal file
54
react/features/overlay/components/native/styles.js
Normal file
@@ -0,0 +1,54 @@
|
||||
// @flow
|
||||
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { ColorSchemeRegistry, schemeColor } from '../../../base/color-scheme';
|
||||
import { BoxModel, ColorPalette } from '../../../base/styles';
|
||||
|
||||
/**
|
||||
* The React {@code Component} styles of the overlay feature.
|
||||
*/
|
||||
export default {
|
||||
connectIndicator: {
|
||||
margin: BoxModel.margin
|
||||
},
|
||||
|
||||
/**
|
||||
* Style for a backdrop overlay covering the screen the the overlay is
|
||||
* rendered.
|
||||
*/
|
||||
container: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
backgroundColor: ColorPalette.black
|
||||
},
|
||||
|
||||
loadingOverlayText: {
|
||||
color: ColorPalette.white
|
||||
},
|
||||
|
||||
loadingOverlayWrapper: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
|
||||
safeContainer: {
|
||||
flex: 1
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Color schemed styles for all the component based on the abstract dialog.
|
||||
*/
|
||||
ColorSchemeRegistry.register('LoadConfigOverlay', {
|
||||
indicatorColor: schemeColor('text'),
|
||||
|
||||
loadingOverlayText: {
|
||||
color: schemeColor('text')
|
||||
},
|
||||
|
||||
loadingOverlayWrapper: {
|
||||
backgroundColor: schemeColor('background')
|
||||
}
|
||||
});
|
||||
@@ -1,21 +0,0 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { ColorPalette, createStyleSheet } from '../../base/styles';
|
||||
|
||||
/**
|
||||
* The React {@code Component} styles of {@code OverlayFrame}.
|
||||
*/
|
||||
export const overlayFrame = createStyleSheet({
|
||||
/**
|
||||
* Style for a backdrop overlay covering the screen the the overlay is
|
||||
* rendered.
|
||||
*/
|
||||
container: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
backgroundColor: ColorPalette.black
|
||||
},
|
||||
|
||||
safeContainer: {
|
||||
flex: 1
|
||||
}
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
/* @flow */
|
||||
// @flow
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* @flow */
|
||||
// @flow
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
Avatar,
|
||||
getAvatarURL,
|
||||
getLocalParticipant
|
||||
} from '../../base/participants';
|
||||
import { connect } from '../../base/redux';
|
||||
} from '../../../base/participants';
|
||||
import { connect } from '../../../base/redux';
|
||||
|
||||
import OverlayFrame from './OverlayFrame';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* @flow */
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { connect } from '../../base/redux';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { connect } from '../../../base/redux';
|
||||
|
||||
import AbstractPageReloadOverlay, { type Props, abstractMapStateToProps }
|
||||
from '../AbstractPageReloadOverlay';
|
||||
|
||||
import AbstractPageReloadOverlay, { abstractMapStateToProps }
|
||||
from './AbstractPageReloadOverlay';
|
||||
import FilmstripOnlyOverlayFrame from './FilmstripOnlyOverlayFrame';
|
||||
|
||||
/**
|
||||
@@ -12,7 +15,7 @@ import FilmstripOnlyOverlayFrame from './FilmstripOnlyOverlayFrame';
|
||||
* mode. Shown before the conference is reloaded. Shows a warning message and
|
||||
* counts down towards the reload.
|
||||
*/
|
||||
class PageReloadFilmstripOnlyOverlay extends AbstractPageReloadOverlay {
|
||||
class PageReloadFilmstripOnlyOverlay extends AbstractPageReloadOverlay<Props> {
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
@@ -38,6 +41,10 @@ class PageReloadFilmstripOnlyOverlay extends AbstractPageReloadOverlay {
|
||||
</FilmstripOnlyOverlayFrame>
|
||||
);
|
||||
}
|
||||
|
||||
_renderButton: () => React$Element<*> | null
|
||||
|
||||
_renderProgressBar: () => React$Element<*> | null
|
||||
}
|
||||
|
||||
export default translate(
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { translate } from '../../base/i18n';
|
||||
import { connect } from '../../base/redux';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { connect } from '../../../base/redux';
|
||||
|
||||
import AbstractPageReloadOverlay, {
|
||||
abstractMapStateToProps,
|
||||
type Props
|
||||
} from './AbstractPageReloadOverlay';
|
||||
} from '../AbstractPageReloadOverlay';
|
||||
|
||||
import OverlayFrame from './OverlayFrame';
|
||||
|
||||
/**
|
||||
@@ -1,10 +1,10 @@
|
||||
/* @flow */
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { reloadNow } from '../../app';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { connect } from '../../base/redux';
|
||||
import { reloadNow } from '../../../app';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { connect } from '../../../base/redux';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link ReloadButton}.
|
||||
@@ -1,6 +1,8 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { translate, translateToHTML } from '../../base/i18n';
|
||||
import { translate, translateToHTML } from '../../../base/i18n';
|
||||
|
||||
import AbstractSuspendedOverlay from './AbstractSuspendedOverlay';
|
||||
import FilmstripOnlyOverlayFrame from './FilmstripOnlyOverlayFrame';
|
||||
@@ -1,6 +1,8 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { translate, translateToHTML } from '../../base/i18n';
|
||||
import { translate, translateToHTML } from '../../../base/i18n';
|
||||
|
||||
import AbstractSuspendedOverlay from './AbstractSuspendedOverlay';
|
||||
import OverlayFrame from './OverlayFrame';
|
||||
@@ -1,7 +1,9 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { translate, translateToHTML } from '../../base/i18n';
|
||||
import { connect } from '../../base/redux';
|
||||
import { translate, translateToHTML } from '../../../base/i18n';
|
||||
import { connect } from '../../../base/redux';
|
||||
|
||||
import AbstractUserMediaPermissionsOverlay, { abstractMapStateToProps }
|
||||
from './AbstractUserMediaPermissionsOverlay';
|
||||
@@ -1,39 +1,21 @@
|
||||
/* global interfaceConfig */
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { translate, translateToHTML } from '../../base/i18n';
|
||||
import { connect } from '../../base/redux';
|
||||
import { translate, translateToHTML } from '../../../base/i18n';
|
||||
import { connect } from '../../../base/redux';
|
||||
|
||||
import AbstractUserMediaPermissionsOverlay, { abstractMapStateToProps }
|
||||
from './AbstractUserMediaPermissionsOverlay';
|
||||
import OverlayFrame from './OverlayFrame';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* Implements a React Component for overlay with guidance how to proceed with
|
||||
* gUM prompt.
|
||||
*/
|
||||
class UserMediaPermissionsOverlay extends AbstractUserMediaPermissionsOverlay {
|
||||
/**
|
||||
* Initializes a new UserMediaPermissionsOverlay instance.
|
||||
*
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
* @public
|
||||
*/
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
/**
|
||||
* The src value of the image for the policy logo.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
policyLogoSrc: interfaceConfig.POLICY_LOGO
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
@@ -80,7 +62,7 @@ class UserMediaPermissionsOverlay extends AbstractUserMediaPermissionsOverlay {
|
||||
* @returns {ReactElement|null}
|
||||
*/
|
||||
_renderPolicyLogo() {
|
||||
const { policyLogoSrc } = this.state;
|
||||
const policyLogoSrc = interfaceConfig.POLICY_LOGO;
|
||||
|
||||
if (policyLogoSrc) {
|
||||
return (
|
||||
19
react/features/overlay/components/web/index.js
Normal file
19
react/features/overlay/components/web/index.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// @flow
|
||||
|
||||
export { default as FilmstripOnlyOverlayFrame } from './FilmstripOnlyOverlayFrame';
|
||||
export { default as OverlayFrame } from './OverlayFrame';
|
||||
|
||||
export {
|
||||
default as PageReloadFilmstripOnlyOverlay
|
||||
} from './PageReloadFilmstripOnlyOverlay';
|
||||
export { default as PageReloadOverlay } from './PageReloadOverlay';
|
||||
export {
|
||||
default as SuspendedFilmstripOnlyOverlay
|
||||
} from './SuspendedFilmstripOnlyOverlay';
|
||||
export { default as SuspendedOverlay } from './SuspendedOverlay';
|
||||
export {
|
||||
default as UserMediaPermissionsFilmstripOnlyOverlay
|
||||
} from './UserMediaPermissionsFilmstripOnlyOverlay';
|
||||
export {
|
||||
default as UserMediaPermissionsOverlay
|
||||
} from './UserMediaPermissionsOverlay';
|
||||
@@ -1,49 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
PageReloadFilmstripOnlyOverlay,
|
||||
PageReloadOverlay,
|
||||
SuspendedFilmstripOnlyOverlay,
|
||||
SuspendedOverlay,
|
||||
UserMediaPermissionsFilmstripOnlyOverlay,
|
||||
UserMediaPermissionsOverlay
|
||||
} from './components';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* Returns the list of available overlays that might be rendered.
|
||||
*
|
||||
* @private
|
||||
* @returns {Array<?React$ComponentType<*>>}
|
||||
*/
|
||||
function _getOverlays() {
|
||||
const filmstripOnly
|
||||
= typeof interfaceConfig === 'object' && interfaceConfig.filmStripOnly;
|
||||
let overlays;
|
||||
|
||||
if (filmstripOnly) {
|
||||
overlays = [
|
||||
PageReloadFilmstripOnlyOverlay,
|
||||
SuspendedFilmstripOnlyOverlay,
|
||||
UserMediaPermissionsFilmstripOnlyOverlay
|
||||
];
|
||||
} else {
|
||||
overlays = [
|
||||
PageReloadOverlay
|
||||
];
|
||||
}
|
||||
|
||||
// Mobile only has a PageReloadOverlay.
|
||||
if (navigator.product !== 'ReactNative') {
|
||||
overlays.push(...[
|
||||
SuspendedOverlay,
|
||||
UserMediaPermissionsOverlay
|
||||
]);
|
||||
}
|
||||
|
||||
return overlays;
|
||||
}
|
||||
import { getOverlays } from './overlays';
|
||||
|
||||
/**
|
||||
* Returns the overlay to be currently rendered.
|
||||
@@ -52,7 +9,7 @@ function _getOverlays() {
|
||||
* @returns {?React$ComponentType<*>}
|
||||
*/
|
||||
export function getOverlayToRender(state: Object) {
|
||||
for (const overlay of _getOverlays()) {
|
||||
for (const overlay of getOverlays()) {
|
||||
// react-i18n / react-redux wrap components and thus we cannot access
|
||||
// the wrapped component's static methods directly.
|
||||
const component = overlay.WrappedComponent || overlay;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// @flow
|
||||
|
||||
export * from './actions';
|
||||
export * from './components';
|
||||
export * from './functions';
|
||||
|
||||
18
react/features/overlay/overlays.native.js
Normal file
18
react/features/overlay/overlays.native.js
Normal file
@@ -0,0 +1,18 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
LoadConfigOverlay,
|
||||
PageReloadOverlay
|
||||
} from './components/native';
|
||||
|
||||
/**
|
||||
* Returns the list of available platform specific overlays.
|
||||
*
|
||||
* @returns {Array<React$Element>}
|
||||
*/
|
||||
export function getOverlays(): Array<React$Element<*>> {
|
||||
return [
|
||||
LoadConfigOverlay,
|
||||
PageReloadOverlay
|
||||
];
|
||||
}
|
||||
38
react/features/overlay/overlays.web.js
Normal file
38
react/features/overlay/overlays.web.js
Normal file
@@ -0,0 +1,38 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
PageReloadFilmstripOnlyOverlay,
|
||||
PageReloadOverlay,
|
||||
SuspendedFilmstripOnlyOverlay,
|
||||
SuspendedOverlay,
|
||||
UserMediaPermissionsFilmstripOnlyOverlay,
|
||||
UserMediaPermissionsOverlay
|
||||
} from './components/web';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* Returns the list of available platform specific overlays.
|
||||
*
|
||||
* @returns {Array<Object>}
|
||||
*/
|
||||
export function getOverlays(): Array<Object> {
|
||||
const overlays = [
|
||||
SuspendedOverlay,
|
||||
UserMediaPermissionsOverlay
|
||||
];
|
||||
|
||||
const filmstripOnly
|
||||
= typeof interfaceConfig === 'object' && interfaceConfig.filmStripOnly;
|
||||
|
||||
if (filmstripOnly) {
|
||||
overlays.push(
|
||||
PageReloadFilmstripOnlyOverlay,
|
||||
SuspendedFilmstripOnlyOverlay,
|
||||
UserMediaPermissionsFilmstripOnlyOverlay);
|
||||
} else {
|
||||
overlays.push(PageReloadOverlay);
|
||||
}
|
||||
|
||||
return overlays;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import { CONFIG_WILL_LOAD, LOAD_CONFIG_ERROR, SET_CONFIG } from '../base/config';
|
||||
import { assign, ReducerRegistry, set } from '../base/redux';
|
||||
|
||||
import {
|
||||
@@ -15,6 +16,13 @@ import {
|
||||
*/
|
||||
ReducerRegistry.register('features/overlay', (state = { }, action) => {
|
||||
switch (action.type) {
|
||||
case CONFIG_WILL_LOAD:
|
||||
return _setShowLoadConfigOverlay(state, Boolean(action.room));
|
||||
|
||||
case LOAD_CONFIG_ERROR:
|
||||
case SET_CONFIG:
|
||||
return _setShowLoadConfigOverlay(false);
|
||||
|
||||
case MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED:
|
||||
return _mediaPermissionPromptVisibilityChanged(state, action);
|
||||
|
||||
@@ -48,15 +56,15 @@ function _mediaPermissionPromptVisibilityChanged(
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces a specific redux action SUSPEND_DETECTED of the feature overlay.
|
||||
* Sets the {@code LoadConfigOverlay} overlay visible or not.
|
||||
*
|
||||
* @param {Object} state - The redux state of the feature overlay.
|
||||
* @private
|
||||
* @param {boolean} show - Whether to show or not the overlay.
|
||||
* @returns {Object} The new state of the feature overlay after the reduction of
|
||||
* the specified action.
|
||||
*/
|
||||
function _suspendDetected(state) {
|
||||
return set(state, 'suspendDetected', true);
|
||||
function _setShowLoadConfigOverlay(state, show) {
|
||||
return set(state, 'loadConfigOverlayVisible', show);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,3 +80,15 @@ function _suspendDetected(state) {
|
||||
function _setFatalError(state, { fatalError }) {
|
||||
return set(state, 'fatalError', fatalError);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces a specific redux action SUSPEND_DETECTED of the feature overlay.
|
||||
*
|
||||
* @param {Object} state - The redux state of the feature overlay.
|
||||
* @private
|
||||
* @returns {Object} The new state of the feature overlay after the reduction of
|
||||
* the specified action.
|
||||
*/
|
||||
function _suspendDetected(state) {
|
||||
return set(state, 'suspendDetected', true);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ export const SET_TOOLBOX_TIMEOUT = 'SET_TOOLBOX_TIMEOUT';
|
||||
* timeoutMS: number
|
||||
* }
|
||||
*/
|
||||
export const SET_TOOLBOX_TIMEOUT_MS = 'SET_TOOLBOX_TIMEOUT';
|
||||
export const SET_TOOLBOX_TIMEOUT_MS = 'SET_TOOLBOX_TIMEOUT_MS';
|
||||
|
||||
/**
|
||||
* The type of the (redux) action which shows/hides the Toolbox.
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
/**
|
||||
* The type of the action which sets the list of known participant IDs which
|
||||
* have an active screen share.
|
||||
*
|
||||
* @returns {{
|
||||
* type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
|
||||
* participantIds: Array<string>
|
||||
* }}
|
||||
*/
|
||||
export const SCREEN_SHARE_PARTICIPANTS_UPDATED
|
||||
= 'SCREEN_SHARE_PARTICIPANTS_UPDATED';
|
||||
|
||||
/**
|
||||
* The type of the action which enables or disables the feature for showing
|
||||
* video thumbnails in a two-axis tile view.
|
||||
|
||||
@@ -1,6 +1,27 @@
|
||||
// @flow
|
||||
|
||||
import { SET_TILE_VIEW } from './actionTypes';
|
||||
import {
|
||||
SCREEN_SHARE_PARTICIPANTS_UPDATED,
|
||||
SET_TILE_VIEW
|
||||
} from './actionTypes';
|
||||
|
||||
/**
|
||||
* Creates a (redux) action which signals that the list of known participants
|
||||
* with screen shares has changed.
|
||||
*
|
||||
* @param {string} participantIds - The participants which currently have active
|
||||
* screen share streams.
|
||||
* @returns {{
|
||||
* type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
|
||||
* participantId: string
|
||||
* }}
|
||||
*/
|
||||
export function setParticipantsWithScreenShare(participantIds: Array<string>) {
|
||||
return {
|
||||
type: SCREEN_SHARE_PARTICIPANTS_UPDATED,
|
||||
participantIds
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a (redux) action which signals to set the UI layout to be tiled view
|
||||
|
||||
@@ -3,14 +3,30 @@
|
||||
import { ReducerRegistry } from '../base/redux';
|
||||
import { PersistenceRegistry } from '../base/storage';
|
||||
|
||||
import { SET_TILE_VIEW } from './actionTypes';
|
||||
import {
|
||||
SCREEN_SHARE_PARTICIPANTS_UPDATED,
|
||||
SET_TILE_VIEW
|
||||
} from './actionTypes';
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
screenShares: []
|
||||
};
|
||||
|
||||
const STORE_NAME = 'features/video-layout';
|
||||
|
||||
PersistenceRegistry.register(STORE_NAME);
|
||||
PersistenceRegistry.register(STORE_NAME, {
|
||||
tileViewEnabled: true
|
||||
});
|
||||
|
||||
ReducerRegistry.register(STORE_NAME, (state = {}, action) => {
|
||||
ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case SCREEN_SHARE_PARTICIPANTS_UPDATED: {
|
||||
return {
|
||||
...state,
|
||||
screenShares: action.participantIds
|
||||
};
|
||||
}
|
||||
|
||||
case SET_TILE_VIEW:
|
||||
return {
|
||||
...state,
|
||||
|
||||
@@ -4,9 +4,16 @@ import {
|
||||
VIDEO_QUALITY_LEVELS,
|
||||
setMaxReceiverVideoQuality
|
||||
} from '../base/conference';
|
||||
import { StateListenerRegistry } from '../base/redux';
|
||||
import {
|
||||
getPinnedParticipant,
|
||||
pinParticipant
|
||||
} from '../base/participants';
|
||||
import { StateListenerRegistry, equals } from '../base/redux';
|
||||
import { selectParticipant } from '../large-video';
|
||||
import { shouldDisplayTileView } from './functions';
|
||||
import { setParticipantsWithScreenShare } from './actions';
|
||||
|
||||
declare var interfaceConfig: Object;
|
||||
|
||||
/**
|
||||
* StateListenerRegistry provides a reliable way of detecting changes to
|
||||
@@ -14,11 +21,89 @@ import { shouldDisplayTileView } from './functions';
|
||||
*/
|
||||
StateListenerRegistry.register(
|
||||
/* selector */ state => shouldDisplayTileView(state),
|
||||
/* listener */ (displayTileView, { dispatch }) => {
|
||||
/* listener */ (displayTileView, store) => {
|
||||
const { dispatch } = store;
|
||||
|
||||
dispatch(selectParticipant());
|
||||
|
||||
if (!displayTileView) {
|
||||
dispatch(setMaxReceiverVideoQuality(VIDEO_QUALITY_LEVELS.HIGH));
|
||||
dispatch(
|
||||
setMaxReceiverVideoQuality(VIDEO_QUALITY_LEVELS.HIGH));
|
||||
|
||||
if (typeof interfaceConfig === 'object'
|
||||
&& interfaceConfig.AUTO_PIN_LATEST_SCREEN_SHARE) {
|
||||
_updateAutoPinnedParticipant(store);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* For auto-pin mode, listen for changes to the known media tracks and look
|
||||
* for updates to screen shares.
|
||||
*/
|
||||
StateListenerRegistry.register(
|
||||
/* selector */ state => state['features/base/tracks'],
|
||||
/* listener */ (tracks, store) => {
|
||||
if (typeof interfaceConfig !== 'object'
|
||||
|| !interfaceConfig.AUTO_PIN_LATEST_SCREEN_SHARE) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldScreenSharesOrder
|
||||
= store.getState()['features/video-layout'].screenShares || [];
|
||||
const knownSharingParticipantIds = tracks.reduce((acc, track) => {
|
||||
if (track.mediaType === 'video' && track.videoType === 'desktop') {
|
||||
acc.push(track.participantId);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
// Filter out any participants which are no longer screen sharing
|
||||
// by looping through the known sharing participants and removing any
|
||||
// participant IDs which are no longer sharing.
|
||||
const newScreenSharesOrder = oldScreenSharesOrder.filter(
|
||||
participantId => knownSharingParticipantIds.includes(participantId));
|
||||
|
||||
// Make sure all new sharing participant get added to the end of the
|
||||
// known screen shares.
|
||||
knownSharingParticipantIds.forEach(participantId => {
|
||||
if (!newScreenSharesOrder.includes(participantId)) {
|
||||
newScreenSharesOrder.push(participantId);
|
||||
}
|
||||
});
|
||||
|
||||
if (!equals(oldScreenSharesOrder, newScreenSharesOrder)) {
|
||||
store.dispatch(
|
||||
setParticipantsWithScreenShare(newScreenSharesOrder));
|
||||
|
||||
_updateAutoPinnedParticipant(store);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Private helper to automatically pin the latest screen share stream or unpin
|
||||
* if there are no more screen share streams.
|
||||
*
|
||||
* @param {Store} store - The redux store.
|
||||
* @returns {void}
|
||||
*/
|
||||
function _updateAutoPinnedParticipant({ dispatch, getState }) {
|
||||
const state = getState();
|
||||
const screenShares = state['features/video-layout'].screenShares;
|
||||
|
||||
if (!screenShares) {
|
||||
return;
|
||||
}
|
||||
|
||||
const latestScreenshareParticipantId
|
||||
= screenShares[screenShares.length - 1];
|
||||
|
||||
if (latestScreenshareParticipantId) {
|
||||
dispatch(pinParticipant(latestScreenshareParticipantId));
|
||||
} else if (getPinnedParticipant(state['features/base/participants'])) {
|
||||
dispatch(pinParticipant(null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
--- /usr/lib/prosody/modules/mod_bosh.lua 2015-12-16 14:28:34.000000000 -0600
|
||||
+++ /usr/lib/prosody/modules/mod_bosh.lua 2015-12-22 10:45:59.818197967 -0600
|
||||
@@ -294,6 +294,9 @@
|
||||
|
||||
session.log("debug", "BOSH session created for request from %s", session.ip);
|
||||
log("info", "New BOSH session, assigned it sid '%s'", sid);
|
||||
+
|
||||
+ hosts[session.host].events.fire_event(
|
||||
+ "bosh-session", { session = session, request = request });
|
||||
|
||||
-- Send creation response
|
||||
local creating_session = true;
|
||||
@@ -56,7 +56,20 @@ const config = {
|
||||
|
||||
// Tell babel to avoid compiling imports into CommonJS
|
||||
// so that webpack may do tree shaking.
|
||||
{ modules: false }
|
||||
{
|
||||
modules: false,
|
||||
|
||||
// Specify our target browsers so no transpiling is
|
||||
// done unnecessarily. For browsers not specified
|
||||
// here, the ES2015+ profile will be used.
|
||||
targets: {
|
||||
chrome: 58,
|
||||
electron: 2,
|
||||
firefox: 54,
|
||||
safari: 11
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
require.resolve('@babel/preset-flow'),
|
||||
require.resolve('@babel/preset-react')
|
||||
|
||||
Reference in New Issue
Block a user